diff --git a/.github/workflows/e2e-atomic-fruits-vault-crossplane.yml b/.github/workflows/e2e-atomic-fruits-vault-crossplane.yml index 66898086..3bc0ddcc 100644 --- a/.github/workflows/e2e-atomic-fruits-vault-crossplane.yml +++ b/.github/workflows/e2e-atomic-fruits-vault-crossplane.yml @@ -1,4 +1,4 @@ -name: Job testing an end to end scenario with simple application. It tests all steps from kind, vault and crossplane installation. +name: Job doing e2e scenario using primaza + vault + crossplane and atomic fruits on: workflow_dispatch: @@ -95,7 +95,7 @@ jobs: run: | ./scripts/crossplane.sh - - name: Installing Postgresql DB and Atomic fruits + - name: Installing Atomic fruits env: ATOMIC_FRUITS_NAMESPACE: app run: | @@ -179,13 +179,16 @@ jobs: run: | ./scripts/primaza.sh log - - name: (Only if it failed) Log Atomic Fruits traces at failures + - name: (Only if it failed) Log Atomic Fruits traces at failure like Primaza if: failure() env: ATOMIC_FRUITS_NAMESPACE: app run: | source ./scripts/common.sh - + + log BLUE "Logs of Primaza pod" + ./scripts/primaza.sh log + log BLUE "List of the pods deployed on the cluster" kubectl get pods -A diff --git a/.github/workflows/e2e-atomic-fruits-vault.yml b/.github/workflows/e2e-atomic-fruits-vault.yml index df6ba5c3..3f182e04 100644 --- a/.github/workflows/e2e-atomic-fruits-vault.yml +++ b/.github/workflows/e2e-atomic-fruits-vault.yml @@ -1,4 +1,4 @@ -name: Job testing an end to end scenario with simple application. It tests all steps from kind and vault installation. +name: Job doing e2e scenario using primaza + vault and atomic fruits on: workflow_dispatch: diff --git a/app/pom.xml b/app/pom.xml index 1d67e13d..9919fdad 100644 --- a/app/pom.xml +++ b/app/pom.xml @@ -219,6 +219,7 @@ io.fabric8 java-generator-maven-plugin + ${kubernetes-client.version} @@ -228,17 +229,22 @@ true + src/main/crds + + <!– Primaza CRDs –> https://raw.githubusercontent.com/primaza/primaza/main/config/crd/bases/primaza.io_clusterenvironments.yaml https://raw.githubusercontent.com/primaza/primaza/main/config/crd/bases/primaza.io_registeredservices.yaml https://raw.githubusercontent.com/primaza/primaza/main/config/crd/bases/primaza.io_servicebindings.yaml https://raw.githubusercontent.com/primaza/primaza/main/config/crd/bases/primaza.io_servicecatalogs.yaml https://raw.githubusercontent.com/primaza/primaza/main/config/crd/bases/primaza.io_serviceclaims.yaml https://raw.githubusercontent.com/primaza/primaza/main/config/crd/bases/primaza.io_serviceclasses.yaml - - https://raw.githubusercontent.com/crossplane-contrib/provider-helm/master/package/crds/helm.crossplane.io_releases.yaml + <!– Crossplane Helm release able to deploy a helm chart –> + <!– Revert to an old version of the CRD as we got a class cast exception using ManagedPolicies field introduced recently –> + <!–https://raw.githubusercontent.com/crossplane-contrib/provider-helm/v0.14.0/package/crds/helm.crossplane.io_releases.yaml–> + https://raw.githubusercontent.com/crossplane-contrib/provider-helm/v0.18.1/package/crds/helm.crossplane.io_releases.yaml + --> diff --git a/app/src/main/crds/helm.crossplane.io_releases.yaml b/app/src/main/crds/helm.crossplane.io_releases.yaml new file mode 100644 index 00000000..0ee0ae2a --- /dev/null +++ b/app/src/main/crds/helm.crossplane.io_releases.yaml @@ -0,0 +1,1005 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.13.0 + name: releases.helm.crossplane.io +spec: + group: helm.crossplane.io + names: + categories: + - crossplane + - managed + - helm + kind: Release + listKind: ReleaseList + plural: releases + singular: release + scope: Cluster + versions: + - additionalPrinterColumns: + - jsonPath: .spec.forProvider.chart.name + name: CHART + type: string + - jsonPath: .spec.forProvider.chart.version + name: VERSION + type: string + - jsonPath: .status.conditions[?(@.type=='Synced')].status + name: SYNCED + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: READY + type: string + - jsonPath: .status.atProvider.state + name: STATE + type: string + - jsonPath: .status.atProvider.revision + name: REVISION + type: string + - jsonPath: .status.atProvider.releaseDescription + name: DESCRIPTION + type: string + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: A Release is an example API type + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: A ReleaseSpec defines the desired state of a Release. + properties: + deletionPolicy: + default: Delete + description: 'DeletionPolicy specifies what will happen to the underlying + external when this managed resource is deleted - either "Delete" + or "Orphan" the external resource. This field is planned to be deprecated + in favor of the ManagementPolicies field in a future release. Currently, + both could be set independently and non-default values would be + honored if the feature flag is enabled. See the design doc for more + information: https://github.com/crossplane/crossplane/blob/499895a25d1a1a0ba1604944ef98ac7a1a71f197/design/design-doc-observe-only-resources.md?plain=1#L223' + enum: + - Orphan + - Delete + type: string + forProvider: + description: ReleaseParameters are the configurable fields of a Release. + properties: + chart: + description: A ChartSpec defines the chart spec for a Release + properties: + name: + type: string + pullSecretRef: + description: A SecretReference is a reference to a secret + in an arbitrary namespace. + properties: + name: + description: Name of the secret. + type: string + namespace: + description: Namespace of the secret. + type: string + required: + - name + - namespace + type: object + repository: + type: string + version: + type: string + required: + - name + - repository + - version + type: object + namespace: + type: string + patchesFrom: + items: + description: ValueFromSource represents source of a value + properties: + configMapKeyRef: + description: DataKeySelector defines required spec to access + a key of a configmap or secret + properties: + key: + type: string + name: + type: string + namespace: + type: string + optional: + type: boolean + required: + - name + - namespace + type: object + secretKeyRef: + description: DataKeySelector defines required spec to access + a key of a configmap or secret + properties: + key: + type: string + name: + type: string + namespace: + type: string + optional: + type: boolean + required: + - name + - namespace + type: object + type: object + type: array + set: + items: + description: SetVal represents a "set" value override in a Release + properties: + name: + type: string + value: + type: string + valueFrom: + description: ValueFromSource represents source of a value + properties: + configMapKeyRef: + description: DataKeySelector defines required spec to + access a key of a configmap or secret + properties: + key: + type: string + name: + type: string + namespace: + type: string + optional: + type: boolean + required: + - name + - namespace + type: object + secretKeyRef: + description: DataKeySelector defines required spec to + access a key of a configmap or secret + properties: + key: + type: string + name: + type: string + namespace: + type: string + optional: + type: boolean + required: + - name + - namespace + type: object + type: object + required: + - name + type: object + type: array + values: + type: object + x-kubernetes-preserve-unknown-fields: true + valuesFrom: + items: + description: ValueFromSource represents source of a value + properties: + configMapKeyRef: + description: DataKeySelector defines required spec to access + a key of a configmap or secret + properties: + key: + type: string + name: + type: string + namespace: + type: string + optional: + type: boolean + required: + - name + - namespace + type: object + secretKeyRef: + description: DataKeySelector defines required spec to access + a key of a configmap or secret + properties: + key: + type: string + name: + type: string + namespace: + type: string + optional: + type: boolean + required: + - name + - namespace + type: object + type: object + type: array + wait: + type: boolean + required: + - chart + - namespace + type: object + managementPolicies: + # default: + # Removed it to check if error is gone: https://github.com/halkyonio/primaza-poc/issues/476 + # - Create + description: 'THIS IS A BETA FIELD. It is on by default but can be + opted out through a Crossplane feature flag. ManagementPolicies + specify the array of actions Crossplane is allowed to take on the + managed and external resources. This field is planned to replace + the DeletionPolicy field in a future release. Currently, both could + be set independently and non-default values would be honored if + the feature flag is enabled. If both are custom, the DeletionPolicy + field will be ignored. See the design doc for more information: + https://github.com/crossplane/crossplane/blob/499895a25d1a1a0ba1604944ef98ac7a1a71f197/design/design-doc-observe-only-resources.md?plain=1#L223 + and this one: https://github.com/crossplane/crossplane/blob/444267e84783136daa93568b364a5f01228cacbe/design/one-pager-ignore-changes.md' + items: + description: A ManagementAction represents an action that the Crossplane + controllers can take on an external resource. + enum: + - Observe + - Create + - Update + - Delete + - LateInitialize + # Removed it to check if error is gone: https://github.com/halkyonio/primaza-poc/issues/476 + # Code generated is: + # public class ReleaseSpec implements io.fabric8.kubernetes.api.model.KubernetesResource { + # ... + # private java.util.List managementPolicies = io.fabric8.kubernetes.client.utils.Serialization.unmarshal("[\"*\"]", java.util.List.class); + - '*' + type: string + type: array + providerConfigRef: + default: + name: default + description: ProviderConfigReference specifies how the provider that + will be used to create, observe, update, and delete this managed + resource should be configured. + properties: + name: + description: Name of the referenced object. + type: string + policy: + description: Policies for referencing. + properties: + resolution: + default: Required + description: Resolution specifies whether resolution of this + reference is required. The default is 'Required', which + means the reconcile will fail if the reference cannot be + resolved. 'Optional' means this reference will be a no-op + if it cannot be resolved. + enum: + - Required + - Optional + type: string + resolve: + description: Resolve specifies when this reference should + be resolved. The default is 'IfNotPresent', which will attempt + to resolve the reference only when the corresponding field + is not present. Use 'Always' to resolve the reference on + every reconcile. + enum: + - Always + - IfNotPresent + type: string + type: object + required: + - name + type: object + publishConnectionDetailsTo: + description: PublishConnectionDetailsTo specifies the connection secret + config which contains a name, metadata and a reference to secret + store config to which any connection details for this managed resource + should be written. Connection details frequently include the endpoint, + username, and password required to connect to the managed resource. + properties: + configRef: + default: + name: default + description: SecretStoreConfigRef specifies which secret store + config should be used for this ConnectionSecret. + properties: + name: + description: Name of the referenced object. + type: string + policy: + description: Policies for referencing. + properties: + resolution: + default: Required + description: Resolution specifies whether resolution of + this reference is required. The default is 'Required', + which means the reconcile will fail if the reference + cannot be resolved. 'Optional' means this reference + will be a no-op if it cannot be resolved. + enum: + - Required + - Optional + type: string + resolve: + description: Resolve specifies when this reference should + be resolved. The default is 'IfNotPresent', which will + attempt to resolve the reference only when the corresponding + field is not present. Use 'Always' to resolve the reference + on every reconcile. + enum: + - Always + - IfNotPresent + type: string + type: object + required: + - name + type: object + metadata: + description: Metadata is the metadata for connection secret. + properties: + annotations: + additionalProperties: + type: string + description: Annotations are the annotations to be added to + connection secret. - For Kubernetes secrets, this will be + used as "metadata.annotations". - It is up to Secret Store + implementation for others store types. + type: object + labels: + additionalProperties: + type: string + description: Labels are the labels/tags to be added to connection + secret. - For Kubernetes secrets, this will be used as "metadata.labels". + - It is up to Secret Store implementation for others store + types. + type: object + type: + description: Type is the SecretType for the connection secret. + - Only valid for Kubernetes Secret Stores. + type: string + type: object + name: + description: Name is the name of the connection secret. + type: string + required: + - name + type: object + rollbackLimit: + description: RollbackRetriesLimit is max number of attempts to retry + Helm deployment by rolling back the release. + format: int32 + type: integer + writeConnectionSecretToRef: + description: WriteConnectionSecretToReference specifies the namespace + and name of a Secret to which any connection details for this managed + resource should be written. Connection details frequently include + the endpoint, username, and password required to connect to the + managed resource. This field is planned to be replaced in a future + release in favor of PublishConnectionDetailsTo. Currently, both + could be set independently and connection details would be published + to both without affecting each other. + properties: + name: + description: Name of the secret. + type: string + namespace: + description: Namespace of the secret. + type: string + required: + - name + - namespace + type: object + required: + - forProvider + type: object + status: + description: A ReleaseStatus represents the observed state of a Release. + properties: + atProvider: + description: ReleaseObservation are the observable fields of a Release. + properties: + releaseDescription: + type: string + revision: + type: integer + state: + description: Status is the status of a release + type: string + type: object + conditions: + description: Conditions of the resource. + items: + description: A Condition that may apply to a resource. + properties: + lastTransitionTime: + description: LastTransitionTime is the last time this condition + transitioned from one status to another. + format: date-time + type: string + message: + description: A Message containing details about this condition's + last transition from one status to another, if any. + type: string + reason: + description: A Reason for this condition's last transition from + one status to another. + type: string + status: + description: Status of this condition; is it currently True, + False, or Unknown? + type: string + type: + description: Type of this condition. At most one of each condition + type may apply to a resource at any point in time. + type: string + required: + - lastTransitionTime + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + failed: + format: int32 + type: integer + patchesSha: + type: string + synced: + type: boolean + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} + - additionalPrinterColumns: + - jsonPath: .spec.forProvider.chart.name + name: CHART + type: string + - jsonPath: .spec.forProvider.chart.version + name: VERSION + type: string + - jsonPath: .status.conditions[?(@.type=='Synced')].status + name: SYNCED + type: string + - jsonPath: .status.conditions[?(@.type=='Ready')].status + name: READY + type: string + - jsonPath: .status.atProvider.state + name: STATE + type: string + - jsonPath: .status.atProvider.revision + name: REVISION + type: string + - jsonPath: .status.atProvider.releaseDescription + name: DESCRIPTION + type: string + - jsonPath: .metadata.creationTimestamp + name: AGE + type: date + name: v1beta1 + schema: + openAPIV3Schema: + description: A Release is an example API type + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: A ReleaseSpec defines the desired state of a Release. + properties: + connectionDetails: + items: + description: ConnectionDetail todo + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: 'If referring to a piece of an object instead of + an entire object, this string should contain a valid JSON/Go + field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within + a pod, this would take on a value like: "spec.containers{name}" + (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" + (container with index 2 in this pod). This syntax is chosen + only to have some well-defined way of referencing a part of + an object. TODO: this design is not final and this field is + subject to change in the future.' + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + type: string + resourceVersion: + description: 'Specific resourceVersion to which this reference + is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' + type: string + skipPartOfReleaseCheck: + description: SkipPartOfReleaseCheck skips check for meta.helm.sh/release-name + annotation. + type: boolean + toConnectionSecretKey: + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + type: string + type: object + x-kubernetes-map-type: atomic + type: array + deletionPolicy: + default: Delete + description: 'DeletionPolicy specifies what will happen to the underlying + external when this managed resource is deleted - either "Delete" + or "Orphan" the external resource. This field is planned to be deprecated + in favor of the ManagementPolicies field in a future release. Currently, + both could be set independently and non-default values would be + honored if the feature flag is enabled. See the design doc for more + information: https://github.com/crossplane/crossplane/blob/499895a25d1a1a0ba1604944ef98ac7a1a71f197/design/design-doc-observe-only-resources.md?plain=1#L223' + enum: + - Orphan + - Delete + type: string + forProvider: + description: ReleaseParameters are the configurable fields of a Release. + properties: + chart: + description: A ChartSpec defines the chart spec for a Release + properties: + name: + description: Name of Helm chart, required if ChartSpec.URL + not set + type: string + pullSecretRef: + description: PullSecretRef is reference to the secret containing + credentials to helm repository + properties: + name: + description: Name of the secret. + type: string + namespace: + description: Namespace of the secret. + type: string + required: + - name + - namespace + type: object + repository: + description: 'Repository: Helm repository URL, required if + ChartSpec.URL not set' + type: string + url: + description: URL to chart package (typically .tgz), optional + and overrides others fields in the spec + type: string + version: + description: Version of Helm chart, late initialized with + latest version if not set + type: string + type: object + insecureSkipTLSVerify: + description: InsecureSkipTLSVerify skips tls certificate checks + for the chart download + type: boolean + namespace: + description: Namespace to install the release into. + type: string + patchesFrom: + description: PatchesFrom describe patches to be applied to the + rendered manifests. + items: + description: ValueFromSource represents source of a value + properties: + configMapKeyRef: + description: DataKeySelector defines required spec to access + a key of a configmap or secret + properties: + key: + type: string + name: + type: string + namespace: + type: string + optional: + type: boolean + required: + - name + - namespace + type: object + secretKeyRef: + description: DataKeySelector defines required spec to access + a key of a configmap or secret + properties: + key: + type: string + name: + type: string + namespace: + type: string + optional: + type: boolean + required: + - name + - namespace + type: object + type: object + type: array + set: + items: + description: SetVal represents a "set" value override in a Release + properties: + name: + type: string + value: + type: string + valueFrom: + description: ValueFromSource represents source of a value + properties: + configMapKeyRef: + description: DataKeySelector defines required spec to + access a key of a configmap or secret + properties: + key: + type: string + name: + type: string + namespace: + type: string + optional: + type: boolean + required: + - name + - namespace + type: object + secretKeyRef: + description: DataKeySelector defines required spec to + access a key of a configmap or secret + properties: + key: + type: string + name: + type: string + namespace: + type: string + optional: + type: boolean + required: + - name + - namespace + type: object + type: object + required: + - name + type: object + type: array + skipCRDs: + description: SkipCRDs skips installation of CRDs for the release. + type: boolean + skipCreateNamespace: + description: SkipCreateNamespace won't create the namespace for + the release. This requires the namespace to already exist. + type: boolean + values: + type: object + x-kubernetes-preserve-unknown-fields: true + valuesFrom: + items: + description: ValueFromSource represents source of a value + properties: + configMapKeyRef: + description: DataKeySelector defines required spec to access + a key of a configmap or secret + properties: + key: + type: string + name: + type: string + namespace: + type: string + optional: + type: boolean + required: + - name + - namespace + type: object + secretKeyRef: + description: DataKeySelector defines required spec to access + a key of a configmap or secret + properties: + key: + type: string + name: + type: string + namespace: + type: string + optional: + type: boolean + required: + - name + - namespace + type: object + type: object + type: array + wait: + description: Wait for the release to become ready. + type: boolean + waitTimeout: + description: WaitTimeout is the duration Helm will wait for the + release to become ready. Only applies if wait is also set. Defaults + to 5m. + type: string + required: + - chart + - namespace + type: object + managementPolicies: + # default: + # - Create + description: 'THIS IS A BETA FIELD. It is on by default but can be + opted out through a Crossplane feature flag. ManagementPolicies + specify the array of actions Crossplane is allowed to take on the + managed and external resources. This field is planned to replace + the DeletionPolicy field in a future release. Currently, both could + be set independently and non-default values would be honored if + the feature flag is enabled. If both are custom, the DeletionPolicy + field will be ignored. See the design doc for more information: + https://github.com/crossplane/crossplane/blob/499895a25d1a1a0ba1604944ef98ac7a1a71f197/design/design-doc-observe-only-resources.md?plain=1#L223 + and this one: https://github.com/crossplane/crossplane/blob/444267e84783136daa93568b364a5f01228cacbe/design/one-pager-ignore-changes.md' + items: + description: A ManagementAction represents an action that the Crossplane + controllers can take on an external resource. + enum: + - Observe + - Create + - Update + - Delete + - LateInitialize + - '*' + type: string + type: array + providerConfigRef: + default: + name: default + description: ProviderConfigReference specifies how the provider that + will be used to create, observe, update, and delete this managed + resource should be configured. + properties: + name: + description: Name of the referenced object. + type: string + policy: + description: Policies for referencing. + properties: + resolution: + default: Required + description: Resolution specifies whether resolution of this + reference is required. The default is 'Required', which + means the reconcile will fail if the reference cannot be + resolved. 'Optional' means this reference will be a no-op + if it cannot be resolved. + enum: + - Required + - Optional + type: string + resolve: + description: Resolve specifies when this reference should + be resolved. The default is 'IfNotPresent', which will attempt + to resolve the reference only when the corresponding field + is not present. Use 'Always' to resolve the reference on + every reconcile. + enum: + - Always + - IfNotPresent + type: string + type: object + required: + - name + type: object + publishConnectionDetailsTo: + description: PublishConnectionDetailsTo specifies the connection secret + config which contains a name, metadata and a reference to secret + store config to which any connection details for this managed resource + should be written. Connection details frequently include the endpoint, + username, and password required to connect to the managed resource. + properties: + configRef: + default: + name: default + description: SecretStoreConfigRef specifies which secret store + config should be used for this ConnectionSecret. + properties: + name: + description: Name of the referenced object. + type: string + policy: + description: Policies for referencing. + properties: + resolution: + default: Required + description: Resolution specifies whether resolution of + this reference is required. The default is 'Required', + which means the reconcile will fail if the reference + cannot be resolved. 'Optional' means this reference + will be a no-op if it cannot be resolved. + enum: + - Required + - Optional + type: string + resolve: + description: Resolve specifies when this reference should + be resolved. The default is 'IfNotPresent', which will + attempt to resolve the reference only when the corresponding + field is not present. Use 'Always' to resolve the reference + on every reconcile. + enum: + - Always + - IfNotPresent + type: string + type: object + required: + - name + type: object + metadata: + description: Metadata is the metadata for connection secret. + properties: + annotations: + additionalProperties: + type: string + description: Annotations are the annotations to be added to + connection secret. - For Kubernetes secrets, this will be + used as "metadata.annotations". - It is up to Secret Store + implementation for others store types. + type: object + labels: + additionalProperties: + type: string + description: Labels are the labels/tags to be added to connection + secret. - For Kubernetes secrets, this will be used as "metadata.labels". + - It is up to Secret Store implementation for others store + types. + type: object + type: + description: Type is the SecretType for the connection secret. + - Only valid for Kubernetes Secret Stores. + type: string + type: object + name: + description: Name is the name of the connection secret. + type: string + required: + - name + type: object + rollbackLimit: + description: RollbackRetriesLimit is max number of attempts to retry + Helm deployment by rolling back the release. + format: int32 + type: integer + writeConnectionSecretToRef: + description: WriteConnectionSecretToReference specifies the namespace + and name of a Secret to which any connection details for this managed + resource should be written. Connection details frequently include + the endpoint, username, and password required to connect to the + managed resource. This field is planned to be replaced in a future + release in favor of PublishConnectionDetailsTo. Currently, both + could be set independently and connection details would be published + to both without affecting each other. + properties: + name: + description: Name of the secret. + type: string + namespace: + description: Namespace of the secret. + type: string + required: + - name + - namespace + type: object + required: + - forProvider + type: object + status: + description: A ReleaseStatus represents the observed state of a Release. + properties: + atProvider: + description: ReleaseObservation are the observable fields of a Release. + properties: + releaseDescription: + type: string + revision: + type: integer + state: + description: Status is the status of a release + type: string + type: object + conditions: + description: Conditions of the resource. + items: + description: A Condition that may apply to a resource. + properties: + lastTransitionTime: + description: LastTransitionTime is the last time this condition + transitioned from one status to another. + format: date-time + type: string + message: + description: A Message containing details about this condition's + last transition from one status to another, if any. + type: string + reason: + description: A Reason for this condition's last transition from + one status to another. + type: string + status: + description: Status of this condition; is it currently True, + False, or Unknown? + type: string + type: + description: Type of this condition. At most one of each condition + type may apply to a resource at any point in time. + type: string + required: + - lastTransitionTime + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + failed: + format: int32 + type: integer + patchesSha: + type: string + synced: + type: boolean + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} diff --git a/app/src/main/crds/primaza.io_clusterenvironments.yaml b/app/src/main/crds/primaza.io_clusterenvironments.yaml new file mode 100644 index 00000000..d595b432 --- /dev/null +++ b/app/src/main/crds/primaza.io_clusterenvironments.yaml @@ -0,0 +1,181 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.11.3 + creationTimestamp: null + name: clusterenvironments.primaza.io +spec: + group: primaza.io + names: + kind: ClusterEnvironment + listKind: ClusterEnvironmentList + plural: clusterenvironments + singular: clusterenvironment + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: the environment associated to the ClusterEnvironment instance + jsonPath: .spec.environmentName + name: Environment + type: string + - description: the state of the ClusterEnvironment + jsonPath: .status.state + name: State + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: ClusterEnvironment is the Schema for the clusterenvironments + API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ClusterEnvironmentSpec defines the desired state of ClusterEnvironment + properties: + applicationNamespaces: + description: Namespaces in target cluster where applications are deployed + items: + type: string + type: array + clusterContextSecret: + description: Name of the Secret where connection (kubeconfig) information + to target cluster is stored + type: string + contactInfo: + description: Cluster Admin's contact information + type: string + description: + description: Description of the ClusterEnvironment + type: string + environmentName: + description: The environment associated to the ClusterEnvironment + instance + type: string + labels: + description: Labels + items: + type: string + type: array + serviceNamespaces: + description: Namespaces in target cluster where services are discovered + items: + type: string + type: array + synchronizationStrategy: + default: Push + description: SynchronizationStrategy defines whether Primaza will + watch clusters (Pull) or Agents will Push data as they have (Push) + enum: + - Pull + - Push + type: string + required: + - clusterContextSecret + - environmentName + - synchronizationStrategy + type: object + status: + description: ClusterEnvironmentStatus defines the observed state of ClusterEnvironment + properties: + conditions: + description: Status Conditions + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + state: + default: Offline + description: The State of the cluster environment + enum: + - Online + - Offline + - Partial + type: string + required: + - conditions + - state + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/app/src/main/crds/primaza.io_registeredservices.yaml b/app/src/main/crds/primaza.io_registeredservices.yaml new file mode 100644 index 00000000..fe8cbeb0 --- /dev/null +++ b/app/src/main/crds/primaza.io_registeredservices.yaml @@ -0,0 +1,165 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.11.3 + creationTimestamp: null + name: registeredservices.primaza.io +spec: + group: primaza.io + names: + kind: RegisteredService + listKind: RegisteredServiceList + plural: registeredservices + singular: registeredservice + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: the state of the RegisteredService + jsonPath: .status.state + name: State + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: RegisteredService is the Schema for the registeredservices API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: RegisteredServiceSpec defines the desired state of RegisteredService + properties: + constraints: + description: Constraints defines under which circumstances the RegisteredService + may be used. + properties: + environments: + description: Environments defines in which environments the RegisteredService + may be used. + items: + type: string + type: array + type: object + healthcheck: + description: HealthCheck defines a health check for the underlying + service. + properties: + container: + description: Container defines a container that will run a check + against the ServiceEndpointDefinition to determine connectivity + and access. + properties: + command: + description: Command to execute in the container to run the + test + items: + type: string + type: array + image: + description: Container image with the client to run the test + type: string + minutes: + default: 5 + description: Minutes between runs of the healthcheck container. Must + be greater than or equal to 1. + format: int32 + minimum: 1 + type: integer + required: + - command + - image + type: object + required: + - container + type: object + serviceClassIdentity: + description: ServiceClassIdentity defines a set of attributes that + are sufficient to identify a service class. A ServiceClaim whose + ServiceClassIdentity field is a subset of a RegisteredService's + keys can claim that service. + items: + description: ServiceClassIdentityItem defines an attribute that + is necessary to identify a service class. + properties: + name: + description: Name of the service class identity attribute. + type: string + value: + description: Value of the service class identity attribute. + type: string + required: + - name + - value + type: object + type: array + serviceEndpointDefinition: + description: ServiceEndpointDefinition defines a set of attributes + sufficient for a client to establish a connection to the service. + items: + description: ServiceEndpointDefinitionItem defines an attribute + that is necessary for a client to connect to a service + properties: + name: + description: Name of the service endpoint definition attribute. + type: string + value: + description: Value of the service endpoint definition attribute. + It is mutually exclusive with ValueFromSecret. + type: string + valueFromSecret: + description: Value reference of the service endpoint definition + attribute. It is mutually exclusive with Value + properties: + key: + description: Key of the secret reference field + type: string + name: + description: Name of the secret reference + type: string + required: + - key + - name + type: object + required: + - name + type: object + type: array + sla: + description: SLA defines the support level for this service. + type: string + required: + - serviceClassIdentity + - serviceEndpointDefinition + type: object + status: + description: RegisteredServiceStatus defines the observed state of RegisteredService. + properties: + state: + default: Unknown + description: State describes the current state of the service. + enum: + - Available + - Claimed + - Unknown + - Unreachable + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/app/src/main/crds/primaza.io_servicebindings.yaml b/app/src/main/crds/primaza.io_servicebindings.yaml new file mode 100644 index 00000000..031e7411 --- /dev/null +++ b/app/src/main/crds/primaza.io_servicebindings.yaml @@ -0,0 +1,243 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.11.3 + creationTimestamp: null + name: servicebindings.primaza.io +spec: + group: primaza.io + names: + kind: ServiceBinding + listKind: ServiceBindingList + plural: servicebindings + singular: servicebinding + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: the state of the ServiceBinding + jsonPath: .status.state + name: State + type: string + - jsonPath: .metadata.annotations.primaza\.io/registered-service-name + name: RegisteredService + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: ServiceBinding is the Schema for the servicebindings API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ServiceBindingSpec defines the desired state of ServiceBinding + properties: + application: + description: 'Application resource to inject the binding info. It + could be any process running within a container. From the spec: + A Service Binding resource **MUST** define a `.spec.application` + which is an `ObjectReference`-like declaration to a `PodSpec`-able + resource. A `ServiceBinding` **MAY** define the application reference + by-name or by-[label selector][ls]. A name and selector **MUST NOT** + be defined in the same reference.' + properties: + apiVersion: + description: API version of the referent. + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + selector: + description: Selector is a query that selects the workload or + workloads to bind the service to + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, NotIn, + Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If + the operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. A + single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field is "key", + the operator is "In", and the values array contains only + "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - apiVersion + - kind + type: object + x-kubernetes-validations: + - message: '`name` and `selector` can not be used at the same time' + rule: '!(has(self.name) && has(self.selector))' + - message: one among `name` and `selector` is required + rule: has(self.name) || has(self.selector) + envs: + description: Envs declares environment variables based on the ServiceEndpointDefinitionSecret + to be projected into the application + items: + description: Environment represents a key to Secret data keys and + name of the environment variable + properties: + key: + description: Secret data key + type: string + name: + description: Name of the environment variable + type: string + required: + - key + - name + type: object + type: array + serviceEndpointDefinitionSecret: + description: ServiceEndpointDefinitionSecret is the name of the secret + to project into the application + type: string + required: + - application + - serviceEndpointDefinitionSecret + type: object + status: + description: Observed status of the service binding within the namespace + properties: + conditions: + description: The status of the service binding along with reason and + type + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + connections: + description: The list of workloads the service is bound to + items: + description: Workload the service is bound to + properties: + name: + description: Name of the referent. + type: string + type: object + type: array + state: + default: Malformed + description: The state of the service binding observed + enum: + - Ready + - Malformed + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/app/src/main/crds/primaza.io_servicecatalogs.yaml b/app/src/main/crds/primaza.io_servicecatalogs.yaml new file mode 100644 index 00000000..835fdc95 --- /dev/null +++ b/app/src/main/crds/primaza.io_servicecatalogs.yaml @@ -0,0 +1,169 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.11.3 + creationTimestamp: null + name: servicecatalogs.primaza.io +spec: + group: primaza.io + names: + kind: ServiceCatalog + listKind: ServiceCatalogList + plural: servicecatalogs + singular: servicecatalog + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: ServiceCatalog is the Schema for the servicecatalogs API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ServiceCatalogSpec defines the desired state of ServiceCatalog + properties: + claimedByLabels: + description: ClaimedByLabels contains a list of services that are + claimed by labels. + items: + properties: + labels: + description: Labels labels selector for the service + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, NotIn, + Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. + If the operator is In or NotIn, the values array + must be non-empty. If the operator is Exists or + DoesNotExist, the values array must be empty. This + array is replaced during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. + A single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field is + "key", the operator is "In", and the values array contains + only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + name: + description: Name defines the name of the known service + type: string + serviceClassIdentity: + description: ServiceClassIdentity defines a set of attributes + that are sufficient to identify a service class. A ServiceClaim + whose ServiceClassIdentity field is a subset of a RegisteredService's + keys can claim that service. + items: + description: ServiceClassIdentityItem defines an attribute + that is necessary to identify a service class. + properties: + name: + description: Name of the service class identity attribute. + type: string + value: + description: Value of the service class identity attribute. + type: string + required: + - name + - value + type: object + type: array + serviceEndpointDefinitionKeys: + description: ServiceEndpointDefinitionKeys defines a set of + keys listing the information this service provides to a workload. + items: + type: string + type: array + required: + - labels + - name + - serviceClassIdentity + - serviceEndpointDefinitionKeys + type: object + type: array + services: + description: Services contains a list of services that are known to + Primaza. + items: + properties: + name: + description: Name defines the name of the known service + type: string + serviceClassIdentity: + description: ServiceClassIdentity defines a set of attributes + that are sufficient to identify a service class. A ServiceClaim + whose ServiceClassIdentity field is a subset of a RegisteredService's + keys can claim that service. + items: + description: ServiceClassIdentityItem defines an attribute + that is necessary to identify a service class. + properties: + name: + description: Name of the service class identity attribute. + type: string + value: + description: Value of the service class identity attribute. + type: string + required: + - name + - value + type: object + type: array + serviceEndpointDefinitionKeys: + description: ServiceEndpointDefinitionKeys defines a set of + keys listing the information this service provides to a workload. + items: + type: string + type: array + required: + - name + - serviceClassIdentity + - serviceEndpointDefinitionKeys + type: object + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/app/src/main/crds/primaza.io_serviceclaims.yaml b/app/src/main/crds/primaza.io_serviceclaims.yaml new file mode 100644 index 00000000..13bb5012 --- /dev/null +++ b/app/src/main/crds/primaza.io_serviceclaims.yaml @@ -0,0 +1,316 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.11.3 + creationTimestamp: null + name: serviceclaims.primaza.io +spec: + group: primaza.io + names: + kind: ServiceClaim + listKind: ServiceClaimList + plural: serviceclaims + singular: serviceclaim + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: the state of the ServiceClaim + jsonPath: .status.state + name: State + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: ServiceClaim is the Schema for the serviceclaims API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ServiceClaimSpec defines the desired state of ServiceClaim + properties: + application: + description: Rules to match workloads to bind + properties: + apiVersion: + description: API version of the referent. + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + selector: + description: Selector is a query that selects the workload or + workloads to bind the service to + properties: + matchExpressions: + description: matchExpressions is a list of label selector + requirements. The requirements are ANDed. + items: + description: A label selector requirement is a selector + that contains values, a key, and an operator that relates + the key and values. + properties: + key: + description: key is the label key that the selector + applies to. + type: string + operator: + description: operator represents a key's relationship + to a set of values. Valid operators are In, NotIn, + Exists and DoesNotExist. + type: string + values: + description: values is an array of string values. If + the operator is In or NotIn, the values array must + be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced + during a strategic merge patch. + items: + type: string + type: array + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: matchLabels is a map of {key,value} pairs. A + single {key,value} in the matchLabels map is equivalent + to an element of matchExpressions, whose key field is "key", + the operator is "In", and the values array contains only + "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + required: + - apiVersion + - kind + type: object + x-kubernetes-validations: + - message: '`name` and `selector` can not be used at the same time' + rule: '!(has(self.name) && has(self.selector))' + - message: one among `name` and `selector` is required + rule: has(self.name) || has(self.selector) + envs: + description: Envs allows projecting Service Endpoint Definition's + data as Environment Variables in the Pod + items: + description: Environment represents a key to Secret data keys and + name of the environment variable + properties: + key: + description: Secret data key + type: string + name: + description: Name of the environment variable + type: string + required: + - key + - name + type: object + type: array + serviceClassIdentity: + description: ServiceClassIdentity defines a set of attributes that + are sufficient to identify a service class. A ServiceClaim whose + ServiceClassIdentity field is a subset of a RegisteredService's + keys can claim that service. + items: + description: ServiceClassIdentityItem defines an attribute that + is necessary to identify a service class. + properties: + name: + description: Name of the service class identity attribute. + type: string + value: + description: Value of the service class identity attribute. + type: string + required: + - name + - value + type: object + type: array + x-kubernetes-validations: + - message: Value is immutable + rule: self == oldSelf + serviceEndpointDefinitionKeys: + description: ServiceEndpointDefinition defines a set of attributes + sufficient for a client to establish a connection to the service. + items: + type: string + type: array + x-kubernetes-validations: + - message: Value is immutable + rule: self == oldSelf + target: + description: Service Claim target + maxProperties: 1 + minProperties: 1 + properties: + applicationClusterContext: + properties: + clusterEnvironmentName: + type: string + namespace: + type: string + required: + - clusterEnvironmentName + - namespace + type: object + environmentTag: + description: EnvironmentTag allows the controller to search for + those application cluster environments that define such EnvironmentTag + type: string + type: object + required: + - application + - serviceClassIdentity + - serviceEndpointDefinitionKeys + type: object + status: + description: ServiceClaimStatus defines the observed state of ServiceClaim + properties: + claimID: + description: Unique ID For the ServiceClaim + type: string + conditions: + description: The status of the service binding along with reason and + type + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + registeredService: + description: Claimed RegisteredService Info + properties: + apiVersion: + description: API version of the referent. + type: string + fieldPath: + description: 'If referring to a piece of an object instead of + an entire object, this string should contain a valid JSON/Go + field access statement, such as desiredState.manifest.containers[2]. + For example, if the object reference is to a container within + a pod, this would take on a value like: "spec.containers{name}" + (where "name" refers to the name of the container that triggered + the event) or if no container name is specified "spec.containers[2]" + (container with index 2 in this pod). This syntax is chosen + only to have some well-defined way of referencing a part of + an object. TODO: this design is not final and this field is + subject to change in the future.' + type: string + kind: + description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + name: + description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names' + type: string + namespace: + description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/' + type: string + resourceVersion: + description: 'Specific resourceVersion to which this reference + is made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency' + type: string + uid: + description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids' + type: string + type: object + x-kubernetes-map-type: atomic + state: + default: Pending + description: The state of the ServiceClaim observed + enum: + - Pending + - Resolved + - Invalid + type: string + required: + - state + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/app/src/main/crds/primaza.io_serviceclasses.yaml b/app/src/main/crds/primaza.io_serviceclasses.yaml new file mode 100644 index 00000000..aa167880 --- /dev/null +++ b/app/src/main/crds/primaza.io_serviceclasses.yaml @@ -0,0 +1,266 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.11.3 + creationTimestamp: null + name: serviceclasses.primaza.io +spec: + group: primaza.io + names: + kind: ServiceClass + listKind: ServiceClassList + plural: serviceclasses + singular: serviceclass + scope: Namespaced + versions: + - name: v1alpha1 + schema: + openAPIV3Schema: + description: ServiceClass is the Schema for the serviceclasses API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ServiceClassSpec defines the desired state of ServiceClass + properties: + constraints: + description: Constraints defines under which circumstances the ServiceClass + may be used. + properties: + environments: + description: Environments defines the environments that the RegisteredService + may be used in. + items: + type: string + type: array + type: object + healthCheck: + description: HealthCheck sets the default health check for generated + registered services + properties: + container: + description: Container defines a container that will run a check + against the ServiceEndpointDefinition to determine connectivity + and access. + properties: + command: + description: Command to execute in the container to run the + test + items: + type: string + type: array + image: + description: Container image with the client to run the test + type: string + minutes: + default: 5 + description: Minutes between runs of the healthcheck container. Must + be greater than or equal to 1. + format: int32 + minimum: 1 + type: integer + required: + - command + - image + type: object + required: + - container + type: object + resource: + description: Resource defines the resource type to be used to convert + into Registered Services + properties: + apiVersion: + description: APIVersion of the underlying service resource + type: string + kind: + description: Kind of the underlying service resource + type: string + serviceEndpointDefinitionMappings: + description: ServiceEndpointDefinitionMappings defines how a key-value + mapping projected into services may be constructed. + properties: + resourceFields: + items: + properties: + jsonPath: + description: JsonPath defines where data lives in the + service resource. This query must resolve to a single + value (e.g. not an array of values). + type: string + name: + description: Name of the data referred to + type: string + secret: + default: true + description: Secret indicates whether or not the mapping + data needs to be stored in a secret. + type: boolean + required: + - jsonPath + - name + type: object + type: array + secretRefFields: + items: + properties: + name: + description: Name of the data referred to + type: string + secretKey: + description: SecretKey defines a constant value or a + JsonPath used to extract from resource's specification + the Key to be copied from the linked secret + maxProperties: 1 + minProperties: 1 + properties: + constant: + description: Constant is a constant value for the + field + type: string + jsonPath: + description: JsonPathExpr represents a jsonPath + for extracting the field + type: string + type: object + secretName: + description: SecretName defines a constant value or + a JsonPath used to extract from resource's specification + the name of a linked secret + maxProperties: 1 + minProperties: 1 + properties: + constant: + description: Constant is a constant value for the + field + type: string + jsonPath: + description: JsonPathExpr represents a jsonPath + for extracting the field + type: string + type: object + required: + - name + - secretKey + - secretName + type: object + type: array + type: object + required: + - apiVersion + - kind + - serviceEndpointDefinitionMappings + type: object + serviceClassIdentity: + description: ServiceClassIdentity defines a set of attributes that + are sufficient to identify a service class. A ServiceClaim whose + ServiceClassIdentity field is a subset of a RegisteredService's + keys can claim that service. + items: + description: ServiceClassIdentityItem defines an attribute that + is necessary to identify a service class. + properties: + name: + description: Name of the service class identity attribute. + type: string + value: + description: Value of the service class identity attribute. + type: string + required: + - name + - value + type: object + type: array + required: + - resource + - serviceClassIdentity + type: object + status: + description: ServiceClassStatus defines the observed state of ServiceClass + properties: + conditions: + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + properties: + lastTransitionTime: + description: lastTransitionTime is the last time the condition + transitioned from one status to another. This should be when + the underlying condition changed. If that is not known, then + using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: message is a human readable message indicating + details about the transition. This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: observedGeneration represents the .metadata.generation + that the condition was set based upon. For instance, if .metadata.generation + is currently 12, but the .status.conditions[x].observedGeneration + is 9, the condition is out of date with respect to the current + state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: reason contains a programmatic identifier indicating + the reason for the condition's last transition. Producers + of specific condition types may define expected values and + meanings for this field, and whether the values are considered + a guaranteed API. The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + --- Many .condition.type values are consistent across resources + like Available, but because arbitrary conditions can be useful + (see .node.status.conditions), the ability to deconflict is + important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/app/src/main/java/io/halkyon/services/KubernetesClientService.java b/app/src/main/java/io/halkyon/services/KubernetesClientService.java index 7951902c..d6e553a5 100644 --- a/app/src/main/java/io/halkyon/services/KubernetesClientService.java +++ b/app/src/main/java/io/halkyon/services/KubernetesClientService.java @@ -244,13 +244,17 @@ public void createCrossplaneHelmRelease(Cluster cluster, io.halkyon.model.Servic // Create Release object ReleaseBuilder release = new ReleaseBuilder(); release.withApiVersion("helm.crossplane.io").withKind("v1beta1").withNewMetadata().withName(service.helmChart) - .endMetadata().withNewSpec().withNewV1beta1ForProvider().addNewV1beta1Set().withName("auth.database") - .withValue("fruits_database").endV1beta1Set().addNewV1beta1Set().withName("auth.username") - .withValue("healthy").endV1beta1Set().addNewV1beta1Set().withName("auth.password").withValue("healthy") - .endV1beta1Set().withNamespace(service.namespace).withWait(true).withNewV1beta1Chart() - .withName(service.helmChart).withRepository(service.helmRepo).withVersion(service.helmChartVersion) - .endV1beta1Chart().endV1beta1ForProvider().withNewV1beta1ProviderConfigRef().withName("helm-provider") - .endV1beta1ProviderConfigRef().endSpec(); + .endMetadata().withNewSpec().withNewForProvider().addNewSet().withName("auth.database") + .withValue("fruits_database").endSet().addNewSet().withName("auth.username").withValue("healthy") + .endSet().addNewSet().withName("auth.password").withValue("healthy").endSet() + .withNamespace(service.namespace).withWait(true).withNewChart().withName(service.helmChart) + .withRepository(service.helmRepo).withVersion(service.helmChartVersion).endChart().endForProvider() + .withNewProviderConfigRef().withName("helm-provider").endProviderConfigRef() + /* + * .withManagementPolicies(ReleaseSpec.ManagementPolicies.CREATE, ReleaseSpec.ManagementPolicies.DELETE, + * ReleaseSpec.ManagementPolicies.UPDATE, ReleaseSpec.ManagementPolicies.OBSERVE) + */ + .endSpec(); // TODO: Logic to be reviewed as we have 2 use cases: // Service(s) instances has been discovered in cluster x.y.z diff --git a/pom.xml b/pom.xml index bbdf1565..e2a23e4d 100644 --- a/pom.xml +++ b/pom.xml @@ -36,14 +36,15 @@ UTF-8 quarkus-bom io.quarkus - 3.6.1 + 3.8.3 3.2.5 3.9.0 2.23.0 1.9.0 1.18.30 - 0.101.3 - + 0.200.0 + + 6.12.1 true format sort diff --git a/scenario.md b/scenario.md index 7acee7bb..1c1c90ee 100644 --- a/scenario.md +++ b/scenario.md @@ -29,8 +29,10 @@ export VM_IP=127.0.0.1 or export VM_IP=$(ifconfig eth0 | grep 'inet ' | cut -d: export VAULT_URL=http://vault-internal.vault:8200 export PRIMAZA_URL=primaza.$VM_IP.nip.io export PRIMAZA_IMAGE_NAME=kind-registry:5000/local/primaza-app +export PRIMAZA_NAMESPACE=primaza curl -s -L "https://raw.githubusercontent.com/snowdrop/k8s-infra/main/kind/kind.sh" | bash -s install --delete-kind-cluster +curl -s -L "https://raw.githubusercontent.com/snowdrop/k8s-infra/main/kind/registry.sh" | bash -s install --registry-name kind-registry kubectl rollout status deployment/ingress-nginx-controller -n ingress $(pwd)/scripts/vault.sh @@ -49,8 +51,24 @@ $(pwd)/scripts/primaza.sh build $(pwd)/scripts/primaza.sh localdeploy export KIND_URL=https://kubernetes.default.svc -$(pwd)/scripts/data/services.sh -$(pwd)/scripts/data/credentials.sh + +$(pwd)/scripts/data/cluster.sh url=$PRIMAZA_URL kube_context=kind kind_url="https://kubernetes.default.svc" environment=dev ns_to_exclude="default,kube-system,ingress,pipelines-as-code,local-path-storage,crossplane-system,primaza,tekton-pipelines,tekton-pipelines-resolvers,vault" + +$(pwd)/scripts/data/services.sh url=$PRIMAZA_URL service_name=postgresql version=14.5 installable=on type=postgresql endpoint=tcp:5432 helm_repo="https://charts.bitnami.com/bitnami&helmChart=postgresql&helmChartVersion=11.9.13" +$(pwd)/scripts/data/services.sh url=$PRIMAZA_URL service_name=mysql version=8.0 type=mysql endpoint=tcp:3306 +$(pwd)/scripts/data/services.sh url=$PRIMAZA_URL service_name=activemq-artemis version=2.26 type=activemq endpoint=tcp:8161 +$(pwd)/scripts/data/services.sh url=$PRIMAZA_URL service_name=mariadb version=10.9 type=mariadb endpoint=tcp:3306 + +$(pwd)/scripts/data/credentials.sh url=$PRIMAZA_URL credential_type=vault credential_name=fruits_database-vault-creds service_name=postgresql vault_kv=primaza/fruits + +# Install atomic fruits +$(pwd)/scripts/atomic-fruits.sh deploy + +# Create the claim +$(pwd)/scripts/data/claims.sh url=$PRIMAZA_URL claim_name=fruits-claim description=postgresql-fruits-db requested_service=postgresql-14.5 application_id=1 + +# Do the binding +$(pwd)/scripts/data/bind_application.sh application_name=atomic-fruits claim_name=fruits-claim ``` ## Access the cluster using mvn quarkus:dev diff --git a/scripts/atomic-fruits.sh b/scripts/atomic-fruits.sh index d4c76918..9b12582a 100755 --- a/scripts/atomic-fruits.sh +++ b/scripts/atomic-fruits.sh @@ -24,7 +24,7 @@ DB_RELEASE_NAME=postgresql DB_VERSION=11.9.13 # Parameters to play the demo -TYPE_SPEED=${TYPE_SPEED:=200} +export TYPE_SPEED=${TYPE_SPEED:=400} NO_WAIT=true function remove() { diff --git a/scripts/crossplane.sh b/scripts/crossplane.sh index 6304fc0c..6bcdcfcb 100755 --- a/scripts/crossplane.sh +++ b/scripts/crossplane.sh @@ -50,7 +50,7 @@ kind: Provider metadata: name: kubernetes-provider spec: - package: "crossplane/provider-kubernetes:main" + package: "xpkg.upbound.io/crossplane-contrib/provider-kubernetes:v0.11.4" controllerConfigRef: name: debug-config EOF @@ -81,9 +81,10 @@ kind: Provider metadata: name: helm-provider spec: - package: crossplanecontrib/provider-helm:v0.14.0 + # Use a more recent version of the provider supporting the managementPolicies: https://github.com/crossplane-contrib/provider-helm/issues/209 + package: xpkg.upbound.io/crossplane-contrib/provider-helm:v0.18.1 controllerConfigRef: - name: debug-config + name: debug-config EOF cmdExec "kubectl wait provider.pkg.crossplane.io/helm-provider --for condition=Healthy=true --timeout=300s" diff --git a/scripts/vault.sh b/scripts/vault.sh index 3037eca7..fe79702f 100755 --- a/scripts/vault.sh +++ b/scripts/vault.sh @@ -3,6 +3,10 @@ SCRIPTS_DIR="$(cd $(dirname "${BASH_SOURCE}") && pwd)" source ${SCRIPTS_DIR}/common.sh +# Parameters to play the demo +export TYPE_SPEED=400 +NO_WAIT=true + #################### ## Global parameters ##################### @@ -196,13 +200,13 @@ EOF } function registerUser() { - if [ -v 1 ]; then + if [ -n "$1" ]; then VAULT_USER=$1 fi - if [ -v 2 ]; then + if [ -n "$2" ]; then VAULT_PASSWORD=$2 fi - if [ -v 3 ]; then + if [ -n "$3" ]; then VAULT_POLICY_NAME=$3 fi @@ -217,15 +221,15 @@ function putHelloKey() { } function putKey() { - if [ -v 1 ]; then + if [ -n "$1" ]; then # primaza KV_APP_NAME=$1 fi - if [ -v 2 ]; then + if [ -n "$2" ]; then # fruits KV_KEY=$2 fi - if [ -v 3 ]; then + if [ -n "$3" ]; then # username=healthy password=healthy database=fruits_database KV_ENTRIES=$3 fi