diff --git a/.github/workflows/releases.yaml b/.github/workflows/releases.yaml index 432e291..d410fa7 100644 --- a/.github/workflows/releases.yaml +++ b/.github/workflows/releases.yaml @@ -47,4 +47,11 @@ jobs: auth_token: ${{ secrets.GITHUB_TOKEN }} run: | echo "${auth_token}" | ko login ${{ env.OCI_DOMAIN }} --username ${{ github.actor }} --password-stdin - ko build ./cmd/kndp/ --tags=${{ env.VERSION }} --bare \ No newline at end of file + ko build ./cmd/kndp/ --tags=${{ env.VERSION }} --bare + + - name: Install crossplane CLI + id: crossplane + run: curl -sL "https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh" | sh + + - name: Build and push crossplane packages + run: ./crossplane xpkg build -f package -o configuration-environment && ./crossplane xpkg push -f configuration-environment ${REGISTRY}/${{ github.repository }}/configuration-environment:${{ env.VERSION }} || true' || true; \ No newline at end of file diff --git a/configuration/crossplane.yaml b/configuration/crossplane.yaml new file mode 100644 index 0000000..ae22124 --- /dev/null +++ b/configuration/crossplane.yaml @@ -0,0 +1,12 @@ +apiVersion: meta.pkg.crossplane.io/v1alpha1 +kind: Configuration +metadata: + name: configuration-environment +spec: + dependsOn: + - provider: xpkg.upbound.io/crossplane-contrib/provider-helm + version: ">=v0.16.0" + - provider: xpkg.upbound.io/crossplane-contrib/provider-kubernetes + version: ">=v0.13.0" + crossplane: + version: ">=v1.14.1-0" \ No newline at end of file diff --git a/configuration/environment/composition.yaml b/configuration/environment/composition.yaml new file mode 100644 index 0000000..3c3f133 --- /dev/null +++ b/configuration/environment/composition.yaml @@ -0,0 +1,98 @@ +apiVersion: apiextensions.crossplane.io/v1 +kind: Composition +metadata: + name: configuration-environment +spec: + compositeTypeRef: + apiVersion: kndp.io/v1alpha1 + kind: Environment + resources: + + - name: crossplane-release + base: + apiVersion: helm.crossplane.io/v1beta1 + kind: Release + spec: + forProvider: + namespace: "" + values: + extraObjects: + - apiVersion: kndp.io/v1alpha1 + kind: Environment + metadata: + name: environment-test + spec: + name: "kndp-crossplane" + namespace: "kndp-system" + registry: + server: "" + token: "" + configuration: + packages: [] + provider: + packages: [] + provider: + packages: [] + configuration: + packages: [] + patches: + - type: FromCompositeFieldPath + fromFieldPath: spec.helmProviderCfgRef + toFieldPath: spec.providerConfigRef.name + - type: FromCompositeFieldPath + fromFieldPath: spec.namespace + toFieldPath: spec.forProvider.namespace + - type: FromCompositeFieldPath + fromFieldPath: spec.name + toFieldPath: metadata.name + - type: FromCompositeFieldPath + fromFieldPath: spec.configuration.packages + toFieldPath: spec.forProvider.values.configuration.packages + - type: FromCompositeFieldPath + fromFieldPath: spec.provider.packages + toFieldPath: spec.forProvider.values.provider.packages + - type: FromCompositeFieldPath + fromFieldPath: spec.crossplane.chart + toFieldPath: spec.forProvider.chart.name + - type: FromCompositeFieldPath + fromFieldPath: spec.crossplane.repository + toFieldPath: spec.forProvider.chart.repository + - type: FromCompositeFieldPath + fromFieldPath: spec.crossplane.version + toFieldPath: spec.forProvider.chart.version + + + - name: kyverno-release + base: + apiVersion: helm.crossplane.io/v1beta1 + kind: Release + metadata: + name: kyverno + annotations: + crossplane.io/external-name: kyverno + spec: + forProvider: + namespace: "" + set: + - name: features.admissionReports.enabled + value: "true" + - name: aggregateReports.enabled + value: "true" + - name: policyReports.enabled + value: "true" + patches: + - type: FromCompositeFieldPath + fromFieldPath: spec.helmProviderCfgRef + toFieldPath: spec.providerConfigRef.name + - type: FromCompositeFieldPath + fromFieldPath: spec.namespace + toFieldPath: spec.forProvider.namespace + - type: FromCompositeFieldPath + fromFieldPath: spec.kyverno.chart + toFieldPath: spec.forProvider.chart.name + - type: FromCompositeFieldPath + fromFieldPath: spec.kyverno.repository + toFieldPath: spec.forProvider.chart.repository + - type: FromCompositeFieldPath + fromFieldPath: spec.kyverno.version + toFieldPath: spec.forProvider.chart.version \ No newline at end of file diff --git a/configuration/environment/xrd.yaml b/configuration/environment/xrd.yaml new file mode 100644 index 0000000..4656c9f --- /dev/null +++ b/configuration/environment/xrd.yaml @@ -0,0 +1,90 @@ +apiVersion: apiextensions.crossplane.io/v1 +kind: CompositeResourceDefinition +metadata: + name: environments.kndp.io +spec: + group: kndp.io + names: + kind: Environment + plural: environments + singular: environment + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + type: object + properties: + spec: + type: object + properties: + crossplane: + type: object + properties: + chart: + type: string + default: crossplane + repository: + type: string + default: https://charts.crossplane.io/stable + version: + type: string + default: "1.15.2" + kyverno: + type: object + properties: + chart: + type: string + default: kyverno + repository: + type: string + default: "https://kyverno.github.io/kyverno/" + version: + type: string + default: "3.2.5" + name: + type: string + namespace: + type: string + configuration: + type: object + properties: + packages: + type: array + items: + type: string + provider: + type: object + properties: + packages: + type: array + items: + type: string + helmProviderCfgRef: + type: string + default: kndp-helm-provider-config + kubernetesProviderCfgRef: + type: string + default: kndp-kubernetes-provider-config + status: + type: object + description: Status information. + properties: + providers: + type: object + description: Providers details. + properties: + kubernetes: + type: object + properties: + name: + type: string + description: Kubernetes provider config name. + helm: + type: object + properties: + name: + type: string + description: Helm provider config name. + + served: true + referenceable: true \ No newline at end of file diff --git a/configuration/registry/composition.yaml b/configuration/registry/composition.yaml new file mode 100644 index 0000000..5200c7d --- /dev/null +++ b/configuration/registry/composition.yaml @@ -0,0 +1,231 @@ +apiVersion: apiextensions.crossplane.io/v1 +kind: Composition +metadata: + name: configuration-registry +spec: + compositeTypeRef: + apiVersion: kndp.io/v1alpha1 + kind: Registry + resources: + + + - name: registry-secret + base: + apiVersion: kubernetes.crossplane.io/v1alpha1 + kind: Object + spec: + forProvider: + manifest: + apiVersion: v1 + kind: Secret + type: kubernetes.io/dockerconfigjson + data: + .dockerconfigjson: "" + patches: + - type: FromCompositeFieldPath + fromFieldPath: spec.kubernetesProviderCfgRef + toFieldPath: spec.providerConfigRef.name + - type: FromCompositeFieldPath + fromFieldPath: spec.namespace + toFieldPath: spec.forProvider.manifest.metadata.namespace + - type: FromCompositeFieldPath + fromFieldPath: metadata.name + transforms: + - type: string + string: + type: Format + fmt: "%s-registry" + toFieldPath: spec.forProvider.manifest.metadata.name + - type: FromCompositeFieldPath + fromFieldPath: metadata.name + transforms: + - type: string + string: + type: Format + fmt: "%s-registry" + toFieldPath: metadata.name + - type: CombineFromComposite + combine: + variables: + - fromFieldPath: spec.token + strategy: string + string: + fmt: "user:%s" + transforms: + - type: string + string: + type: Convert + convert: "ToBase64" + toFieldPath: metadata.annotations[auth] + - type: ToCompositeFieldPath + fromFieldPath: metadata.annotations[auth] + toFieldPath: status.auth + - type: CombineFromComposite + combine: + variables: + - fromFieldPath: spec.server + - fromFieldPath: status.auth + strategy: string + string: + fmt: '{"auths":{"%s":{"auth":"%s"}}}' + transforms: + - type: string + string: + type: Convert + convert: "ToBase64" + toFieldPath: spec.forProvider.manifest.data[.dockerconfigjson] + + + - name: kyverno-policy-scplc + base: + apiVersion: kubernetes.crossplane.io/v1alpha1 + kind: Object + spec: + forProvider: + manifest: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + spec: + generateExisting: true + rules: + - name: kndp-sync-registry-secrets + match: + resources: + kinds: + - Namespace + generate: + apiVersion: v1 + kind: Secret + synchronize: true + patches: + - type: FromCompositeFieldPath + fromFieldPath: spec.kubernetesProviderCfgRef + toFieldPath: spec.providerConfigRef.name + - type: FromCompositeFieldPath + fromFieldPath: metadata.name + transforms: + - type: string + string: + type: Format + fmt: "%s-scplc" + toFieldPath: metadata.name + - type: FromCompositeFieldPath + fromFieldPath: metadata.namespace + toFieldPath: spec.forProvider.manifest.metadata.namespace + - type: FromCompositeFieldPath + fromFieldPath: metadata.name + transforms: + - type: string + string: + type: Format + fmt: "%s-scplc" + toFieldPath: spec.forProvider.manifest.metadata.name + - type: FromCompositeFieldPath + fromFieldPath: metadata.name + transforms: + - type: string + string: + type: Format + fmt: "%s-scplc" + toFieldPath: spec.forProvider.manifest.spec.rules[0].generate.name + - type: FromCompositeFieldPath + fromFieldPath: metadata.name + transforms: + - type: string + string: + type: Format + fmt: "%s-scplc" + toFieldPath: spec.forProvider.manifest.spec.rules[0].generate.clone.name + - type: FromCompositeFieldPath + fromFieldPath: spec.namespace + transforms: + - type: string + string: + type: Format + fmt: "%s-scplc" + toFieldPath: spec.forProvider.manifest.spec.rules[0].generate.clone.namespace + - type: FromCompositeFieldPath + fromFieldPath: spec.namespace + transforms: + - type: string + string: + type: Format + fmt: "%s-scplc" + toFieldPath: spec.forProvider.manifest.spec.rules[0].generate.namespace + + + - name: kyverno-policy-regplc + base: + apiVersion: kubernetes.crossplane.io/v1alpha1 + kind: Object + spec: + forProvider: + manifest: + apiVersion: kyverno.io/v1 + kind: ClusterPolicy + spec: + generateExisting: true + rules: + - name: "" + match: + any: + - resources: + kinds: + - Pod + skipBackgroundRequests: false + mutate: + foreach: + - list: request.object.spec.containers + patchStrategicMerge: + spec: + containers: + - (image): "" + image: "{{ regex_replace_all_literal('^[^/]+', '{{element.image}}', 'localhost:30100') }}" + patches: + - type: FromCompositeFieldPath + fromFieldPath: spec.kubernetesProviderCfgRef + toFieldPath: spec.providerConfigRef.name + - type: FromCompositeFieldPath + fromFieldPath: metadata.name + transforms: + - type: string + string: + type: Format + fmt: "%s-scplc" + toFieldPath: spec.forProvider.manifest.metadata.name + - type: FromCompositeFieldPath + fromFieldPath: metadata.namespace + toFieldPath: spec.forProvider.manifest.metadata.namespace + - type: FromCompositeFieldPath + fromFieldPath: metadata.name + transforms: + - type: string + string: + type: Format + fmt: "%s-regplc" + toFieldPath: spec.forProvider.manifest.metadata.name + - type: FromCompositeFieldPath + fromFieldPath: metadata.name + transforms: + - type: string + string: + type: Format + fmt: "%s-regplc" + toFieldPath: spec.forProvider.manifest.spec.rules[0].name + - type: FromCompositeFieldPath + fromFieldPath: metadata.name + transforms: + - type: string + string: + type: Format + fmt: "*%s*" + toFieldPath: spec.forProvider.manifest.spec.rules[0].mutate.foreach[0].patchStrategicMerge.spec.containers[0].(image) + - type: FromCompositeFieldPath + fromFieldPath: metadata.name + transforms: + - type: string + string: + type: Format + fmt: "%s-regplc" + toFieldPath: metadata.name + diff --git a/configuration/registry/xrd.yaml b/configuration/registry/xrd.yaml new file mode 100644 index 0000000..5b42cdb --- /dev/null +++ b/configuration/registry/xrd.yaml @@ -0,0 +1,41 @@ +apiVersion: apiextensions.crossplane.io/v1 +kind: CompositeResourceDefinition +metadata: + name: registrys.kndp.io +spec: + group: kndp.io + names: + kind: Registry + plural: registrys + singular: registry + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + type: object + properties: + spec: + type: object + properties: + name: + type: string + namespace: + type: string + server: + type: string + token: + type: string + kubernetesProviderCfgRef: + type: string + status: + type: object + description: Status information. + properties: + registry: + type: object + properties: + auth: + type: string + + served: true + referenceable: true \ No newline at end of file diff --git a/internal/engine/engine.go b/internal/engine/engine.go index 9551c71..3417ad0 100644 --- a/internal/engine/engine.go +++ b/internal/engine/engine.go @@ -63,6 +63,11 @@ var ( "xpkg.upbound.io/crossplane-contrib/provider-helm:v0.19.0", }, }, + "configuration": map[string]any{ + "packages": []string{ + "ghcr.io/kndpio/configuration-environment:0.0.1", + }, + }, "args": []string{}, } ) @@ -340,6 +345,28 @@ func (a *SecretReconciler) Reconcile(ctx context.Context, req reconcile.Request) }, } + envObj := &unstructured.Unstructured{ + Object: map[string]interface{}{ + "apiVersion": "kndp.io/v1alpha1", + "kind": "Environment", + "metadata": map[string]interface{}{ + "name": "environment", + }, + "spec": map[string]interface{}{ + "name": ReleaseName, + "namespace": namespace.Namespace, + "configuration": map[string]interface{}{ + "packages": []interface{}{}, + }, + "provider": map[string]interface{}{ + "packages": []interface{}{}, + }, + "helmProviderCfgRef": helmProviderConfigName, + "kubernetesProviderCfgRef": providerConfigName, + }, + }, + } + if _, err = controllerutil.CreateOrUpdate(ctx, a.Client, pc, func() error { pc.Object["spec"] = map[string]interface{}{ "credentials": map[string]interface{}{ @@ -372,6 +399,10 @@ func (a *SecretReconciler) Reconcile(ctx context.Context, req reconcile.Request) return reconcile.Result{}, err } + if _, err = controllerutil.CreateOrUpdate(ctx, a.Client, envObj, func() error { return nil }); err != nil { + return reconcile.Result{}, err + } + a.CancelFunc() return reconcile.Result{}, nil diff --git a/internal/environment/environment.go b/internal/environment/environment.go index c92029a..121e19e 100644 --- a/internal/environment/environment.go +++ b/internal/environment/environment.go @@ -101,7 +101,7 @@ func (e *Environment) Upgrade(ctx context.Context, logger *zap.SugaredLogger) er } // confirmationPrompt prompts the user with a yes/no choice. -func confirmationPrompt(s string, logger *zap.SugaredLogger) bool { +func confirmationPrompt(s string, logger *zap.SugaredLogger) bool { reader := bufio.NewReader(os.Stdin) for { fmt.Printf("%s [y/n]: ", s) @@ -121,7 +121,7 @@ func confirmationPrompt(s string, logger *zap.SugaredLogger) bool { } // Delete environment cluster -func (e *Environment) Delete(f bool, logger *zap.SugaredLogger) error { +func (e *Environment) Delete(f bool, logger *zap.SugaredLogger) error { var err error if !f && !confirmationPrompt(fmt.Sprintf("Do you really want to delete environment %s ?", e.name), logger) { return nil