diff --git a/.github/workflows/cd-pipeline.yml b/.github/workflows/cd-pipeline.yml
index 0e8e9de3bf..4a84f3663b 100644
--- a/.github/workflows/cd-pipeline.yml
+++ b/.github/workflows/cd-pipeline.yml
@@ -45,6 +45,7 @@ on: # rebuild any PRs and main branch changes
- 'bitnami/kiam/**'
- 'bitnami/kibana/**'
- 'bitnami/kong/**'
+ - 'bitnami/kubeapps/**'
- 'bitnami/kube-prometheus/**'
- 'bitnami/kube-state-metrics/**'
- 'bitnami/kubernetes-event-exporter/**'
diff --git a/.vib/kubeapps/cypress/cypress.json b/.vib/kubeapps/cypress/cypress.json
new file mode 100644
index 0000000000..3dd1c48bbe
--- /dev/null
+++ b/.vib/kubeapps/cypress/cypress.json
@@ -0,0 +1,8 @@
+{
+ "baseUrl": "http://localhost/",
+ "env": {
+ "repoName": "bitnami",
+ "repoURL": "https://charts.bitnami.com/bitnami"
+ },
+ "defaultCommandTimeout": 30000
+}
diff --git a/.vib/kubeapps/cypress/cypress/fixtures/releases.json b/.vib/kubeapps/cypress/cypress/fixtures/releases.json
new file mode 100644
index 0000000000..a6fee047e7
--- /dev/null
+++ b/.vib/kubeapps/cypress/cypress/fixtures/releases.json
@@ -0,0 +1,6 @@
+{
+ "newRelease": {
+ "application": "apache",
+ "name": "oatmeal"
+ }
+}
diff --git a/.vib/kubeapps/cypress/cypress/integration/kubeapps_spec.js b/.vib/kubeapps/cypress/cypress/integration/kubeapps_spec.js
new file mode 100644
index 0000000000..adbfa77cad
--- /dev/null
+++ b/.vib/kubeapps/cypress/cypress/integration/kubeapps_spec.js
@@ -0,0 +1,32 @@
+///
+import { random } from '../support/utils';
+
+it('allows managing a helm chart release', () => {
+ cy.login();
+
+ // Prefer UI interaction over direct navigation because the URL includes references to
+ // the ns name, which is only known at runtime.
+ cy.contains('Catalog').click();
+
+ cy.fixture('releases').then((releases) => {
+ const releaseName = `${releases.newRelease.name}-${random}`
+
+ cy.contains('div.card', releases.newRelease.application).click();
+ cy.contains(Cypress.env('repoName'));
+ cy.contains(Cypress.env('repoURL'));
+ cy.contains('Deploy').click();
+
+ cy.get('#releaseName').type(releaseName);
+ cy.contains('Deploy').click();
+ cy.get('.application-status-pie-chart-title', { timeout: (Cypress.config('defaultCommandTimeout') * 3) }).should(
+ 'have.text',
+ 'Ready'
+ );
+
+ cy.contains('Delete').click();
+ cy.get('cds-modal-actions').within(() => {
+ cy.contains('Delete').click();
+ });
+ cy.contains(releaseName).should('not.exist');
+ });
+});
diff --git a/.vib/kubeapps/cypress/cypress/support/commands.js b/.vib/kubeapps/cypress/cypress/support/commands.js
new file mode 100644
index 0000000000..bd40884329
--- /dev/null
+++ b/.vib/kubeapps/cypress/cypress/support/commands.js
@@ -0,0 +1,21 @@
+const COMMAND_DELAY = 2000;
+
+for (const command of ['click']) {
+ Cypress.Commands.overwrite(command, (originalFn, ...args) => {
+ const origVal = originalFn(...args);
+
+ return new Promise((resolve) => {
+ setTimeout(() => {
+ resolve(origVal);
+ }, COMMAND_DELAY);
+ });
+ });
+}
+
+Cypress.Commands.add('login', () => {
+ cy.request('/static/token/token.txt').then(res => {
+ cy.visit('/login');
+ cy.get('#token').type(res.body);
+ cy.contains('Submit').click();
+ })
+});
diff --git a/.vib/kubeapps/cypress/cypress/support/index.js b/.vib/kubeapps/cypress/cypress/support/index.js
new file mode 100644
index 0000000000..37a498fb5b
--- /dev/null
+++ b/.vib/kubeapps/cypress/cypress/support/index.js
@@ -0,0 +1,20 @@
+// ***********************************************************
+// This example support/index.js is processed and
+// loaded automatically before your test files.
+//
+// This is a great place to put global configuration and
+// behavior that modifies Cypress.
+//
+// You can change the location of this file or turn off
+// automatically serving support files with the
+// 'supportFile' configuration option.
+//
+// You can read more here:
+// https://on.cypress.io/configuration
+// ***********************************************************
+
+// Import commands.js using ES2015 syntax:
+import './commands';
+
+// Alternatively you can use CommonJS syntax:
+// require('./commands')
diff --git a/.vib/kubeapps/cypress/cypress/support/utils.js b/.vib/kubeapps/cypress/cypress/support/utils.js
new file mode 100644
index 0000000000..f0217c9773
--- /dev/null
+++ b/.vib/kubeapps/cypress/cypress/support/utils.js
@@ -0,0 +1,3 @@
+///
+
+export let random = (Math.random() + 1).toString(36).substring(7);
diff --git a/.vib/kubeapps/goss/goss.yaml b/.vib/kubeapps/goss/goss.yaml
new file mode 100644
index 0000000000..299744d00f
--- /dev/null
+++ b/.vib/kubeapps/goss/goss.yaml
@@ -0,0 +1,32 @@
+http:
+ http://kubeapps-internal-kubeappsapis:{{ .Vars.kubeappsapis.service.ports.http }}/core/plugins/v1alpha1/configured-plugins:
+ status: 200
+ http://kubeapps-internal-dashboard:{{ .Vars.dashboard.service.ports.http }}:
+ status: 200
+file:
+ /config/kubeapps-apis/plugins.conf:
+ filetype: symlink
+ exists: true
+ mode: "0777"
+ contains:
+ - /timeoutSeconds.*{{ .Vars.kubeappsapis.pluginConfig.core.packages.v1alpha1.timeoutSeconds }}/
+ /config/clusters.conf:
+ filetype: symlink
+ exists: true
+ mode: "0777"
+ contains:
+ {{ range .Vars.clusters }}
+ - /domain.*{{ .domain }}/
+ - /name.*{{ .name }}/
+ {{ end }}
+ /var/run/secrets/kubernetes.io/serviceaccount:
+ exists: {{ .Vars.kubeappsapis.serviceAccount.automountServiceAccountToken }}
+ filetype: directory
+ mode: "3777"
+command:
+ check-user-info:
+ exec: id
+ exit-status: 0
+ stdout:
+ - uid={{ .Vars.kubeappsapis.containerSecurityContext.runAsUser }}
+ - /groups=.*{{ .Vars.kubeappsapis.podSecurityContext.fsGroup }}/
diff --git a/.vib/kubeapps/goss/vars.yaml b/.vib/kubeapps/goss/vars.yaml
new file mode 100644
index 0000000000..09e840bbe6
--- /dev/null
+++ b/.vib/kubeapps/goss/vars.yaml
@@ -0,0 +1,22 @@
+dashboard:
+ service:
+ ports:
+ http: 8081
+clusters:
+ - name: default
+ domain: cluster.local
+kubeappsapis:
+ pluginConfig:
+ core:
+ packages:
+ v1alpha1:
+ timeoutSeconds: 250
+ podSecurityContext:
+ fsGroup: 1002
+ containerSecurityContext:
+ runAsUser: 1002
+ service:
+ ports:
+ http: 8081
+ serviceAccount:
+ automountServiceAccountToken: true
\ No newline at end of file
diff --git a/.vib/kubeapps/vib-publish.json b/.vib/kubeapps/vib-publish.json
index 9d58d2f1f7..08ec8da6c1 100644
--- a/.vib/kubeapps/vib-publish.json
+++ b/.vib/kubeapps/vib-publish.json
@@ -16,6 +16,56 @@
}
]
},
+ "verify": {
+ "context": {
+ "resources": {
+ "url": "{SHA_ARCHIVE}",
+ "path": "/bitnami/kubeapps"
+ },
+ "runtime_parameters": "cGFja2FnaW5nOgogIGhlbG06CiAgICBlbmFibGVkOiB0cnVlCmZyb250ZW5kOgogIHNlcnZpY2U6CiAgICB0eXBlOiBMb2FkQmFsYW5jZXIKICAgIHBvcnRzOgogICAgICBodHRwOiA4MApkYXNoYm9hcmQ6CiAgZW5hYmxlZDogdHJ1ZQogIGV4dHJhVm9sdW1lczoKICAgIHwtCiAgICAtIG5hbWU6IHRva2VuCiAgICAgIHNlY3JldDoKICAgICAgICBzZWNyZXROYW1lOiB7eyBpbmNsdWRlICJjb21tb24ubmFtZXMuZnVsbG5hbWUubmFtZXNwYWNlIiAuIH19LXZpYi10b2tlbgogIGV4dHJhVm9sdW1lTW91bnRzOgogICAgLSBuYW1lOiB0b2tlbgogICAgICBtb3VudFBhdGg6IC9hcHAvc3RhdGljL3Rva2VuL3Rva2VuLnR4dAogICAgICBzdWJQYXRoOiB0b2tlbgphcHByZXBvc2l0b3J5OgogIGluaXRpYWxSZXBvczoKICAgIC0gbmFtZTogYml0bmFtaQogICAgICB1cmw6IGh0dHBzOi8vY2hhcnRzLmJpdG5hbWkuY29tL2JpdG5hbWkKICB3YXRjaEFsbE5hbWVzcGFjZXM6IGZhbHNlCmF1dGhQcm94eToKICBlbmFibGVkOiBmYWxzZQpwaW5uaXBlZFByb3h5OgogIGVuYWJsZWQ6IGZhbHNlCmNsdXN0ZXJzOgogIC0gbmFtZTogZGVmYXVsdAogICAgZG9tYWluOiBjbHVzdGVyLmxvY2FsCnJiYWM6CiAgY3JlYXRlOiB0cnVlCmt1YmVhcHBzYXBpczoKICBwbHVnaW5Db25maWc6CiAgICBjb3JlOgogICAgICBwYWNrYWdlczoKICAgICAgICB2MWFscGhhMToKICAgICAgICAgIHRpbWVvdXRTZWNvbmRzOiAyNTAKICBwb2RTZWN1cml0eUNvbnRleHQ6CiAgICBlbmFibGVkOiB0cnVlCiAgICBmc0dyb3VwOiAxMDAyCiAgY29udGFpbmVyU2VjdXJpdHlDb250ZXh0OgogICAgZW5hYmxlZDogdHJ1ZQogICAgcnVuQXNVc2VyOiAxMDAyCiAgc2VydmljZToKICAgIHBvcnRzOgogICAgICBodHRwOiA4MDgxCiAgc2VydmljZUFjY291bnQ6CiAgICBjcmVhdGU6IHRydWUKICAgIGF1dG9tb3VudFNlcnZpY2VBY2NvdW50VG9rZW46IHRydWUKcG9zdGdyZXNxbDoKICBlbmFibGVkOiB0cnVlCmV4dHJhRGVwbG95OgogIC0gfC0KICAgIGFwaVZlcnNpb246IHYxCiAgICBraW5kOiBTZXJ2aWNlQWNjb3VudAogICAgbWV0YWRhdGE6CiAgICAgIG5hbWU6IHt7IGluY2x1ZGUgImNvbW1vbi5uYW1lcy5mdWxsbmFtZS5uYW1lc3BhY2UiIC4gfX0tdmliCiAgICAgIG5hbWVzcGFjZToge3sgLlJlbGVhc2UuTmFtZXNwYWNlIH19CiAgLSB8LQogICAgYXBpVmVyc2lvbjogcmJhYy5hdXRob3JpemF0aW9uLms4cy5pby92MQogICAga2luZDogQ2x1c3RlclJvbGVCaW5kaW5nCiAgICBtZXRhZGF0YToKICAgICAgbmFtZToge3sgaW5jbHVkZSAiY29tbW9uLm5hbWVzLmZ1bGxuYW1lLm5hbWVzcGFjZSIgLiB9fS12aWItdmlldwogICAgcm9sZVJlZjoKICAgICAgYXBpR3JvdXA6IHJiYWMuYXV0aG9yaXphdGlvbi5rOHMuaW8KICAgICAga2luZDogQ2x1c3RlclJvbGUKICAgICAgbmFtZTogdmlldwogICAgc3ViamVjdHM6CiAgICAtIGtpbmQ6IFNlcnZpY2VBY2NvdW50CiAgICAgIG5hbWU6IHt7IGluY2x1ZGUgImNvbW1vbi5uYW1lcy5mdWxsbmFtZS5uYW1lc3BhY2UiIC4gfX0tdmliCiAgICAgIG5hbWVzcGFjZToge3sgLlJlbGVhc2UuTmFtZXNwYWNlIH19CiAgLSB8LQogICAgYXBpVmVyc2lvbjogcmJhYy5hdXRob3JpemF0aW9uLms4cy5pby92MQogICAga2luZDogQ2x1c3RlclJvbGVCaW5kaW5nCiAgICBtZXRhZGF0YToKICAgICAgbmFtZToge3sgaW5jbHVkZSAiY29tbW9uLm5hbWVzLmZ1bGxuYW1lLm5hbWVzcGFjZSIgLiB9fS12aWItZWRpdAogICAgcm9sZVJlZjoKICAgICAgYXBpR3JvdXA6IHJiYWMuYXV0aG9yaXphdGlvbi5rOHMuaW8KICAgICAga2luZDogQ2x1c3RlclJvbGUKICAgICAgbmFtZTogZWRpdAogICAgc3ViamVjdHM6CiAgICAtIGtpbmQ6IFNlcnZpY2VBY2NvdW50CiAgICAgIG5hbWU6IHt7IGluY2x1ZGUgImNvbW1vbi5uYW1lcy5mdWxsbmFtZS5uYW1lc3BhY2UiIC4gfX0tdmliCiAgICAgIG5hbWVzcGFjZToge3sgLlJlbGVhc2UuTmFtZXNwYWNlIH19CiAgLSB8LQogICAgYXBpVmVyc2lvbjogdjEKICAgIGtpbmQ6IFNlY3JldAogICAgdHlwZToga3ViZXJuZXRlcy5pby9zZXJ2aWNlLWFjY291bnQtdG9rZW4KICAgIG1ldGFkYXRhOgogICAgICBuYW1lOiB7eyBpbmNsdWRlICJjb21tb24ubmFtZXMuZnVsbG5hbWUubmFtZXNwYWNlIiAuIH19LXZpYi10b2tlbgogICAgICBuYW1lc3BhY2U6IHt7IC5SZWxlYXNlLk5hbWVzcGFjZSB9fQogICAgICBhbm5vdGF0aW9uczoKICAgICAgICBrdWJlcm5ldGVzLmlvL3NlcnZpY2UtYWNjb3VudC5uYW1lOiB7eyBpbmNsdWRlICJjb21tb24ubmFtZXMuZnVsbG5hbWUubmFtZXNwYWNlIiAuIH19LXZpYgo=",
+ "target_platform": {
+ "target_platform_id": "{VIB_ENV_TARGET_PLATFORM}",
+ "size": {
+ "name": "S4"
+ }
+ }
+ },
+ "actions": [
+ {
+ "action_id": "health-check",
+ "params": {
+ "endpoint": "lb-kubeapps-http",
+ "app_protocol": "HTTP"
+ }
+ },
+ {
+ "action_id": "goss",
+ "params": {
+ "resources": {
+ "path": "/.vib/kubeapps/goss"
+ },
+ "remote": {
+ "workload": "deploy-kubeapps-internal-kubeappsapis"
+ },
+ "vars_file": "vars.yaml"
+ }
+ },
+ {
+ "action_id": "cypress",
+ "params": {
+ "resources": {
+ "path": "/.vib/kubeapps/cypress"
+ },
+ "endpoint": "lb-kubeapps-http",
+ "env": {
+ "repoName": "bitnami",
+ "repoURL": "https://charts.bitnami.com/bitnami"
+ },
+ "app_protocol": "HTTP"
+ }
+ }
+ ]
+ },
"publish": {
"actions": [
{
diff --git a/.vib/kubeapps/vib-verify.json b/.vib/kubeapps/vib-verify.json
index c2c4d44305..592f7e0ec8 100644
--- a/.vib/kubeapps/vib-verify.json
+++ b/.vib/kubeapps/vib-verify.json
@@ -15,6 +15,56 @@
"action_id": "helm-lint"
}
]
+ },
+ "verify": {
+ "context": {
+ "resources": {
+ "url": "{SHA_ARCHIVE}",
+ "path": "/bitnami/kubeapps"
+ },
+ "runtime_parameters": "cGFja2FnaW5nOgogIGhlbG06CiAgICBlbmFibGVkOiB0cnVlCmZyb250ZW5kOgogIHNlcnZpY2U6CiAgICB0eXBlOiBMb2FkQmFsYW5jZXIKICAgIHBvcnRzOgogICAgICBodHRwOiA4MApkYXNoYm9hcmQ6CiAgZW5hYmxlZDogdHJ1ZQogIGV4dHJhVm9sdW1lczoKICAgIHwtCiAgICAtIG5hbWU6IHRva2VuCiAgICAgIHNlY3JldDoKICAgICAgICBzZWNyZXROYW1lOiB7eyBpbmNsdWRlICJjb21tb24ubmFtZXMuZnVsbG5hbWUubmFtZXNwYWNlIiAuIH19LXZpYi10b2tlbgogIGV4dHJhVm9sdW1lTW91bnRzOgogICAgLSBuYW1lOiB0b2tlbgogICAgICBtb3VudFBhdGg6IC9hcHAvc3RhdGljL3Rva2VuL3Rva2VuLnR4dAogICAgICBzdWJQYXRoOiB0b2tlbgphcHByZXBvc2l0b3J5OgogIGluaXRpYWxSZXBvczoKICAgIC0gbmFtZTogYml0bmFtaQogICAgICB1cmw6IGh0dHBzOi8vY2hhcnRzLmJpdG5hbWkuY29tL2JpdG5hbWkKICB3YXRjaEFsbE5hbWVzcGFjZXM6IGZhbHNlCmF1dGhQcm94eToKICBlbmFibGVkOiBmYWxzZQpwaW5uaXBlZFByb3h5OgogIGVuYWJsZWQ6IGZhbHNlCmNsdXN0ZXJzOgogIC0gbmFtZTogZGVmYXVsdAogICAgZG9tYWluOiBjbHVzdGVyLmxvY2FsCnJiYWM6CiAgY3JlYXRlOiB0cnVlCmt1YmVhcHBzYXBpczoKICBwbHVnaW5Db25maWc6CiAgICBjb3JlOgogICAgICBwYWNrYWdlczoKICAgICAgICB2MWFscGhhMToKICAgICAgICAgIHRpbWVvdXRTZWNvbmRzOiAyNTAKICBwb2RTZWN1cml0eUNvbnRleHQ6CiAgICBlbmFibGVkOiB0cnVlCiAgICBmc0dyb3VwOiAxMDAyCiAgY29udGFpbmVyU2VjdXJpdHlDb250ZXh0OgogICAgZW5hYmxlZDogdHJ1ZQogICAgcnVuQXNVc2VyOiAxMDAyCiAgc2VydmljZToKICAgIHBvcnRzOgogICAgICBodHRwOiA4MDgxCiAgc2VydmljZUFjY291bnQ6CiAgICBjcmVhdGU6IHRydWUKICAgIGF1dG9tb3VudFNlcnZpY2VBY2NvdW50VG9rZW46IHRydWUKcG9zdGdyZXNxbDoKICBlbmFibGVkOiB0cnVlCmV4dHJhRGVwbG95OgogIC0gfC0KICAgIGFwaVZlcnNpb246IHYxCiAgICBraW5kOiBTZXJ2aWNlQWNjb3VudAogICAgbWV0YWRhdGE6CiAgICAgIG5hbWU6IHt7IGluY2x1ZGUgImNvbW1vbi5uYW1lcy5mdWxsbmFtZS5uYW1lc3BhY2UiIC4gfX0tdmliCiAgICAgIG5hbWVzcGFjZToge3sgLlJlbGVhc2UuTmFtZXNwYWNlIH19CiAgLSB8LQogICAgYXBpVmVyc2lvbjogcmJhYy5hdXRob3JpemF0aW9uLms4cy5pby92MQogICAga2luZDogQ2x1c3RlclJvbGVCaW5kaW5nCiAgICBtZXRhZGF0YToKICAgICAgbmFtZToge3sgaW5jbHVkZSAiY29tbW9uLm5hbWVzLmZ1bGxuYW1lLm5hbWVzcGFjZSIgLiB9fS12aWItdmlldwogICAgcm9sZVJlZjoKICAgICAgYXBpR3JvdXA6IHJiYWMuYXV0aG9yaXphdGlvbi5rOHMuaW8KICAgICAga2luZDogQ2x1c3RlclJvbGUKICAgICAgbmFtZTogdmlldwogICAgc3ViamVjdHM6CiAgICAtIGtpbmQ6IFNlcnZpY2VBY2NvdW50CiAgICAgIG5hbWU6IHt7IGluY2x1ZGUgImNvbW1vbi5uYW1lcy5mdWxsbmFtZS5uYW1lc3BhY2UiIC4gfX0tdmliCiAgICAgIG5hbWVzcGFjZToge3sgLlJlbGVhc2UuTmFtZXNwYWNlIH19CiAgLSB8LQogICAgYXBpVmVyc2lvbjogcmJhYy5hdXRob3JpemF0aW9uLms4cy5pby92MQogICAga2luZDogQ2x1c3RlclJvbGVCaW5kaW5nCiAgICBtZXRhZGF0YToKICAgICAgbmFtZToge3sgaW5jbHVkZSAiY29tbW9uLm5hbWVzLmZ1bGxuYW1lLm5hbWVzcGFjZSIgLiB9fS12aWItZWRpdAogICAgcm9sZVJlZjoKICAgICAgYXBpR3JvdXA6IHJiYWMuYXV0aG9yaXphdGlvbi5rOHMuaW8KICAgICAga2luZDogQ2x1c3RlclJvbGUKICAgICAgbmFtZTogZWRpdAogICAgc3ViamVjdHM6CiAgICAtIGtpbmQ6IFNlcnZpY2VBY2NvdW50CiAgICAgIG5hbWU6IHt7IGluY2x1ZGUgImNvbW1vbi5uYW1lcy5mdWxsbmFtZS5uYW1lc3BhY2UiIC4gfX0tdmliCiAgICAgIG5hbWVzcGFjZToge3sgLlJlbGVhc2UuTmFtZXNwYWNlIH19CiAgLSB8LQogICAgYXBpVmVyc2lvbjogdjEKICAgIGtpbmQ6IFNlY3JldAogICAgdHlwZToga3ViZXJuZXRlcy5pby9zZXJ2aWNlLWFjY291bnQtdG9rZW4KICAgIG1ldGFkYXRhOgogICAgICBuYW1lOiB7eyBpbmNsdWRlICJjb21tb24ubmFtZXMuZnVsbG5hbWUubmFtZXNwYWNlIiAuIH19LXZpYi10b2tlbgogICAgICBuYW1lc3BhY2U6IHt7IC5SZWxlYXNlLk5hbWVzcGFjZSB9fQogICAgICBhbm5vdGF0aW9uczoKICAgICAgICBrdWJlcm5ldGVzLmlvL3NlcnZpY2UtYWNjb3VudC5uYW1lOiB7eyBpbmNsdWRlICJjb21tb24ubmFtZXMuZnVsbG5hbWUubmFtZXNwYWNlIiAuIH19LXZpYgo=",
+ "target_platform": {
+ "target_platform_id": "{VIB_ENV_TARGET_PLATFORM}",
+ "size": {
+ "name": "S4"
+ }
+ }
+ },
+ "actions": [
+ {
+ "action_id": "health-check",
+ "params": {
+ "endpoint": "lb-kubeapps-http",
+ "app_protocol": "HTTP"
+ }
+ },
+ {
+ "action_id": "goss",
+ "params": {
+ "resources": {
+ "path": "/.vib/kubeapps/goss"
+ },
+ "remote": {
+ "workload": "deploy-kubeapps-internal-kubeappsapis"
+ },
+ "vars_file": "vars.yaml"
+ }
+ },
+ {
+ "action_id": "cypress",
+ "params": {
+ "resources": {
+ "path": "/.vib/kubeapps/cypress"
+ },
+ "endpoint": "lb-kubeapps-http",
+ "app_protocol": "HTTP",
+ "env": {
+ "repoName": "bitnami",
+ "repoURL": "https://charts.bitnami.com/bitnami"
+ }
+ }
+ }
+ ]
}
}
}