summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKamil Trzciński <ayufan@ayufan.eu>2019-01-04 10:34:35 +0000
committerKamil Trzciński <ayufan@ayufan.eu>2019-01-04 10:34:35 +0000
commit43687c62607075ee201b8ea1e16ac6e6563b45be (patch)
tree77ebb5da957717d4447395b1f1b85eacaf9614b2
parent24985807dc9e642f1ac2ca6b6d24f086f8eb4282 (diff)
parent82a5cf0aad4cf0c67067cf03e34f539fe72ded76 (diff)
downloadgitlab-ce-43687c62607075ee201b8ea1e16ac6e6563b45be.tar.gz
Merge branch '49056-configure-auto-devops-deployed-applications-with-secrets-that-aren-t-committed-to-the-repo' into 'master'
Configure Auto DevOps deployed applications with secrets from prefixed CI variables See merge request gitlab-org/gitlab-ce!23719
-rw-r--r--app/views/ci/variables/_content.html.haml2
-rw-r--r--changelogs/unreleased/49056-configure-auto-devops-deployed-applications-with-secrets-that-aren-t-committed-to-the-repo.yml5
-rw-r--r--lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml67
-rw-r--r--locale/gitlab.pot3
-rw-r--r--qa/qa/fixtures/auto_devops_rack/config.ru2
-rw-r--r--qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb105
6 files changed, 141 insertions, 43 deletions
diff --git a/app/views/ci/variables/_content.html.haml b/app/views/ci/variables/_content.html.haml
index fa82611d9c1..90c59bec975 100644
--- a/app/views/ci/variables/_content.html.haml
+++ b/app/views/ci/variables/_content.html.haml
@@ -1 +1,3 @@
= _('Environment variables are applied to environments via the runner. They can be protected by only exposing them to protected branches or tags. You can use environment variables for passwords, secret keys, or whatever you want.')
+= _('You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>.').html_safe
+= link_to _('More information'), help_page_path('ci/variables/README', anchor: 'variables')
diff --git a/changelogs/unreleased/49056-configure-auto-devops-deployed-applications-with-secrets-that-aren-t-committed-to-the-repo.yml b/changelogs/unreleased/49056-configure-auto-devops-deployed-applications-with-secrets-that-aren-t-committed-to-the-repo.yml
new file mode 100644
index 00000000000..65efa85176b
--- /dev/null
+++ b/changelogs/unreleased/49056-configure-auto-devops-deployed-applications-with-secrets-that-aren-t-committed-to-the-repo.yml
@@ -0,0 +1,5 @@
+---
+title: Configure Auto DevOps deployed applications with secrets from prefixed CI variables
+merge_request: 23719
+author:
+type: added
diff --git a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
index 8f6cf8d2d03..b5350f56f9c 100644
--- a/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml
@@ -596,10 +596,55 @@ rollout 100%:
fi
}
+ # Extracts variables prefixed with K8S_SECRET_
+ # and creates a Kubernetes secret.
+ #
+ # e.g. If we have the following environment variables:
+ # K8S_SECRET_A=value1
+ # K8S_SECRET_B=multi\ word\ value
+ #
+ # Then we will create a secret with the following key-value pairs:
+ # data:
+ # A: dmFsdWUxCg==
+ # B: bXVsdGkgd29yZCB2YWx1ZQo=
+ function create_application_secret() {
+ track="${1-stable}"
+ export APPLICATION_SECRET_NAME=$(application_secret_name "$track")
+
+ bash -c '
+ function k8s_prefixed_variables() {
+ env | sed -n "s/^K8S_SECRET_\(.*\)$/\1/p"
+ }
+
+ kubectl create secret \
+ -n "$KUBE_NAMESPACE" generic "$APPLICATION_SECRET_NAME" \
+ --from-env-file <(k8s_prefixed_variables) -o yaml --dry-run |
+ kubectl replace -n "$KUBE_NAMESPACE" --force -f -
+ '
+ }
+
+ function deploy_name() {
+ name="$CI_ENVIRONMENT_SLUG"
+ track="${1-stable}"
+
+ if [[ "$track" != "stable" ]]; then
+ name="$name-$track"
+ fi
+
+ echo $name
+ }
+
+ function application_secret_name() {
+ track="${1-stable}"
+ name=$(deploy_name "$track")
+
+ echo "${name}-secret"
+ }
+
function deploy() {
track="${1-stable}"
percentage="${2:-100}"
- name="$CI_ENVIRONMENT_SLUG"
+ name=$(deploy_name "$track")
replicas="1"
service_enabled="true"
@@ -608,7 +653,6 @@ rollout 100%:
# if track is different than stable,
# re-use all attached resources
if [[ "$track" != "stable" ]]; then
- name="$name-$track"
service_enabled="false"
postgres_enabled="false"
fi
@@ -621,6 +665,8 @@ rollout 100%:
secret_name=''
fi
+ create_application_secret "$track"
+
if [[ -n "$DB_INITIALIZE" && -z "$(helm ls -q "^$name$")" ]]; then
echo "Deploying first release with database initialization..."
helm upgrade --install \
@@ -633,6 +679,7 @@ rollout 100%:
--set image.secrets[0].name="$secret_name" \
--set application.track="$track" \
--set application.database_url="$DATABASE_URL" \
+ --set application.secretName="$APPLICATION_SECRET_NAME" \
--set service.url="$CI_ENVIRONMENT_URL" \
--set replicaCount="$replicas" \
--set postgresql.enabled="$postgres_enabled" \
@@ -665,6 +712,7 @@ rollout 100%:
--set image.secrets[0].name="$secret_name" \
--set application.track="$track" \
--set application.database_url="$DATABASE_URL" \
+ --set application.secretName="$APPLICATION_SECRET_NAME" \
--set service.url="$CI_ENVIRONMENT_URL" \
--set replicaCount="$replicas" \
--set postgresql.enabled="$postgres_enabled" \
@@ -684,11 +732,7 @@ rollout 100%:
function scale() {
track="${1-stable}"
percentage="${2-100}"
- name="$CI_ENVIRONMENT_SLUG"
-
- if [[ "$track" != "stable" ]]; then
- name="$name-$track"
- fi
+ name=$(deploy_name "$track")
replicas=$(get_replicas "$track" "$percentage")
@@ -882,15 +926,14 @@ rollout 100%:
function delete() {
track="${1-stable}"
- name="$CI_ENVIRONMENT_SLUG"
-
- if [[ "$track" != "stable" ]]; then
- name="$name-$track"
- fi
+ name=$(deploy_name "$track")
if [[ -n "$(helm ls -q "^$name$")" ]]; then
helm delete --purge "$name"
fi
+
+ secret_name=$(application_secret_name "$track")
+ kubectl delete secret --ignore-not-found -n "$KUBE_NAMESPACE" "$secret_name"
}
before_script:
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index ddfd5599883..10a3a70b32a 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -7719,6 +7719,9 @@ msgstr ""
msgid "You have reached your project limit"
msgstr ""
+msgid "You may also add variables that are made available to the running application by prepending the variable key with <code>K8S_SECRET_</code>."
+msgstr ""
+
msgid "You must accept our Terms of Service and privacy policy in order to register an account"
msgstr ""
diff --git a/qa/qa/fixtures/auto_devops_rack/config.ru b/qa/qa/fixtures/auto_devops_rack/config.ru
index bde8e15488a..e990662145a 100644
--- a/qa/qa/fixtures/auto_devops_rack/config.ru
+++ b/qa/qa/fixtures/auto_devops_rack/config.ru
@@ -1 +1 @@
-run lambda { |env| [200, { 'Content-Type' => 'text/plain' }, StringIO.new("Hello World!\n")] }
+run lambda { |env| [200, { 'Content-Type' => 'text/plain' }, StringIO.new("Hello World! #{ENV['OPTIONAL_MESSAGE']}\n")] }
diff --git a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
index b0c277a48c3..6cd5c06a088 100644
--- a/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
+++ b/qa/qa/specs/features/browser_ui/7_configure/auto_devops/create_project_with_auto_devops_spec.rb
@@ -5,60 +5,73 @@ require 'pathname'
module QA
context 'Configure', :orchestrated, :kubernetes do
describe 'Auto DevOps support' do
- after do
- @cluster&.remove!
+ def login
+ Runtime::Browser.visit(:gitlab, Page::Main::Login)
+ Page::Main::Login.act { sign_in_using_credentials }
end
- [true, false].each do |rbac|
- context "when rbac is #{rbac ? 'enabled' : 'disabled'}" do
- it 'user creates a new project and runs auto devops' do
- Runtime::Browser.visit(:gitlab, Page::Main::Login)
- Page::Main::Login.act { sign_in_using_credentials }
+ before(:all) do
+ login
- project = Resource::Project.fabricate! do |p|
- p.name = Runtime::Env.auto_devops_project_name || 'project-with-autodevops'
- p.description = 'Project with Auto Devops'
- end
+ @project = Resource::Project.fabricate! do |p|
+ p.name = Runtime::Env.auto_devops_project_name || 'project-with-autodevops'
+ p.description = 'Project with Auto Devops'
+ end
- # Disable code_quality check in Auto DevOps pipeline as it takes
- # too long and times out the test
- Resource::CiVariable.fabricate! do |resource|
- resource.project = project
- resource.key = 'CODE_QUALITY_DISABLED'
- resource.value = '1'
- end
+ # Disable code_quality check in Auto DevOps pipeline as it takes
+ # too long and times out the test
+ Resource::CiVariable.fabricate! do |resource|
+ resource.project = @project
+ resource.key = 'CODE_QUALITY_DISABLED'
+ resource.value = '1'
+ end
- # Create Auto Devops compatible repo
- Resource::Repository::ProjectPush.fabricate! do |push|
- push.project = project
- push.directory = Pathname
- .new(__dir__)
- .join('../../../../../fixtures/auto_devops_rack')
- push.commit_message = 'Create Auto DevOps compatible rack application'
- end
+ # Create Auto Devops compatible repo
+ Resource::Repository::ProjectPush.fabricate! do |push|
+ push.project = @project
+ push.directory = Pathname
+ .new(__dir__)
+ .join('../../../../../fixtures/auto_devops_rack')
+ push.commit_message = 'Create Auto DevOps compatible rack application'
+ end
- Page::Project::Show.act { wait_for_push }
+ Page::Project::Show.act { wait_for_push }
+ end
+ [true, false].each do |rbac|
+ context "when rbac is #{rbac ? 'enabled' : 'disabled'}" do
+ before(:all) do
# Create and connect K8s cluster
@cluster = Service::KubernetesCluster.new(rbac: rbac).create!
kubernetes_cluster = Resource::KubernetesCluster.fabricate! do |cluster|
- cluster.project = project
+ cluster.project = @project
cluster.cluster = @cluster
cluster.install_helm_tiller = true
cluster.install_ingress = true
cluster.install_prometheus = true
cluster.install_runner = true
end
+
kubernetes_cluster.populate(:ingress_ip)
- project.visit!
+ @project.visit!
Page::Project::Menu.act { click_ci_cd_settings }
Page::Project::Settings::CICD.perform do |p|
p.enable_auto_devops_with_domain(
"#{kubernetes_cluster.ingress_ip}.nip.io")
end
+ end
- project.visit!
+ after(:all) do
+ @cluster&.remove!
+ end
+
+ before do
+ login
+ end
+
+ it 'runs auto devops' do
+ @project.visit!
Page::Project::Menu.act { click_ci_cd_pipelines }
Page::Project::Pipeline::Index.act { go_to_latest_pipeline }
@@ -78,6 +91,38 @@ module QA
end
end
end
+
+ it 'user sets application secret variable and Auto DevOps passes it to container' do
+ # Set an application secret CI variable (prefixed with K8S_SECRET_)
+ Resource::CiVariable.fabricate! do |resource|
+ resource.project = @project
+ resource.key = 'K8S_SECRET_OPTIONAL_MESSAGE'
+ resource.value = 'You can see this application secret'
+ end
+
+ @project.visit!
+ Page::Project::Menu.act { click_ci_cd_pipelines }
+ Page::Project::Pipeline::Index.act { go_to_latest_pipeline }
+
+ Page::Project::Pipeline::Show.perform do |pipeline|
+ expect(pipeline).to have_build('build', status: :success, wait: 600)
+ expect(pipeline).to have_build('test', status: :success, wait: 600)
+ expect(pipeline).to have_build('production', status: :success, wait: 1200)
+ end
+
+ Page::Project::Menu.act { click_operations_environments }
+
+ Page::Project::Operations::Environments::Index.perform do |index|
+ index.go_to_environment('production')
+ end
+
+ Page::Project::Operations::Environments::Show.perform do |show|
+ show.view_deployment do
+ expect(page).to have_content('Hello World!')
+ expect(page).to have_content('You can see this application secret')
+ end
+ end
+ end
end
end
end