diff options
author | Kamil Trzciński <ayufan@ayufan.eu> | 2018-03-01 23:46:03 +0000 |
---|---|---|
committer | Kamil Trzciński <ayufan@ayufan.eu> | 2018-03-01 23:46:03 +0000 |
commit | 59de0443edba21a2110f783a4b2595bc02e7db0f (patch) | |
tree | 5fbabbeec70c9129b5db9b184d7620dbc35aaac2 | |
parent | 947a7f858765fdbad2f4084bed24994329d62337 (diff) | |
parent | c607008ee55e35465e04a938a341f2f24cb6761f (diff) | |
download | gitlab-ce-59de0443edba21a2110f783a4b2595bc02e7db0f.tar.gz |
Merge branch '32831-single-deploy-of-runner-in-k8s-cluster' into 'master'
Extend Cluster Applications to install GitLab Runner to Kubernetes cluster
Closes #32831
See merge request gitlab-org/gitlab-ce!17134
35 files changed, 758 insertions, 411 deletions
diff --git a/app/assets/javascripts/clusters/components/applications.vue b/app/assets/javascripts/clusters/components/applications.vue index 35618398468..1325a268214 100644 --- a/app/assets/javascripts/clusters/components/applications.vue +++ b/app/assets/javascripts/clusters/components/applications.vue @@ -99,12 +99,6 @@ </p> `; }, - gitlabRunnerDescription() { - return _.escape(s__( - `ClusterIntegration|GitLab Runner is the open source project that is used to run your jobs - and send the results back to GitLab.`, - )); - }, prometheusDescription() { return sprintf( _.escape(s__( @@ -256,6 +250,22 @@ > </div> </application-row> + <application-row + id="runner" + :title="applications.runner.title" + title-link="https://docs.gitlab.com/runner/" + :status="applications.runner.status" + :status-reason="applications.runner.statusReason" + :request-status="applications.runner.requestStatus" + :request-reason="applications.runner.requestReason" + > + <div slot="description"> + {{ s__(`ClusterIntegration|GitLab Runner connects to this + project's repository and executes CI/CD jobs, + pushing results back and deploying, + applications to production.`) }} + </div> + </application-row> <!-- NOTE: Don't forget to update `clusters.scss` min-height for this block and uncomment `application_spec` tests diff --git a/app/models/clusters/applications/helm.rb b/app/models/clusters/applications/helm.rb index 193bb48e54d..58de3448577 100644 --- a/app/models/clusters/applications/helm.rb +++ b/app/models/clusters/applications/helm.rb @@ -15,7 +15,7 @@ module Clusters end def install_command - Gitlab::Kubernetes::Helm::InstallCommand.new(name, install_helm: true) + Gitlab::Kubernetes::Helm::InitCommand.new(name) end end end diff --git a/app/models/clusters/applications/ingress.rb b/app/models/clusters/applications/ingress.rb index 9f583342c19..27fc3b85465 100644 --- a/app/models/clusters/applications/ingress.rb +++ b/app/models/clusters/applications/ingress.rb @@ -5,6 +5,7 @@ module Clusters include ::Clusters::Concerns::ApplicationCore include ::Clusters::Concerns::ApplicationStatus + include ::Clusters::Concerns::ApplicationData include AfterCommitQueue default_value_for :ingress_type, :nginx @@ -29,12 +30,12 @@ module Clusters 'stable/nginx-ingress' end - def chart_values_file - "#{Rails.root}/vendor/#{name}/values.yaml" - end - def install_command - Gitlab::Kubernetes::Helm::InstallCommand.new(name, chart: chart, chart_values_file: chart_values_file) + Gitlab::Kubernetes::Helm::InstallCommand.new( + name, + chart: chart, + values: values + ) end def schedule_status_update diff --git a/app/models/clusters/applications/prometheus.rb b/app/models/clusters/applications/prometheus.rb index aa22e9d5d58..89ebd63e605 100644 --- a/app/models/clusters/applications/prometheus.rb +++ b/app/models/clusters/applications/prometheus.rb @@ -7,6 +7,7 @@ module Clusters include ::Clusters::Concerns::ApplicationCore include ::Clusters::Concerns::ApplicationStatus + include ::Clusters::Concerns::ApplicationData default_value_for :version, VERSION @@ -30,12 +31,12 @@ module Clusters 80 end - def chart_values_file - "#{Rails.root}/vendor/#{name}/values.yaml" - end - def install_command - Gitlab::Kubernetes::Helm::InstallCommand.new(name, chart: chart, chart_values_file: chart_values_file) + Gitlab::Kubernetes::Helm::InstallCommand.new( + name, + chart: chart, + values: values + ) end def proxy_client diff --git a/app/models/clusters/applications/runner.rb b/app/models/clusters/applications/runner.rb new file mode 100644 index 00000000000..7adf1663c35 --- /dev/null +++ b/app/models/clusters/applications/runner.rb @@ -0,0 +1,68 @@ +module Clusters + module Applications + class Runner < ActiveRecord::Base + VERSION = '0.1.13'.freeze + + self.table_name = 'clusters_applications_runners' + + include ::Clusters::Concerns::ApplicationCore + include ::Clusters::Concerns::ApplicationStatus + include ::Clusters::Concerns::ApplicationData + + belongs_to :runner, class_name: 'Ci::Runner', foreign_key: :runner_id + delegate :project, to: :cluster + + default_value_for :version, VERSION + + def chart + "#{name}/gitlab-runner" + end + + def repository + 'https://charts.gitlab.io' + end + + def values + content_values.to_yaml + end + + def install_command + Gitlab::Kubernetes::Helm::InstallCommand.new( + name, + chart: chart, + values: values, + repository: repository + ) + end + + private + + def ensure_runner + runner || create_and_assign_runner + end + + def create_and_assign_runner + transaction do + project.runners.create!(name: 'kubernetes-cluster', tag_list: %w(kubernetes cluster)).tap do |runner| + update!(runner_id: runner.id) + end + end + end + + def gitlab_url + Gitlab::Routing.url_helpers.root_url(only_path: false) + end + + def specification + { + "gitlabUrl" => gitlab_url, + "runnerToken" => ensure_runner.token + } + end + + def content_values + specification.merge(YAML.load_file(chart_values_file)) + end + end + end +end diff --git a/app/models/clusters/cluster.rb b/app/models/clusters/cluster.rb index 8678f70f78c..1c0046107d7 100644 --- a/app/models/clusters/cluster.rb +++ b/app/models/clusters/cluster.rb @@ -7,7 +7,8 @@ module Clusters APPLICATIONS = { Applications::Helm.application_name => Applications::Helm, Applications::Ingress.application_name => Applications::Ingress, - Applications::Prometheus.application_name => Applications::Prometheus + Applications::Prometheus.application_name => Applications::Prometheus, + Applications::Runner.application_name => Applications::Runner }.freeze belongs_to :user @@ -23,6 +24,7 @@ module Clusters has_one :application_helm, class_name: 'Clusters::Applications::Helm' has_one :application_ingress, class_name: 'Clusters::Applications::Ingress' has_one :application_prometheus, class_name: 'Clusters::Applications::Prometheus' + has_one :application_runner, class_name: 'Clusters::Applications::Runner' accepts_nested_attributes_for :provider_gcp, update_only: true accepts_nested_attributes_for :platform_kubernetes, update_only: true @@ -68,7 +70,8 @@ module Clusters [ application_helm || build_application_helm, application_ingress || build_application_ingress, - application_prometheus || build_application_prometheus + application_prometheus || build_application_prometheus, + application_runner || build_application_runner ] end diff --git a/app/models/clusters/concerns/application_data.rb b/app/models/clusters/concerns/application_data.rb new file mode 100644 index 00000000000..96ac757e99e --- /dev/null +++ b/app/models/clusters/concerns/application_data.rb @@ -0,0 +1,23 @@ +module Clusters + module Concerns + module ApplicationData + extend ActiveSupport::Concern + + included do + def repository + nil + end + + def values + File.read(chart_values_file) + end + + private + + def chart_values_file + "#{Rails.root}/vendor/#{name}/values.yaml" + end + end + end + end +end diff --git a/app/views/projects/clusters/show.html.haml b/app/views/projects/clusters/show.html.haml index 179c45a9867..2ee0eafcf1a 100644 --- a/app/views/projects/clusters/show.html.haml +++ b/app/views/projects/clusters/show.html.haml @@ -10,6 +10,7 @@ install_helm_path: install_applications_namespace_project_cluster_path(@cluster.project.namespace, @cluster.project, @cluster, :helm), install_ingress_path: install_applications_namespace_project_cluster_path(@cluster.project.namespace, @cluster.project, @cluster, :ingress), install_prometheus_path: install_applications_namespace_project_cluster_path(@cluster.project.namespace, @cluster.project, @cluster, :prometheus), + install_runner_path: install_applications_namespace_project_cluster_path(@cluster.project.namespace, @cluster.project, @cluster, :runner), toggle_status: @cluster.enabled? ? 'true': 'false', cluster_status: @cluster.status_name, cluster_status_reason: @cluster.status_reason, diff --git a/changelogs/unreleased/32831-single-deploy-of-runner-in-k8s-cluster.yml b/changelogs/unreleased/32831-single-deploy-of-runner-in-k8s-cluster.yml new file mode 100644 index 00000000000..74675992105 --- /dev/null +++ b/changelogs/unreleased/32831-single-deploy-of-runner-in-k8s-cluster.yml @@ -0,0 +1,5 @@ +--- +title: Allow installation of GitLab Runner with a single click +merge_request: 17134 +author: +type: added diff --git a/db/migrate/20180214155405_create_clusters_applications_runners.rb b/db/migrate/20180214155405_create_clusters_applications_runners.rb new file mode 100644 index 00000000000..fc4c0881338 --- /dev/null +++ b/db/migrate/20180214155405_create_clusters_applications_runners.rb @@ -0,0 +1,32 @@ +class CreateClustersApplicationsRunners < ActiveRecord::Migration + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + create_table :clusters_applications_runners do |t| + t.references :cluster, null: false, foreign_key: { on_delete: :cascade } + t.references :runner, references: :ci_runners + t.index :runner_id + t.index :cluster_id, unique: true + t.integer :status, null: false + t.timestamps_with_timezone null: false + t.string :version, null: false + t.text :status_reason + end + + add_concurrent_foreign_key :clusters_applications_runners, :ci_runners, + column: :runner_id, + on_delete: :nullify + end + + def down + if foreign_keys_for(:clusters_applications_runners, :runner_id).any? + remove_foreign_key :clusters_applications_runners, column: :runner_id + end + + drop_table :clusters_applications_runners + end +end diff --git a/db/schema.rb b/db/schema.rb index 773cf8b4d3f..db8bafe9677 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -582,6 +582,19 @@ ActiveRecord::Schema.define(version: 20180301084653) do t.datetime_with_timezone "updated_at", null: false end + create_table "clusters_applications_runners", force: :cascade do |t| + t.integer "cluster_id", null: false + t.integer "runner_id" + t.integer "status", null: false + t.datetime_with_timezone "created_at", null: false + t.datetime_with_timezone "updated_at", null: false + t.string "version", null: false + t.text "status_reason" + end + + add_index "clusters_applications_runners", ["cluster_id"], name: "index_clusters_applications_runners_on_cluster_id", unique: true, using: :btree + add_index "clusters_applications_runners", ["runner_id"], name: "index_clusters_applications_runners_on_runner_id", using: :btree + create_table "container_repositories", force: :cascade do |t| t.integer "project_id", null: false t.string "name", null: false @@ -1988,6 +2001,8 @@ ActiveRecord::Schema.define(version: 20180301084653) do add_foreign_key "cluster_providers_gcp", "clusters", on_delete: :cascade add_foreign_key "clusters", "users", on_delete: :nullify add_foreign_key "clusters_applications_helm", "clusters", on_delete: :cascade + add_foreign_key "clusters_applications_runners", "ci_runners", column: "runner_id", name: "fk_02de2ded36", on_delete: :nullify + add_foreign_key "clusters_applications_runners", "clusters", on_delete: :cascade add_foreign_key "container_repositories", "projects" add_foreign_key "deploy_keys_projects", "projects", name: "fk_58a901ca7e", on_delete: :cascade add_foreign_key "deployments", "projects", name: "fk_b9a3851b82", on_delete: :cascade diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md index bbe25c2d911..4ac54f96aa2 100644 --- a/doc/user/project/clusters/index.md +++ b/doc/user/project/clusters/index.md @@ -120,6 +120,7 @@ added directly to your configured cluster. Those applications are needed for | [Helm Tiller](https://docs.helm.sh/) | 10.2+ | Helm is a package manager for Kubernetes and is required to install all the other applications. It will be automatically installed as a dependency when you try to install a different app. It is installed in its own pod inside the cluster which can run the `helm` CLI in a safe environment. | | [Ingress](https://kubernetes.io/docs/concepts/services-networking/ingress/) | 10.2+ | Ingress can provide load balancing, SSL termination, and name-based virtual hosting. It acts as a web proxy for your applications and is useful if you want to use [Auto DevOps](../../../topics/autodevops/index.md) or deploy your own web apps. | | [Prometheus](https://prometheus.io/docs/introduction/overview/) | 10.4+ | Prometheus is an open-source monitoring and alerting system useful to supervise your deployed applications | +| [GitLab Runner](https://docs.gitlab.com/runner/) | 10.6+ | GitLab Runner is the open source project that is used to run your jobs and send the results back to GitLab. It is used in conjunction with [GitLab CI](https://about.gitlab.com/features/gitlab-ci-cd/), the open-source continuous integration service included with GitLab that coordinates the jobs. | ## Getting the external IP address diff --git a/lib/gitlab/kubernetes/config_map.rb b/lib/gitlab/kubernetes/config_map.rb new file mode 100644 index 00000000000..95e1054919d --- /dev/null +++ b/lib/gitlab/kubernetes/config_map.rb @@ -0,0 +1,37 @@ +module Gitlab + module Kubernetes + class ConfigMap + def initialize(name, values) + @name = name + @values = values + end + + def generate + resource = ::Kubeclient::Resource.new + resource.metadata = metadata + resource.data = { values: values } + resource + end + + private + + attr_reader :name, :values + + def metadata + { + name: config_map_name, + namespace: namespace, + labels: { name: config_map_name } + } + end + + def config_map_name + "values-content-configuration-#{name}" + end + + def namespace + Gitlab::Kubernetes::Helm::NAMESPACE + end + end + end +end diff --git a/lib/gitlab/kubernetes/helm/api.rb b/lib/gitlab/kubernetes/helm/api.rb index 737081ddc5b..2edd34109ba 100644 --- a/lib/gitlab/kubernetes/helm/api.rb +++ b/lib/gitlab/kubernetes/helm/api.rb @@ -9,7 +9,8 @@ module Gitlab def install(command) @namespace.ensure_exists! - @kubeclient.create_pod(pod_resource(command)) + create_config_map(command) if command.config_map? + @kubeclient.create_pod(command.pod_resource) end ## @@ -33,8 +34,10 @@ module Gitlab private - def pod_resource(command) - Gitlab::Kubernetes::Helm::Pod.new(command, @namespace.name, @kubeclient).generate + def create_config_map(command) + command.config_map_resource.tap do |config_map_resource| + @kubeclient.create_config_map(config_map_resource) + end end end end diff --git a/lib/gitlab/kubernetes/helm/base_command.rb b/lib/gitlab/kubernetes/helm/base_command.rb new file mode 100644 index 00000000000..6e4df05aa7e --- /dev/null +++ b/lib/gitlab/kubernetes/helm/base_command.rb @@ -0,0 +1,40 @@ +module Gitlab + module Kubernetes + module Helm + class BaseCommand + attr_reader :name + + def initialize(name) + @name = name + end + + def pod_resource + Gitlab::Kubernetes::Helm::Pod.new(self, namespace).generate + end + + def generate_script + <<~HEREDOC + set -eo pipefail + apk add -U ca-certificates openssl >/dev/null + wget -q -O - https://kubernetes-helm.storage.googleapis.com/helm-v#{Gitlab::Kubernetes::Helm::HELM_VERSION}-linux-amd64.tar.gz | tar zxC /tmp >/dev/null + mv /tmp/linux-amd64/helm /usr/bin/ + HEREDOC + end + + def config_map? + false + end + + def pod_name + "install-#{name}" + end + + private + + def namespace + Gitlab::Kubernetes::Helm::NAMESPACE + end + end + end + end +end diff --git a/lib/gitlab/kubernetes/helm/init_command.rb b/lib/gitlab/kubernetes/helm/init_command.rb new file mode 100644 index 00000000000..a02e64561f6 --- /dev/null +++ b/lib/gitlab/kubernetes/helm/init_command.rb @@ -0,0 +1,19 @@ +module Gitlab + module Kubernetes + module Helm + class InitCommand < BaseCommand + def generate_script + super + [ + init_helm_command + ].join("\n") + end + + private + + def init_helm_command + "helm init >/dev/null" + end + end + end + end +end diff --git a/lib/gitlab/kubernetes/helm/install_command.rb b/lib/gitlab/kubernetes/helm/install_command.rb index bf6981035f4..30af3e97b4a 100644 --- a/lib/gitlab/kubernetes/helm/install_command.rb +++ b/lib/gitlab/kubernetes/helm/install_command.rb @@ -1,54 +1,45 @@ module Gitlab module Kubernetes module Helm - class InstallCommand - attr_reader :name, :install_helm, :chart, :chart_values_file + class InstallCommand < BaseCommand + attr_reader :name, :chart, :repository, :values - def initialize(name, install_helm: false, chart: false, chart_values_file: false) + def initialize(name, chart:, values:, repository: nil) @name = name - @install_helm = install_helm @chart = chart - @chart_values_file = chart_values_file + @values = values + @repository = repository end - def pod_name - "install-#{name}" + def generate_script + super + [ + init_command, + repository_command, + script_command + ].compact.join("\n") end - def generate_script(namespace_name) - [ - install_dps_command, - init_command, - complete_command(namespace_name) - ].join("\n") + def config_map? + true + end + + def config_map_resource + Gitlab::Kubernetes::ConfigMap.new(name, values).generate end private def init_command - if install_helm - 'helm init >/dev/null' - else - 'helm init --client-only >/dev/null' - end + 'helm init --client-only >/dev/null' end - def complete_command(namespace_name) - return unless chart - - if chart_values_file - "helm install #{chart} --name #{name} --namespace #{namespace_name} -f /data/helm/#{name}/config/values.yaml >/dev/null" - else - "helm install #{chart} --name #{name} --namespace #{namespace_name} >/dev/null" - end + def repository_command + "helm repo add #{name} #{repository}" if repository end - def install_dps_command + def script_command <<~HEREDOC - set -eo pipefail - apk add -U ca-certificates openssl >/dev/null - wget -q -O - https://kubernetes-helm.storage.googleapis.com/helm-v#{Gitlab::Kubernetes::Helm::HELM_VERSION}-linux-amd64.tar.gz | tar zxC /tmp >/dev/null - mv /tmp/linux-amd64/helm /usr/bin/ + helm install #{chart} --name #{name} --namespace #{Gitlab::Kubernetes::Helm::NAMESPACE} -f /data/helm/#{name}/config/values.yaml >/dev/null HEREDOC end end diff --git a/lib/gitlab/kubernetes/helm/pod.rb b/lib/gitlab/kubernetes/helm/pod.rb index ca5e06009fa..1e12299eefd 100644 --- a/lib/gitlab/kubernetes/helm/pod.rb +++ b/lib/gitlab/kubernetes/helm/pod.rb @@ -2,18 +2,17 @@ module Gitlab module Kubernetes module Helm class Pod - def initialize(command, namespace_name, kubeclient) + def initialize(command, namespace_name) @command = command @namespace_name = namespace_name - @kubeclient = kubeclient end def generate spec = { containers: [container_specification], restartPolicy: 'Never' } - if command.chart_values_file - create_config_map + if command.config_map? spec[:volumes] = volumes_specification + spec[:containers][0][:volumeMounts] = volume_mounts_specification end ::Kubeclient::Resource.new(metadata: metadata, spec: spec) @@ -21,18 +20,16 @@ module Gitlab private - attr_reader :command, :namespace_name, :kubeclient + attr_reader :command, :namespace_name, :kubeclient, :config_map def container_specification - container = { + { name: 'helm', image: 'alpine:3.6', env: generate_pod_env(command), command: %w(/bin/sh), args: %w(-c $(COMMAND_SCRIPT)) } - container[:volumeMounts] = volume_mounts_specification if command.chart_values_file - container end def labels @@ -50,13 +47,12 @@ module Gitlab } end - def volume_mounts_specification - [ - { - name: 'configuration-volume', - mountPath: "/data/helm/#{command.name}/config" - } - ] + def generate_pod_env(command) + { + HELM_VERSION: Gitlab::Kubernetes::Helm::HELM_VERSION, + TILLER_NAMESPACE: namespace_name, + COMMAND_SCRIPT: command.generate_script + }.map { |key, value| { name: key, value: value } } end def volumes_specification @@ -71,23 +67,13 @@ module Gitlab ] end - def generate_pod_env(command) - { - HELM_VERSION: Gitlab::Kubernetes::Helm::HELM_VERSION, - TILLER_NAMESPACE: namespace_name, - COMMAND_SCRIPT: command.generate_script(namespace_name) - }.map { |key, value| { name: key, value: value } } - end - - def create_config_map - resource = ::Kubeclient::Resource.new - resource.metadata = { - name: "values-content-configuration-#{command.name}", - namespace: namespace_name, - labels: { name: "values-content-configuration-#{command.name}" } - } - resource.data = { values: File.read(command.chart_values_file) } - kubeclient.create_config_map(resource) + def volume_mounts_specification + [ + { + name: 'configuration-volume', + mountPath: "/data/helm/#{command.name}/config" + } + ] end end end diff --git a/spec/factories/clusters/applications/helm.rb b/spec/factories/clusters/applications/helm.rb index 775fbb3d27b..3deca103578 100644 --- a/spec/factories/clusters/applications/helm.rb +++ b/spec/factories/clusters/applications/helm.rb @@ -34,5 +34,6 @@ FactoryBot.define do factory :clusters_applications_ingress, class: Clusters::Applications::Ingress factory :clusters_applications_prometheus, class: Clusters::Applications::Prometheus + factory :clusters_applications_runner, class: Clusters::Applications::Runner end end diff --git a/spec/javascripts/clusters/components/applications_spec.js b/spec/javascripts/clusters/components/applications_spec.js index dfb4cc1b9b1..d546543d273 100644 --- a/spec/javascripts/clusters/components/applications_spec.js +++ b/spec/javascripts/clusters/components/applications_spec.js @@ -38,11 +38,9 @@ describe('Applications', () => { expect(vm.$el.querySelector('.js-cluster-application-row-prometheus')).toBeDefined(); }); - /* * / it('renders a row for GitLab Runner', () => { expect(vm.$el.querySelector('.js-cluster-application-row-runner')).toBeDefined(); }); - /* */ }); describe('Ingress application', () => { diff --git a/spec/lib/gitlab/kubernetes/config_map_spec.rb b/spec/lib/gitlab/kubernetes/config_map_spec.rb new file mode 100644 index 00000000000..33dfa461202 --- /dev/null +++ b/spec/lib/gitlab/kubernetes/config_map_spec.rb @@ -0,0 +1,25 @@ +require 'spec_helper' + +describe Gitlab::Kubernetes::ConfigMap do + let(:kubeclient) { double('kubernetes client') } + let(:application) { create(:clusters_applications_prometheus) } + let(:config_map) { described_class.new(application.name, application.values) } + let(:namespace) { Gitlab::Kubernetes::Helm::NAMESPACE } + + let(:metadata) do + { + name: "values-content-configuration-#{application.name}", + namespace: namespace, + labels: { name: "values-content-configuration-#{application.name}" } + } + end + + describe '#generate' do + let(:resource) { ::Kubeclient::Resource.new(metadata: metadata, data: { values: application.values }) } + subject { config_map.generate } + + it 'should build a Kubeclient Resource' do + is_expected.to eq(resource) + end + end +end diff --git a/spec/lib/gitlab/kubernetes/helm/api_spec.rb b/spec/lib/gitlab/kubernetes/helm/api_spec.rb index 69112fe90b1..740466ea5cb 100644 --- a/spec/lib/gitlab/kubernetes/helm/api_spec.rb +++ b/spec/lib/gitlab/kubernetes/helm/api_spec.rb @@ -5,14 +5,21 @@ describe Gitlab::Kubernetes::Helm::Api do let(:helm) { described_class.new(client) } let(:gitlab_namespace) { Gitlab::Kubernetes::Helm::NAMESPACE } let(:namespace) { Gitlab::Kubernetes::Namespace.new(gitlab_namespace, client) } - let(:install_helm) { true } - let(:chart) { 'stable/a_chart' } - let(:application_name) { 'app_name' } - let(:command) { Gitlab::Kubernetes::Helm::InstallCommand.new(application_name, install_helm: install_helm, chart: chart) } + let(:application) { create(:clusters_applications_prometheus) } + + let(:command) do + Gitlab::Kubernetes::Helm::InstallCommand.new( + application.name, + chart: application.chart, + values: application.values + ) + end + subject { helm } before do allow(Gitlab::Kubernetes::Namespace).to receive(:new).with(gitlab_namespace, client).and_return(namespace) + allow(client).to receive(:create_config_map) end describe '#initialize' do @@ -26,6 +33,7 @@ describe Gitlab::Kubernetes::Helm::Api do describe '#install' do before do allow(client).to receive(:create_pod).and_return(nil) + allow(client).to receive(:create_config_map).and_return(nil) allow(namespace).to receive(:ensure_exists!).once end @@ -35,6 +43,16 @@ describe Gitlab::Kubernetes::Helm::Api do subject.install(command) end + + context 'with a ConfigMap' do + let(:resource) { Gitlab::Kubernetes::ConfigMap.new(application.name, application.values).generate } + + it 'creates a ConfigMap on kubeclient' do + expect(client).to receive(:create_config_map).with(resource).once + + subject.install(command) + end + end end describe '#installation_status' do diff --git a/spec/lib/gitlab/kubernetes/helm/base_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/base_command_spec.rb new file mode 100644 index 00000000000..3cfdae794f6 --- /dev/null +++ b/spec/lib/gitlab/kubernetes/helm/base_command_spec.rb @@ -0,0 +1,44 @@ +require 'spec_helper' + +describe Gitlab::Kubernetes::Helm::BaseCommand do + let(:application) { create(:clusters_applications_helm) } + let(:base_command) { described_class.new(application.name) } + + describe '#generate_script' do + let(:helm_version) { Gitlab::Kubernetes::Helm::HELM_VERSION } + let(:command) do + <<~HEREDOC + set -eo pipefail + apk add -U ca-certificates openssl >/dev/null + wget -q -O - https://kubernetes-helm.storage.googleapis.com/helm-v#{helm_version}-linux-amd64.tar.gz | tar zxC /tmp >/dev/null + mv /tmp/linux-amd64/helm /usr/bin/ + HEREDOC + end + + subject { base_command.generate_script } + + it 'should return a command that prepares the environment for helm-cli' do + expect(subject).to eq(command) + end + end + + describe '#pod_resource' do + subject { base_command.pod_resource } + + it 'should returns a kubeclient resoure with pod content for application' do + is_expected.to be_an_instance_of ::Kubeclient::Resource + end + end + + describe '#config_map?' do + subject { base_command.config_map? } + + it { is_expected.to be_falsy } + end + + describe '#pod_name' do + subject { base_command.pod_name } + + it { is_expected.to eq('install-helm') } + end +end diff --git a/spec/lib/gitlab/kubernetes/helm/init_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/init_command_spec.rb new file mode 100644 index 00000000000..e6920b0a76f --- /dev/null +++ b/spec/lib/gitlab/kubernetes/helm/init_command_spec.rb @@ -0,0 +1,24 @@ +require 'spec_helper' + +describe Gitlab::Kubernetes::Helm::InitCommand do + let(:application) { create(:clusters_applications_helm) } + let(:init_command) { described_class.new(application.name) } + + describe '#generate_script' do + let(:command) do + <<~MSG.chomp + set -eo pipefail + apk add -U ca-certificates openssl >/dev/null + wget -q -O - https://kubernetes-helm.storage.googleapis.com/helm-v2.7.0-linux-amd64.tar.gz | tar zxC /tmp >/dev/null + mv /tmp/linux-amd64/helm /usr/bin/ + helm init >/dev/null + MSG + end + + subject { init_command.generate_script } + + it 'should return the appropriate command' do + is_expected.to eq(command) + end + end +end diff --git a/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb b/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb index 63997a40d52..137b8f718de 100644 --- a/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb +++ b/spec/lib/gitlab/kubernetes/helm/install_command_spec.rb @@ -1,79 +1,56 @@ require 'rails_helper' describe Gitlab::Kubernetes::Helm::InstallCommand do - let(:prometheus) { create(:clusters_applications_prometheus) } - - describe "#initialize" do - context "With all the params" do - subject { described_class.new(prometheus.name, install_helm: true, chart: prometheus.chart, chart_values_file: prometheus.chart_values_file) } - - it 'should assign all parameters' do - expect(subject.name).to eq(prometheus.name) - expect(subject.install_helm).to be_truthy - expect(subject.chart).to eq(prometheus.chart) - expect(subject.chart_values_file).to eq("#{Rails.root}/vendor/prometheus/values.yaml") - end - end - - context 'when install_helm is not set' do - subject { described_class.new(prometheus.name, chart: prometheus.chart, chart_values_file: true) } - - it 'should set install_helm as false' do - expect(subject.install_helm).to be_falsy - end - end - - context 'when chart is not set' do - subject { described_class.new(prometheus.name, install_helm: true) } + let(:application) { create(:clusters_applications_prometheus) } + let(:namespace) { Gitlab::Kubernetes::Helm::NAMESPACE } + + let(:install_command) do + described_class.new( + application.name, + chart: application.chart, + values: application.values + ) + end - it 'should set chart as nil' do - expect(subject.chart).to be_falsy - end + describe '#generate_script' do + let(:command) do + <<~MSG + set -eo pipefail + apk add -U ca-certificates openssl >/dev/null + wget -q -O - https://kubernetes-helm.storage.googleapis.com/helm-v2.7.0-linux-amd64.tar.gz | tar zxC /tmp >/dev/null + mv /tmp/linux-amd64/helm /usr/bin/ + helm init --client-only >/dev/null + helm install #{application.chart} --name #{application.name} --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null + MSG end - context 'when chart_values_file is not set' do - subject { described_class.new(prometheus.name, install_helm: true, chart: prometheus.chart) } + subject { install_command.generate_script } - it 'should set chart_values_file as nil' do - expect(subject.chart_values_file).to be_falsy - end + it 'should return appropriate command' do + is_expected.to eq(command) end - end - - describe "#generate_script" do - let(:install_command) { described_class.new(prometheus.name, install_helm: install_helm) } - let(:client) { double('kubernetes client') } - let(:namespace) { Gitlab::Kubernetes::Namespace.new(Gitlab::Kubernetes::Helm::NAMESPACE, client) } - subject { install_command.send(:generate_script, namespace.name) } - context 'when install helm is true' do - let(:install_helm) { true } - let(:command) do - <<~MSG - set -eo pipefail - apk add -U ca-certificates openssl >/dev/null - wget -q -O - https://kubernetes-helm.storage.googleapis.com/helm-v2.7.0-linux-amd64.tar.gz | tar zxC /tmp >/dev/null - mv /tmp/linux-amd64/helm /usr/bin/ - - helm init >/dev/null - MSG + context 'with an application with a repository' do + let(:ci_runner) { create(:ci_runner) } + let(:application) { create(:clusters_applications_runner, runner: ci_runner) } + let(:install_command) do + described_class.new( + application.name, + chart: application.chart, + values: application.values, + repository: application.repository + ) end - it 'should return appropriate command' do - is_expected.to eq(command) - end - end - - context 'when install helm is false' do - let(:install_helm) { false } let(:command) do <<~MSG set -eo pipefail apk add -U ca-certificates openssl >/dev/null wget -q -O - https://kubernetes-helm.storage.googleapis.com/helm-v2.7.0-linux-amd64.tar.gz | tar zxC /tmp >/dev/null mv /tmp/linux-amd64/helm /usr/bin/ - helm init --client-only >/dev/null + helm repo add #{application.name} #{application.repository} + helm install #{application.chart} --name #{application.name} --namespace #{namespace} -f /data/helm/#{application.name}/config/values.yaml >/dev/null MSG end @@ -81,50 +58,29 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do is_expected.to eq(command) end end + end - context 'when chart is present' do - let(:install_command) { described_class.new(prometheus.name, chart: prometheus.chart) } - let(:command) do - <<~MSG.chomp - set -eo pipefail - apk add -U ca-certificates openssl >/dev/null - wget -q -O - https://kubernetes-helm.storage.googleapis.com/helm-v2.7.0-linux-amd64.tar.gz | tar zxC /tmp >/dev/null - mv /tmp/linux-amd64/helm /usr/bin/ + describe '#config_map?' do + subject { install_command.config_map? } - helm init --client-only >/dev/null - helm install #{prometheus.chart} --name #{prometheus.name} --namespace #{namespace.name} >/dev/null - MSG - end + it { is_expected.to be_truthy } + end - it 'should return appropriate command' do - is_expected.to eq(command) - end + describe '#config_map_resource' do + let(:metadata) do + { + name: "values-content-configuration-#{application.name}", + namespace: namespace, + labels: { name: "values-content-configuration-#{application.name}" } + } end - context 'when chart values file is present' do - let(:install_command) { described_class.new(prometheus.name, chart: prometheus.chart, chart_values_file: prometheus.chart_values_file) } - let(:command) do - <<~MSG.chomp - set -eo pipefail - apk add -U ca-certificates openssl >/dev/null - wget -q -O - https://kubernetes-helm.storage.googleapis.com/helm-v2.7.0-linux-amd64.tar.gz | tar zxC /tmp >/dev/null - mv /tmp/linux-amd64/helm /usr/bin/ + let(:resource) { ::Kubeclient::Resource.new(metadata: metadata, data: { values: application.values }) } - helm init --client-only >/dev/null - helm install #{prometheus.chart} --name #{prometheus.name} --namespace #{namespace.name} -f /data/helm/#{prometheus.name}/config/values.yaml >/dev/null - MSG - end + subject { install_command.config_map_resource } - it 'should return appropriate command' do - is_expected.to eq(command) - end + it 'returns a KubeClient resource with config map content for the application' do + is_expected.to eq(resource) end end - - describe "#pod_name" do - let(:install_command) { described_class.new(prometheus.name, install_helm: true, chart: prometheus.chart, chart_values_file: true) } - subject { install_command.send(:pod_name) } - - it { is_expected.to eq('install-prometheus') } - end end diff --git a/spec/lib/gitlab/kubernetes/helm/pod_spec.rb b/spec/lib/gitlab/kubernetes/helm/pod_spec.rb index ebb6033f71e..43adc80d576 100644 --- a/spec/lib/gitlab/kubernetes/helm/pod_spec.rb +++ b/spec/lib/gitlab/kubernetes/helm/pod_spec.rb @@ -5,13 +5,9 @@ describe Gitlab::Kubernetes::Helm::Pod do let(:cluster) { create(:cluster) } let(:app) { create(:clusters_applications_prometheus, cluster: cluster) } let(:command) { app.install_command } - let(:client) { double('kubernetes client') } - let(:namespace) { Gitlab::Kubernetes::Namespace.new(Gitlab::Kubernetes::Helm::NAMESPACE, client) } - subject { described_class.new(command, namespace.name, client) } + let(:namespace) { Gitlab::Kubernetes::Helm::NAMESPACE } - before do - allow(client).to receive(:create_config_map).and_return(nil) - end + subject { described_class.new(command, namespace) } shared_examples 'helm pod' do it 'should generate a Kubeclient::Resource' do @@ -47,7 +43,7 @@ describe Gitlab::Kubernetes::Helm::Pod do end end - context 'with a configuration file' do + context 'with a install command' do it_behaves_like 'helm pod' it 'should include volumes for the container' do @@ -62,14 +58,14 @@ describe Gitlab::Kubernetes::Helm::Pod do end it 'should mount configMap specification in the volume' do - spec = subject.generate.spec - expect(spec.volumes.first.configMap['name']).to eq("values-content-configuration-#{app.name}") - expect(spec.volumes.first.configMap['items'].first['key']).to eq('values') - expect(spec.volumes.first.configMap['items'].first['path']).to eq('values.yaml') + volume = subject.generate.spec.volumes.first + expect(volume.configMap['name']).to eq("values-content-configuration-#{app.name}") + expect(volume.configMap['items'].first['key']).to eq('values') + expect(volume.configMap['items'].first['path']).to eq('values.yaml') end end - context 'without a configuration file' do + context 'with a init command' do let(:app) { create(:clusters_applications_helm, cluster: cluster) } it_behaves_like 'helm pod' diff --git a/spec/models/clusters/applications/helm_spec.rb b/spec/models/clusters/applications/helm_spec.rb index eb57abaf6ef..ba7bad617b4 100644 --- a/spec/models/clusters/applications/helm_spec.rb +++ b/spec/models/clusters/applications/helm_spec.rb @@ -1,102 +1,17 @@ require 'rails_helper' describe Clusters::Applications::Helm do - it { is_expected.to belong_to(:cluster) } - it { is_expected.to validate_presence_of(:cluster) } - - describe '#name' do - it 'is .application_name' do - expect(subject.name).to eq(described_class.application_name) - end - - it 'is recorded in Clusters::Cluster::APPLICATIONS' do - expect(Clusters::Cluster::APPLICATIONS[subject.name]).to eq(described_class) - end - end - - describe '#version' do - it 'defaults to Gitlab::Kubernetes::Helm::HELM_VERSION' do - expect(subject.version).to eq(Gitlab::Kubernetes::Helm::HELM_VERSION) - end - end - - describe '#status' do - let(:cluster) { create(:cluster) } - - subject { described_class.new(cluster: cluster) } - - it 'defaults to :not_installable' do - expect(subject.status_name).to be(:not_installable) - end - - context 'when platform kubernetes is defined' do - let(:cluster) { create(:cluster, :provided_by_gcp) } - - it 'defaults to :installable' do - expect(subject.status_name).to be(:installable) - end - end - end + include_examples 'cluster application core specs', :clusters_applications_helm describe '#install_command' do - it 'has all the needed information' do - expect(subject.install_command).to have_attributes(name: subject.name, install_helm: true) - end - end - - describe 'status state machine' do - describe '#make_installing' do - subject { create(:clusters_applications_helm, :scheduled) } - - it 'is installing' do - subject.make_installing! - - expect(subject).to be_installing - end - end - - describe '#make_installed' do - subject { create(:clusters_applications_helm, :installing) } - - it 'is installed' do - subject.make_installed - - expect(subject).to be_installed - end - end - - describe '#make_errored' do - subject { create(:clusters_applications_helm, :installing) } - let(:reason) { 'some errors' } - - it 'is errored' do - subject.make_errored(reason) - - expect(subject).to be_errored - expect(subject.status_reason).to eq(reason) - end - end - - describe '#make_scheduled' do - subject { create(:clusters_applications_helm, :installable) } - - it 'is scheduled' do - subject.make_scheduled - - expect(subject).to be_scheduled - end - - describe 'when was errored' do - subject { create(:clusters_applications_helm, :errored) } + let(:helm) { create(:clusters_applications_helm) } - it 'clears #status_reason' do - expect(subject.status_reason).not_to be_nil + subject { helm.install_command } - subject.make_scheduled! + it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InitCommand) } - expect(subject.status_reason).to be_nil - end - end + it 'should be initialized with 1 arguments' do + expect(subject.name).to eq('helm') end end end diff --git a/spec/models/clusters/applications/ingress_spec.rb b/spec/models/clusters/applications/ingress_spec.rb index a34f4ff2b48..03f5b88a525 100644 --- a/spec/models/clusters/applications/ingress_spec.rb +++ b/spec/models/clusters/applications/ingress_spec.rb @@ -1,16 +1,16 @@ require 'rails_helper' describe Clusters::Applications::Ingress do - it { is_expected.to belong_to(:cluster) } - it { is_expected.to validate_presence_of(:cluster) } + let(:ingress) { create(:clusters_applications_ingress) } + + include_examples 'cluster application core specs', :clusters_applications_ingress + include_examples 'cluster application status specs', :cluster_application_ingress before do allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_in) allow(ClusterWaitForIngressIpAddressWorker).to receive(:perform_async) end - include_examples 'cluster application specs', described_class - describe '#make_installed!' do before do application.make_installed! @@ -52,4 +52,27 @@ describe Clusters::Applications::Ingress do end end end + + describe '#install_command' do + subject { ingress.install_command } + + it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) } + + it 'should be initialized with ingress arguments' do + expect(subject.name).to eq('ingress') + expect(subject.chart).to eq('stable/nginx-ingress') + expect(subject.values).to eq(ingress.values) + end + end + + describe '#values' do + subject { ingress.values } + + it 'should include ingress valid keys' do + is_expected.to include('image') + is_expected.to include('repository') + is_expected.to include('stats') + is_expected.to include('podAnnotations') + end + end end diff --git a/spec/models/clusters/applications/prometheus_spec.rb b/spec/models/clusters/applications/prometheus_spec.rb index 01037919530..df8a508e021 100644 --- a/spec/models/clusters/applications/prometheus_spec.rb +++ b/spec/models/clusters/applications/prometheus_spec.rb @@ -1,10 +1,8 @@ require 'rails_helper' describe Clusters::Applications::Prometheus do - it { is_expected.to belong_to(:cluster) } - it { is_expected.to validate_presence_of(:cluster) } - - include_examples 'cluster application specs', described_class + include_examples 'cluster application core specs', :clusters_applications_prometheus + include_examples 'cluster application status specs', :cluster_application_prometheus describe 'transition to installed' do let(:project) { create(:project) } @@ -24,14 +22,6 @@ describe Clusters::Applications::Prometheus do end end - describe "#chart_values_file" do - subject { create(:clusters_applications_prometheus).chart_values_file } - - it 'should return chart values file path' do - expect(subject).to eq("#{Rails.root}/vendor/prometheus/values.yaml") - end - end - describe '#proxy_client' do context 'cluster is nil' do it 'returns nil' do @@ -85,4 +75,33 @@ describe Clusters::Applications::Prometheus do end end end + + describe '#install_command' do + let(:kubeclient) { double('kubernetes client') } + let(:prometheus) { create(:clusters_applications_prometheus) } + + subject { prometheus.install_command } + + it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) } + + it 'should be initialized with 3 arguments' do + expect(subject.name).to eq('prometheus') + expect(subject.chart).to eq('stable/prometheus') + expect(subject.values).to eq(prometheus.values) + end + end + + describe '#values' do + let(:prometheus) { create(:clusters_applications_prometheus) } + + subject { prometheus.values } + + it 'should include prometheus valid values' do + is_expected.to include('alertmanager') + is_expected.to include('kubeStateMetrics') + is_expected.to include('nodeExporter') + is_expected.to include('pushgateway') + is_expected.to include('serverFiles') + end + end end diff --git a/spec/models/clusters/applications/runner_spec.rb b/spec/models/clusters/applications/runner_spec.rb new file mode 100644 index 00000000000..612a3c8e413 --- /dev/null +++ b/spec/models/clusters/applications/runner_spec.rb @@ -0,0 +1,69 @@ +require 'rails_helper' + +describe Clusters::Applications::Runner do + let(:ci_runner) { create(:ci_runner) } + + include_examples 'cluster application core specs', :clusters_applications_runner + include_examples 'cluster application status specs', :cluster_application_runner + + it { is_expected.to belong_to(:runner) } + + describe '#install_command' do + let(:kubeclient) { double('kubernetes client') } + let(:gitlab_runner) { create(:clusters_applications_runner, runner: ci_runner) } + + subject { gitlab_runner.install_command } + + it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) } + + it 'should be initialized with 4 arguments' do + expect(subject.name).to eq('runner') + expect(subject.chart).to eq('runner/gitlab-runner') + expect(subject.repository).to eq('https://charts.gitlab.io') + expect(subject.values).to eq(gitlab_runner.values) + end + end + + describe '#values' do + let(:gitlab_runner) { create(:clusters_applications_runner, runner: ci_runner) } + + subject { gitlab_runner.values } + + it 'should include runner valid values' do + is_expected.to include('concurrent') + is_expected.to include('checkInterval') + is_expected.to include('rbac') + is_expected.to include('runners') + is_expected.to include('resources') + is_expected.to include("runnerToken: #{ci_runner.token}") + is_expected.to include("gitlabUrl: #{Gitlab::Routing.url_helpers.root_url}") + end + + context 'without a runner' do + let(:project) { create(:project) } + let(:cluster) { create(:cluster) } + let(:gitlab_runner) { create(:clusters_applications_runner, cluster: cluster) } + + before do + cluster.projects << project + end + + it 'creates a runner' do + expect do + subject + end.to change { Ci::Runner.count }.by(1) + end + + it 'uses the new runner token' do + expect(subject).to include("runnerToken: #{gitlab_runner.reload.runner.token}") + end + + it 'assigns the new runner to runner' do + subject + gitlab_runner.reload + + expect(gitlab_runner.runner).not_to be_nil + end + end + end +end diff --git a/spec/models/clusters/cluster_spec.rb b/spec/models/clusters/cluster_spec.rb index 799d7ced116..8f12a0e3085 100644 --- a/spec/models/clusters/cluster_spec.rb +++ b/spec/models/clusters/cluster_spec.rb @@ -8,6 +8,7 @@ describe Clusters::Cluster do it { is_expected.to have_one(:application_helm) } it { is_expected.to have_one(:application_ingress) } it { is_expected.to have_one(:application_prometheus) } + it { is_expected.to have_one(:application_runner) } it { is_expected.to delegate_method(:status).to(:provider) } it { is_expected.to delegate_method(:status_reason).to(:provider) } it { is_expected.to delegate_method(:status_name).to(:provider) } @@ -196,9 +197,10 @@ describe Clusters::Cluster do let!(:helm) { create(:clusters_applications_helm, cluster: cluster) } let!(:ingress) { create(:clusters_applications_ingress, cluster: cluster) } let!(:prometheus) { create(:clusters_applications_prometheus, cluster: cluster) } + let!(:runner) { create(:clusters_applications_runner, cluster: cluster) } it 'returns a list of created applications' do - is_expected.to contain_exactly(helm, ingress, prometheus) + is_expected.to contain_exactly(helm, ingress, prometheus, runner) end end end diff --git a/spec/support/cluster_application_spec.rb b/spec/support/cluster_application_spec.rb deleted file mode 100644 index ab77910a050..00000000000 --- a/spec/support/cluster_application_spec.rb +++ /dev/null @@ -1,105 +0,0 @@ -shared_examples 'cluster application specs' do - let(:factory_name) { described_class.to_s.downcase.gsub("::", "_") } - - describe '#name' do - it 'is .application_name' do - expect(subject.name).to eq(described_class.application_name) - end - - it 'is recorded in Clusters::Cluster::APPLICATIONS' do - expect(Clusters::Cluster::APPLICATIONS[subject.name]).to eq(described_class) - end - end - - describe '#status' do - let(:cluster) { create(:cluster, :provided_by_gcp) } - - subject { described_class.new(cluster: cluster) } - - it 'defaults to :not_installable' do - expect(subject.status_name).to be(:not_installable) - end - - context 'when application helm is scheduled' do - before do - create(factory_name, :scheduled, cluster: cluster) - end - - it 'defaults to :not_installable' do - expect(subject.status_name).to be(:not_installable) - end - end - - context 'when application helm is installed' do - before do - create(:clusters_applications_helm, :installed, cluster: cluster) - end - - it 'defaults to :installable' do - expect(subject.status_name).to be(:installable) - end - end - end - - describe '#install_command' do - it 'has all the needed information' do - expect(subject.install_command).to have_attributes(name: subject.name, install_helm: false) - end - end - - describe 'status state machine' do - describe '#make_installing' do - subject { create(factory_name, :scheduled) } - - it 'is installing' do - subject.make_installing! - - expect(subject).to be_installing - end - end - - describe '#make_installed' do - subject { create(factory_name, :installing) } - - it 'is installed' do - subject.make_installed - - expect(subject).to be_installed - end - end - - describe '#make_errored' do - subject { create(factory_name, :installing) } - let(:reason) { 'some errors' } - - it 'is errored' do - subject.make_errored(reason) - - expect(subject).to be_errored - expect(subject.status_reason).to eq(reason) - end - end - - describe '#make_scheduled' do - subject { create(factory_name, :installable) } - - it 'is scheduled' do - subject.make_scheduled - - expect(subject).to be_scheduled - end - - describe 'when was errored' do - subject { create(factory_name, :errored) } - - it 'clears #status_reason' do - expect(subject.status_reason).not_to be_nil - - subject.make_scheduled! - - expect(subject.status_reason).to be_nil - end - end - end - end -end diff --git a/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb b/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb new file mode 100644 index 00000000000..87d12a784ba --- /dev/null +++ b/spec/support/shared_examples/models/cluster_application_core_shared_examples.rb @@ -0,0 +1,70 @@ +shared_examples 'cluster application core specs' do |application_name| + it { is_expected.to belong_to(:cluster) } + it { is_expected.to validate_presence_of(:cluster) } + + describe '#name' do + it 'is .application_name' do + expect(subject.name).to eq(described_class.application_name) + end + + it 'is recorded in Clusters::Cluster::APPLICATIONS' do + expect(Clusters::Cluster::APPLICATIONS[subject.name]).to eq(described_class) + end + end + + describe 'status state machine' do + describe '#make_installing' do + subject { create(application_name, :scheduled) } + + it 'is installing' do + subject.make_installing! + + expect(subject).to be_installing + end + end + + describe '#make_installed' do + subject { create(application_name, :installing) } + + it 'is installed' do + subject.make_installed + + expect(subject).to be_installed + end + end + + describe '#make_errored' do + subject { create(application_name, :installing) } + let(:reason) { 'some errors' } + + it 'is errored' do + subject.make_errored(reason) + + expect(subject).to be_errored + expect(subject.status_reason).to eq(reason) + end + end + + describe '#make_scheduled' do + subject { create(application_name, :installable) } + + it 'is scheduled' do + subject.make_scheduled + + expect(subject).to be_scheduled + end + + describe 'when was errored' do + subject { create(application_name, :errored) } + + it 'clears #status_reason' do + expect(subject.status_reason).not_to be_nil + + subject.make_scheduled! + + expect(subject.status_reason).to be_nil + end + end + end + end +end diff --git a/spec/support/shared_examples/models/cluster_application_status_shared_examples.rb b/spec/support/shared_examples/models/cluster_application_status_shared_examples.rb new file mode 100644 index 00000000000..765dd32f4ba --- /dev/null +++ b/spec/support/shared_examples/models/cluster_application_status_shared_examples.rb @@ -0,0 +1,31 @@ +shared_examples 'cluster application status specs' do |application_name| + describe '#status' do + let(:cluster) { create(:cluster, :provided_by_gcp) } + + subject { described_class.new(cluster: cluster) } + + it 'sets a default status' do + expect(subject.status_name).to be(:not_installable) + end + + context 'when application helm is scheduled' do + before do + create(:clusters_applications_helm, :scheduled, cluster: cluster) + end + + it 'defaults to :not_installable' do + expect(subject.status_name).to be(:not_installable) + end + end + + context 'when application is scheduled' do + before do + create(:clusters_applications_helm, :installed, cluster: cluster) + end + + it 'sets a default status' do + expect(subject.status_name).to be(:installable) + end + end + end +end diff --git a/vendor/runner/values.yaml b/vendor/runner/values.yaml new file mode 100644 index 00000000000..b7e2e24acaf --- /dev/null +++ b/vendor/runner/values.yaml @@ -0,0 +1,25 @@ +## Configure the maximum number of concurrent jobs +## - Documentation: https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-global-section +## - Default value: 10 +## - Currently don't support auto-scaling. +concurrent: 4 + +## Defines in seconds how often to check GitLab for a new builds +## - Documentation: https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-global-section +## - Default value: 3 +checkInterval: 3 + +## For RBAC support +rbac: + create: false + clusterWideAccess: false + +## Configuration for the Pods that that the runner launches for each new job +## +runners: + image: ubuntu:16.04 + privileged: false + builds: {} + services: {} + helpers: {} +resources: {} |