From 9d42eb54f8e64bdb95ad8970e1d0385ca641dc36 Mon Sep 17 00:00:00 2001 From: jeremy cotineau Date: Fri, 23 Feb 2024 11:19:20 +0100 Subject: [PATCH] SONAR-21727 implement mpdev verify tests command NO-JIRA temporary fix missing application crd in test waiting for https://github.com/datreeio/CRDs-catalog/pull/276 merge update partner name and partner id update partner id and fix tests --- .cirrus/unit_helm_compatibility_test.sh | 2 +- .../sonarqube-dce/templates/application.yml | 8 +- .../templates/tests/sonarqube-test.yaml | 2 +- google-cloud-marketplace-k8s-app/Dockerfile | 14 + google-cloud-marketplace-k8s-app/README.md | 1 + .../data-test/schema.yaml | 78 +++ google-cloud-marketplace-k8s-app/schema.yaml | 8 +- .../app.k8s.io/application_v1alpha1.json | 158 ++++++ .../app.k8s.io/application_v1beta1.json | 513 ++++++++++++++++++ .../sonarqube-dce/application-values.yaml | 3 +- 10 files changed, 780 insertions(+), 7 deletions(-) create mode 100644 google-cloud-marketplace-k8s-app/data-test/schema.yaml create mode 100644 tests/test-crds/app.k8s.io/application_v1alpha1.json create mode 100644 tests/test-crds/app.k8s.io/application_v1beta1.json diff --git a/.cirrus/unit_helm_compatibility_test.sh b/.cirrus/unit_helm_compatibility_test.sh index 9e8d0dc5c..c1cad82b3 100755 --- a/.cirrus/unit_helm_compatibility_test.sh +++ b/.cirrus/unit_helm_compatibility_test.sh @@ -16,6 +16,6 @@ echo 'Running unit compatibility tests for Kubernetes version' $KUBE_VERSION for file in "$STATIC_TEST_FOLDER"/*; do TEST_CASE_NAME=$(basename "$file") echo 'Entering test for' $TEST_CASE_NAME - helm template --kube-version $KUBE_VERSION --dry-run --debug -f "$file" $TEST_CASE_NAME . | kubeconform --kubernetes-version $KUBE_VERSION --summary --strict + helm template --kube-version $KUBE_VERSION --dry-run --debug -f "$file" $TEST_CASE_NAME . | kubeconform --kubernetes-version $KUBE_VERSION --summary --strict -schema-location default -schema-location "../../tests/test-crds/app.k8s.io/application_v1beta1.json" echo 'Ending test for' $TEST_CASE_NAME done \ No newline at end of file diff --git a/charts/sonarqube-dce/templates/application.yml b/charts/sonarqube-dce/templates/application.yml index e59132e94..3623c7976 100644 --- a/charts/sonarqube-dce/templates/application.yml +++ b/charts/sonarqube-dce/templates/application.yml @@ -1,4 +1,4 @@ -{{- if and .Values.application .Values.application.create }} # declared in schema.yaml +{{- if .Values.gcp_marketplace }} # declared in google-cloud-marketplace-k8s-app value folder apiVersion: app.k8s.io/v1beta1 kind: Application metadata: @@ -8,7 +8,7 @@ metadata: app.kubernetes.io/name: "{{ .Release.Name }}" annotations: #to update with partner metadata - marketplace.cloud.google.com/deploy-info: '{"partner_id": "partner", "product_id": "sonarqube-dce", "partner_name": "Partner"}' + marketplace.cloud.google.com/deploy-info: '{"partner_id": "sonarsource-public", "product_id": "official-sonarqube-data-center-edition", "partner_name": "SonarSource SA"}' kubernetes-engine.cloud.google.com/icon: data:image/png;base64,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 spec: descriptor: @@ -34,7 +34,9 @@ spec: For extended documentation on how to configure this app, please refer to the [official SonarQube helm chart documentation](https://artifacthub.io/packages/helm/sonarqube/sonarqube-dce) and the main [README](https://github.com/SonarSource/helm-chart-sonarqube/blob/master/README.md) selector: matchLabels: - app.kubernetes.io/name: "{{ .Release.Name }}" + # we should use app.kubernetes.io/name, which should be set by default to all pods, but this is not working. + # so we rely on our own custom release field + release: "{{ .Release.Name }}" addOwnerRef: true componentKinds: - group: v1 diff --git a/charts/sonarqube-dce/templates/tests/sonarqube-test.yaml b/charts/sonarqube-dce/templates/tests/sonarqube-test.yaml index 2ef873e28..7b4b7461c 100644 --- a/charts/sonarqube-dce/templates/tests/sonarqube-test.yaml +++ b/charts/sonarqube-dce/templates/tests/sonarqube-test.yaml @@ -30,7 +30,7 @@ spec: '--waitretry=1', '--timeout=5', '-t', - '12', + '1200', '-qO-', '{{ template "sonarqube.fullname" . }}:{{ .Values.service.internalPort }}/api/system/status' ] diff --git a/google-cloud-marketplace-k8s-app/Dockerfile b/google-cloud-marketplace-k8s-app/Dockerfile index 62c40f850..f29aafda2 100644 --- a/google-cloud-marketplace-k8s-app/Dockerfile +++ b/google-cloud-marketplace-k8s-app/Dockerfile @@ -1,6 +1,9 @@ ARG FROM=gcr.io/cloud-marketplace-tools/k8s/deployer_helm:latest FROM $FROM +ENV WAIT_FOR_READY_TIMEOUT 1200 +ENV TESTER_TIMEOUT 1200 + COPY charts/sonarqube-dce /tmp/chart.tmp/sonarqube-dce RUN cd /tmp \ && mv chart.tmp/* chart \ @@ -11,9 +14,20 @@ RUN cd /tmp \ COPY google-cloud-marketplace-k8s-app/schema.yaml /data/schema.yaml # Provide registry prefix and tag for default values for images. +# Might not be needed on V2 schema ARG REGISTRY ARG TAG RUN cat /data/schema.yaml \ | env -i "REGISTRY=$REGISTRY" "TAG=$TAG" envsubst \ > /data/schema.yaml.new \ && mv /data/schema.yaml.new /data/schema.yaml + +COPY google-cloud-marketplace-k8s-app/data-test/schema.yaml /data-test/schema.yaml +# Provide registry prefix and tag for default values for images. +# Might not be needed on V2 schema +ARG REGISTRY +ARG TAG +RUN cat /data-test/schema.yaml \ + | env -i "REGISTRY=$REGISTRY" "TAG=$TAG" envsubst \ + > /data-test/schema.yaml.new \ + && mv /data-test/schema.yaml.new /data-test/schema.yaml diff --git a/google-cloud-marketplace-k8s-app/README.md b/google-cloud-marketplace-k8s-app/README.md index 494c4c6bb..f5919f367 100644 --- a/google-cloud-marketplace-k8s-app/README.md +++ b/google-cloud-marketplace-k8s-app/README.md @@ -18,6 +18,7 @@ export VERSION=10.4.0 export MINOR_VERSION=$(echo $VERSION | cut -d. -f1,2) # Deployer does not care about patch version. see [here](https://github.com/GoogleCloudPlatform/marketplace-k8s-app-tools/blob/master/docs/building-deployer-helm.md#images-in-staging-gcr) docker build -f google-cloud-marketplace-k8s-app/Dockerfile --tag $REGISTRY/$APP_NAME/deployer:$MINOR_VERSION . +docker push $REGISTRY/$APP_NAME/deployer:$MINOR_VERSION ``` With the deployer being built, one can deploy the app as is, with diff --git a/google-cloud-marketplace-k8s-app/data-test/schema.yaml b/google-cloud-marketplace-k8s-app/data-test/schema.yaml new file mode 100644 index 000000000..8e7d28923 --- /dev/null +++ b/google-cloud-marketplace-k8s-app/data-test/schema.yaml @@ -0,0 +1,78 @@ +x-google-marketplace: + clusterConstraints: + istio: + type: UNSUPPORTED + schemaVersion: v2 + applicationApiVersion: v1beta1 + publishedVersion: '10.4.0' + publishedVersionMetadata: + releaseNote: >- + A first release. + images: + '': + properties: + ApplicationNodes.image.repository: + type: REPO_WITH_REGISTRY + ApplicationNodes.image.tag: + type: TAG + sonarqube-dce-search: + properties: + searchNodes.image.repository: + type: REPO_WITH_REGISTRY + searchNodes.image.tag: + type: TAG + +properties: + name: + type: string + x-google-marketplace: + type: NAME + namespace: + type: string + x-google-marketplace: + type: NAMESPACE + appUid: + type: string + x-google-marketplace: + type: APPLICATION_UID + applicationUid: + generatedProperties: + createApplicationBoolean: application.create + ApplicationNodes.jwtSecret: + title: JWT Token for app authentication + description: A HS256 key encoded with base64 (This value must be set before installing the app, see documentation for more details) + maxLength: 44 + type: string + default: dZ0EB0KxnF++nr5+4vfTCaun/eWbv6gOoXodiAMqcFo= + x-google-marketplace: + type: MASKED_FIELD + postgresql.enabled: + title: Enable embedeed PostgreSQL + description: If true, PostgreSQL will be installed (not recommended for production use case) + type: boolean + default: true + jdbcOverwrite.enable: + title: Enable external DB configuration + description: If true, the JDBC URL, username and password will be used to connect to the database. Make sure enable embedeed PostgreSQL is set to false + type: boolean + default: false + jdbcOverwrite.jdbcUrl: + title: JDBC URL + description: The JDBC URL to connect to the database + type: string + default: '' + jdbcOverwrite.jdbcUsername: + title: JDBC Username + description: The username to connect to the database + type: string + default: '' + jdbcOverwrite.jdbcPassword: + title: JDBC Password + description: The password to connect to the database + type: string + default: '' + +required: +- name +- namespace +- ApplicationNodes.jwtSecret diff --git a/google-cloud-marketplace-k8s-app/schema.yaml b/google-cloud-marketplace-k8s-app/schema.yaml index 0749525de..62eadf6d5 100644 --- a/google-cloud-marketplace-k8s-app/schema.yaml +++ b/google-cloud-marketplace-k8s-app/schema.yaml @@ -70,7 +70,13 @@ properties: description: The password to connect to the database type: string default: '' - + gcp_marketplace: + title: GCP Marketplace enabled + description: this flag indicate to the chart that it runs as a gcp marketplace application + type: string + default: 'true' + enum: + - 'true' required: - name - namespace diff --git a/tests/test-crds/app.k8s.io/application_v1alpha1.json b/tests/test-crds/app.k8s.io/application_v1alpha1.json new file mode 100644 index 000000000..9a6e6b418 --- /dev/null +++ b/tests/test-crds/app.k8s.io/application_v1alpha1.json @@ -0,0 +1,158 @@ +{ + "description": "Application is the Schema for the applications 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": "ApplicationSpec defines the specification for an Application.", + "properties": { + "assemblyPhase": { + "type": "string" + }, + "componentKinds": { + "description": "ComponentGroupKinds is a list of Kinds for Application's components (e.g. Deployments, Pods, Services, CRDs). It can be used in conjunction with the Application's Selector to list or watch the Applications components.", + "items": { + "description": "GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying concepts during lookup stages without having partially valid types", + "properties": { + "group": { + "type": "string" + }, + "kind": { + "type": "string" + } + }, + "type": "object", + "additionalProperties": false + }, + "type": "array" + }, + "description": { + "type": "string" + }, + "info": { + "description": "Info contains human readable key,value pairs for the Application.", + "items": { + "description": "InfoItem is a human readable key,value pair containing important information about how to access the Application.", + "properties": { + "name": { + "description": "Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names", + "type": "string" + }, + "value": { + "type": "string" + } + }, + "type": "object", + "additionalProperties": false + }, + "type": "array" + }, + "keywords": { + "items": { + "type": "string" + }, + "type": "array" + }, + "links": { + "items": { + "properties": { + "description": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "additionalProperties": false + }, + "type": "array" + }, + "maintainers": { + "items": { + "properties": { + "email": { + "type": "string" + }, + "name": { + "type": "string" + }, + "url": { + "type": "string" + } + }, + "type": "object", + "additionalProperties": false + }, + "type": "array" + }, + "notes": { + "type": "string" + }, + "owners": { + "items": { + "type": "string" + }, + "type": "array" + }, + "selector": { + "properties": { + "matchExpressions": { + "items": { + "properties": { + "key": { + "type": "string" + }, + "operator": { + "type": "string" + }, + "values": { + "items": { + "type": "string" + }, + "type": "array" + } + }, + "type": "object", + "additionalProperties": false + }, + "type": "array" + }, + "matchLabels": { + "type": "object" + } + }, + "type": "object", + "additionalProperties": false + }, + "type": { + "type": "string" + }, + "version": { + "type": "string" + } + }, + "type": "object", + "additionalProperties": false + }, + "status": { + "properties": { + "observedGeneration": { + "type": "integer" + } + }, + "type": "object", + "additionalProperties": false + } + }, + "type": "object" +} diff --git a/tests/test-crds/app.k8s.io/application_v1beta1.json b/tests/test-crds/app.k8s.io/application_v1beta1.json new file mode 100644 index 000000000..8781669fe --- /dev/null +++ b/tests/test-crds/app.k8s.io/application_v1beta1.json @@ -0,0 +1,513 @@ +{ + "description": "Application is the Schema for the applications 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": "ApplicationSpec defines the specification for an Application.", + "properties": { + "addOwnerRef": { + "description": "AddOwnerRef objects - flag to indicate if we need to add OwnerRefs to matching objects Matching is done by using Selector to query all ComponentGroupKinds", + "type": "boolean" + }, + "assemblyPhase": { + "description": "AssemblyPhase represents the current phase of the application's assembly. An empty value is equivalent to \"Succeeded\".", + "type": "string" + }, + "componentKinds": { + "description": "ComponentGroupKinds is a list of Kinds for Application's components (e.g. Deployments, Pods, Services, CRDs). It can be used in conjunction with the Application's Selector to list or watch the Applications components.", + "items": { + "description": "GroupKind specifies a Group and a Kind, but does not force a version. This is useful for identifying concepts during lookup stages without having partially valid types", + "properties": { + "group": { + "type": "string" + }, + "kind": { + "type": "string" + } + }, + "required": [ + "group", + "kind" + ], + "type": "object", + "additionalProperties": false + }, + "type": "array" + }, + "descriptor": { + "description": "Descriptor regroups information and metadata about an application.", + "properties": { + "description": { + "description": "Description is a brief string description of the Application.", + "type": "string" + }, + "icons": { + "description": "Icons is an optional list of icons for an application. Icon information includes the source, size, and mime type.", + "items": { + "description": "ImageSpec contains information about an image used as an icon.", + "properties": { + "size": { + "description": "(optional) The size of the image in pixels (e.g., 25x25).", + "type": "string" + }, + "src": { + "description": "The source for image represented as either an absolute URL to the image or a Data URL containing the image. Data URLs are defined in RFC 2397.", + "type": "string" + }, + "type": { + "description": "(optional) The mine type of the image (e.g., \"image/png\").", + "type": "string" + } + }, + "required": [ + "src" + ], + "type": "object", + "additionalProperties": false + }, + "type": "array" + }, + "keywords": { + "description": "Keywords is an optional list of key words associated with the application (e.g. MySQL, RDBMS, database).", + "items": { + "type": "string" + }, + "type": "array" + }, + "links": { + "description": "Links are a list of descriptive URLs intended to be used to surface additional documentation, dashboards, etc.", + "items": { + "description": "Link contains information about an URL to surface documentation, dashboards, etc.", + "properties": { + "description": { + "description": "Description is human readable content explaining the purpose of the link.", + "type": "string" + }, + "url": { + "description": "Url typically points at a website address.", + "type": "string" + } + }, + "type": "object", + "additionalProperties": false + }, + "type": "array" + }, + "maintainers": { + "description": "Maintainers is an optional list of maintainers of the application. The maintainers in this list maintain the the source code, images, and package for the application.", + "items": { + "description": "ContactData contains information about an individual or organization.", + "properties": { + "email": { + "description": "Email is the email address.", + "type": "string" + }, + "name": { + "description": "Name is the descriptive name.", + "type": "string" + }, + "url": { + "description": "Url could typically be a website address.", + "type": "string" + } + }, + "type": "object", + "additionalProperties": false + }, + "type": "array" + }, + "notes": { + "description": "Notes contain a human readable snippets intended as a quick start for the users of the Application. CommonMark markdown syntax may be used for rich text representation.", + "type": "string" + }, + "owners": { + "description": "Owners is an optional list of the owners of the installed application. The owners of the application should be contacted in the event of a planned or unplanned disruption affecting the application.", + "items": { + "description": "ContactData contains information about an individual or organization.", + "properties": { + "email": { + "description": "Email is the email address.", + "type": "string" + }, + "name": { + "description": "Name is the descriptive name.", + "type": "string" + }, + "url": { + "description": "Url could typically be a website address.", + "type": "string" + } + }, + "type": "object", + "additionalProperties": false + }, + "type": "array" + }, + "type": { + "description": "Type is the type of the application (e.g. WordPress, MySQL, Cassandra).", + "type": "string" + }, + "version": { + "description": "Version is an optional version indicator for the Application.", + "type": "string" + } + }, + "type": "object", + "additionalProperties": false + }, + "info": { + "description": "Info contains human readable key,value pairs for the Application.", + "items": { + "description": "InfoItem is a human readable key,value pair containing important information about how to access the Application.", + "properties": { + "name": { + "description": "Name is a human readable title for this piece of information.", + "type": "string" + }, + "type": { + "description": "Type of the value for this InfoItem.", + "type": "string" + }, + "value": { + "description": "Value is human readable content.", + "type": "string" + }, + "valueFrom": { + "description": "ValueFrom defines a reference to derive the value from another source.", + "properties": { + "configMapKeyRef": { + "description": "Selects a key of a ConfigMap.", + "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" + }, + "key": { + "description": "The key to select.", + "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", + "additionalProperties": false + }, + "ingressRef": { + "description": "Select an Ingress.", + "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" + }, + "host": { + "description": "The optional host to select.", + "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" + }, + "path": { + "description": "The optional HTTP path.", + "type": "string" + }, + "protocol": { + "description": "Protocol for the ingress", + "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", + "additionalProperties": false + }, + "secretKeyRef": { + "description": "Selects a key of a Secret.", + "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" + }, + "key": { + "description": "The key to select.", + "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", + "additionalProperties": false + }, + "serviceRef": { + "description": "Select a Service.", + "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" + }, + "path": { + "description": "The optional HTTP path.", + "type": "string" + }, + "port": { + "description": "The optional port to select.", + "format": "int32", + "type": "integer" + }, + "protocol": { + "description": "Protocol for the service", + "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", + "additionalProperties": false + }, + "type": { + "description": "Type of source.", + "type": "string" + } + }, + "type": "object", + "additionalProperties": false + } + }, + "type": "object", + "additionalProperties": false + }, + "type": "array" + }, + "selector": { + "description": "Selector is a label query over kinds that created by the application. It must match the component objects' labels. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors", + "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", + "additionalProperties": false + }, + "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", + "additionalProperties": false + } + }, + "type": "object", + "additionalProperties": false + }, + "status": { + "description": "ApplicationStatus defines controller's the observed state of Application", + "properties": { + "components": { + "description": "Object status array for all matching objects", + "items": { + "description": "ObjectStatus is a generic status holder for objects", + "properties": { + "group": { + "description": "Object group", + "type": "string" + }, + "kind": { + "description": "Kind of object", + "type": "string" + }, + "link": { + "description": "Link to object", + "type": "string" + }, + "name": { + "description": "Name of object", + "type": "string" + }, + "status": { + "description": "Status. Values: InProgress, Ready, Unknown", + "type": "string" + } + }, + "type": "object", + "additionalProperties": false + }, + "type": "array" + }, + "componentsReady": { + "description": "ComponentsReady: status of the components in the format ready/total", + "type": "string" + }, + "conditions": { + "description": "Conditions represents the latest state of the object", + "items": { + "description": "Condition describes the state of an object at a certain point.", + "properties": { + "lastTransitionTime": { + "description": "Last time the condition transitioned from one status to another.", + "format": "date-time", + "type": "string" + }, + "lastUpdateTime": { + "description": "Last time the condition was probed", + "format": "date-time", + "type": "string" + }, + "message": { + "description": "A human readable message indicating details about the transition.", + "type": "string" + }, + "reason": { + "description": "The reason for the condition's last transition.", + "type": "string" + }, + "status": { + "description": "Status of the condition, one of True, False, Unknown.", + "type": "string" + }, + "type": { + "description": "Type of condition.", + "type": "string" + } + }, + "required": [ + "status", + "type" + ], + "type": "object", + "additionalProperties": false + }, + "type": "array" + }, + "observedGeneration": { + "description": "ObservedGeneration is the most recent generation observed. It corresponds to the Object's generation, which is updated on mutation by the API Server.", + "format": "int64", + "type": "integer" + } + }, + "type": "object", + "additionalProperties": false + } + }, + "type": "object" +} diff --git a/tests/unit-compatibility-test/sonarqube-dce/application-values.yaml b/tests/unit-compatibility-test/sonarqube-dce/application-values.yaml index 3123b8101..66a6a848f 100644 --- a/tests/unit-compatibility-test/sonarqube-dce/application-values.yaml +++ b/tests/unit-compatibility-test/sonarqube-dce/application-values.yaml @@ -1 +1,2 @@ -application.create: true \ No newline at end of file +#placeholder value to trigger the creation of the application (related to google cloud marketplace k8s app +gcp_marketplace: true \ No newline at end of file