Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 16 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ Search OperatorHub for "pattern" and accept all the defaults
## Create the Multi-Cloud GitOps pattern

```
kubectl create -f config/samples/gitops_v1alpha1_pattern.yaml
oc create -f config/samples/gitops_v1alpha1_pattern.yaml
```

### Check the status

```
kubectl get -f config/samples/gitops_v1alpha1_pattern.yaml -o yaml
oc get -f config/samples/gitops_v1alpha1_pattern.yaml -o yaml
oc get applications -A -w
```

Expand All @@ -36,21 +36,27 @@ secret and then add the secrets via the UI (this approach is a bit more work)
### Delete the pattern

```
kubectl delete -f config/samples/gitops_v1alpha1_pattern.yaml
oc delete -f config/samples/gitops_v1alpha1_pattern.yaml
```

This will only remove the top-level application.
The subscription and anything created by Argo will not be removed and canmust be removed manually.
Removing the top-level application ensures that Argo won't try to put back anything you delete.
This action removes the `Pattern` instance only.

## Watch the logs

When installing via UI the namespace will be `patterns-operator` (recommended)
If you annotate the Pattern instance with `patterns.gitops.hybrid-cloud-patterns.io/prune: "true"`:

```
oc logs -n patterns-operator `oc get -n patterns-operator pods -o name --field-selector status.phase=Running | grep patterns` -c manager -f
oc annotate -f config/samples/gitops_v1alpha1_pattern.yaml patterns.gitops.hybrid-cloud-patterns.io/prune='true'
```

Once the `Pattern` instance is deleted, the following resources will also be removed:

- The top-level application of the hub cluster.
- The child applications of the hub cluster.
- The top-level application of the spoke clusters.
- The child applications of the spoke clusters.
- The `ManagedCluster` instances (excluding the `local-cluster`).

**NOTE:** The GitOps Operator `Subscription` and the main `ArgoCD` instance will not be removed and must be removed manually.

## Development

### Test your changes locally against a remote cluster
Expand Down
70 changes: 1 addition & 69 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,10 @@ import (
// to ensure that exec-entrypoint and run can make use of them.
_ "k8s.io/client-go/plugin/pkg/client/auth"

"k8s.io/apimachinery/pkg/api/errors"
k8sruntime "k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
ctrl "sigs.k8s.io/controller-runtime"
crclient "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/healthz"
"sigs.k8s.io/controller-runtime/pkg/log/zap"
"sigs.k8s.io/controller-runtime/pkg/manager"
Expand All @@ -46,9 +44,6 @@ import (
"github.com/hybrid-cloud-patterns/patterns-operator/version"
consolev1 "github.com/openshift/api/console/v1"
operatorv1 "github.com/openshift/api/operator/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/kubernetes"
//+kubebuilder:scaffold:imports
)

Expand Down Expand Up @@ -85,12 +80,6 @@ func main() {

setupLog.Info("detected operator namespace", "namespace", controllers.DetectOperatorNamespace())

// Create initial config map for gitops
err := createPatternsOperatorConfigMap()
if err != nil {
setupLog.Error(err, "unable to create config map")
}

mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
HealthProbeBindAddress: probeAddr,
Expand Down Expand Up @@ -120,7 +109,7 @@ func main() {
setupLog.Error(err, "unable to add console plugin runnable")
}

analyticsEnabled := areAnalyticsEnabled(mgr.GetAPIReader())
analyticsEnabled := strings.ToLower(os.Getenv("ANALYTICS")) != "false"
setupLog.Info("analytics enabled", "enabled", analyticsEnabled)
if err = (&controllers.PatternReconciler{
Client: mgr.GetClient(),
Expand Down Expand Up @@ -162,44 +151,6 @@ func printVersion() {
setupLog.Info(fmt.Sprintf("Build Date: %s", version.BuildDate))
}

// Creates the patterns operator configmap
// This will include configuration parameters that
// will allow operator configuration
func createPatternsOperatorConfigMap() error {
config, err := ctrl.GetConfig()
if err != nil {
return fmt.Errorf("failed to get config: %s", err)
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
return fmt.Errorf("failed to call NewForConfig: %s", err)
}

configMap := corev1.ConfigMap{
TypeMeta: metav1.TypeMeta{
Kind: "ConfigMap",
APIVersion: "v1",
},
ObjectMeta: metav1.ObjectMeta{
Name: controllers.OperatorConfigMap,
Namespace: controllers.DetectOperatorNamespace(),
},
}

_, err = clientset.CoreV1().ConfigMaps(controllers.DetectOperatorNamespace()).Get(context.Background(), controllers.OperatorConfigMap, metav1.GetOptions{})
if err != nil && errors.IsNotFound(err) {
// if the configmap does not exist we create an empty one
_, err = clientset.CoreV1().ConfigMaps(controllers.DetectOperatorNamespace()).Create(context.Background(), &configMap, metav1.CreateOptions{})
if err != nil {
return err
}
} else {
// if we had an error that is not IsNotFound we need to return it
return err
}
return nil
}

func registerComponentOrExit(mgr manager.Manager, f func(*k8sruntime.Scheme) error) {
// Setup Scheme for all resources
if err := f(mgr.GetScheme()); err != nil {
Expand All @@ -208,22 +159,3 @@ func registerComponentOrExit(mgr manager.Manager, f func(*k8sruntime.Scheme) err
}
setupLog.Info(fmt.Sprintf("Component registered: %v", reflect.ValueOf(f)))
}

// areAnalyticsEnabled determines whether analytics are enabled.
// Precedence: Operator ConfigMap key "analytics.enabled" (true/false) > ENV ANALYTICS (false means disabled)
func areAnalyticsEnabled(reader crclient.Reader) bool {
enabled := strings.ToLower(os.Getenv("ANALYTICS")) != "false"

var cm corev1.ConfigMap
err := reader.Get(context.Background(), crclient.ObjectKey{Namespace: controllers.DetectOperatorNamespace(), Name: controllers.OperatorConfigMap}, &cm)
if err != nil {
setupLog.Error(err, "error reading operator configmap for analytics setting")
return enabled
}

if v, ok := cm.Data["analytics.enabled"]; ok {
return strings.EqualFold(v, "true")
}

return enabled
}
74 changes: 0 additions & 74 deletions cmd/main_test.go

This file was deleted.

10 changes: 5 additions & 5 deletions internal/controller/argo.go
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ func newArgoCD(name, namespace string, patternsOperatorConfig PatternsOperatorCo
"g, cluster-admins, role:admin",
"g, admin, role:admin",
}
for argoAdmin := range strings.SplitSeq(patternsOperatorConfig.getValueWithDefault("gitops.additionalArgoAdmins"), ",") {
for argoAdmin := range strings.SplitSeq(patternsOperatorConfig.getStringValue("gitops.additionalArgoAdmins"), ",") {
argoAdmin = strings.TrimSpace(argoAdmin)
if argoAdmin != "" {
argoPolicies = append(argoPolicies, "g, "+argoAdmin+", role:admin")
Expand Down Expand Up @@ -160,7 +160,7 @@ health_status.message = "An install plan for a subscription is pending installat
return health_status`,
},
}
if strings.EqualFold(patternsOperatorConfig.getValueWithDefault("gitops.applicationHealthCheckEnabled"), "true") {
if patternsOperatorConfig.getBoolValue("gitops.applicationHealthCheckEnabled") {
// As of ArgoCD 1.8 the Application health check was dropped (see https://github.com/argoproj/argo-cd/issues/3781),
// but in app-of-apps pattern this is needed in order to implement children apps dependencies via sync-waves
resourceHealthChecks = append(resourceHealthChecks, argooperator.ResourceHealthCheck{
Expand Down Expand Up @@ -978,9 +978,9 @@ func newArgoGiteaApplication(p *api.Pattern, patternsOperatorConfig PatternsOper
},
Project: "default",
Source: &argoapi.ApplicationSource{
RepoURL: patternsOperatorConfig.getValueWithDefault("gitea.helmRepoUrl"),
TargetRevision: patternsOperatorConfig.getValueWithDefault("gitea.chartVersion"),
Chart: patternsOperatorConfig.getValueWithDefault("gitea.chartName"),
RepoURL: patternsOperatorConfig.getStringValue("gitea.helmRepoUrl"),
TargetRevision: patternsOperatorConfig.getStringValue("gitea.chartVersion"),
Chart: patternsOperatorConfig.getStringValue("gitea.chartName"),
Helm: &argoapi.ApplicationSourceHelm{
Parameters: parameters,
},
Expand Down
27 changes: 0 additions & 27 deletions internal/controller/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,30 +85,3 @@ const (

// Experimental Capabilities that can be enabled
// Currently none

var DefaultPatternsOperatorConfig = map[string]string{
"gitops.catalogSource": GitOpsDefaultCatalogSource,
"gitops.channel": GitOpsDefaultChannel,
"gitops.sourceNamespace": GitOpsDefaultCatalogSourceNamespace,
"gitops.installApprovalPlan": GitOpsDefaultApprovalPlan,
"gitops.csv": GitOpsDefaultCSV,
"gitops.additionalArgoAdmins": "",
"gitops.applicationHealthCheckEnabled": "false",
"gitea.chartName": GiteaChartName,
"gitea.helmRepoUrl": GiteaHelmRepoUrl,
"gitea.chartVersion": GiteaDefaultChartVersion,
"analytics.enabled": "true",
"catalog.image": "",
}

type PatternsOperatorConfig map[string]string

func (g PatternsOperatorConfig) getValueWithDefault(k string) string {
if v, present := g[k]; present {
return v
}
if defaultValue, present := DefaultPatternsOperatorConfig[k]; present {
return defaultValue
}
return ""
}
Loading