Extend Cluster Applications to install GitLab Runner to Kubernetes cluster
This commit is contained in:
parent
947a7f8587
commit
c607008ee5
35 changed files with 768 additions and 421 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
68
app/models/clusters/applications/runner.rb
Normal file
68
app/models/clusters/applications/runner.rb
Normal file
|
@ -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
|
|
@ -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
|
||||
|
||||
|
|
23
app/models/clusters/concerns/application_data.rb
Normal file
23
app/models/clusters/concerns/application_data.rb
Normal file
|
@ -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
|
|
@ -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,
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Allow installation of GitLab Runner with a single click
|
||||
merge_request: 17134
|
||||
author:
|
||||
type: added
|
|
@ -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
|
15
db/schema.rb
15
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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
37
lib/gitlab/kubernetes/config_map.rb
Normal file
37
lib/gitlab/kubernetes/config_map.rb
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
40
lib/gitlab/kubernetes/helm/base_command.rb
Normal file
40
lib/gitlab/kubernetes/helm/base_command.rb
Normal file
|
@ -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
|
19
lib/gitlab/kubernetes/helm/init_command.rb
Normal file
19
lib/gitlab/kubernetes/helm/init_command.rb
Normal file
|
@ -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
|
|
@ -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}"
|
||||
end
|
||||
|
||||
def generate_script(namespace_name)
|
||||
[
|
||||
install_dps_command,
|
||||
def generate_script
|
||||
super + [
|
||||
init_command,
|
||||
complete_command(namespace_name)
|
||||
].join("\n")
|
||||
repository_command,
|
||||
script_command
|
||||
].compact.join("\n")
|
||||
end
|
||||
|
||||
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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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', () => {
|
||||
|
|
25
spec/lib/gitlab/kubernetes/config_map_spec.rb
Normal file
25
spec/lib/gitlab/kubernetes/config_map_spec.rb
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
44
spec/lib/gitlab/kubernetes/helm/base_command_spec.rb
Normal file
44
spec/lib/gitlab/kubernetes/helm/base_command_spec.rb
Normal file
|
@ -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
|
24
spec/lib/gitlab/kubernetes/helm/init_command_spec.rb
Normal file
24
spec/lib/gitlab/kubernetes/helm/init_command_spec.rb
Normal file
|
@ -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
|
|
@ -1,117 +1,56 @@
|
|||
require 'rails_helper'
|
||||
|
||||
describe Gitlab::Kubernetes::Helm::InstallCommand do
|
||||
let(:prometheus) { create(:clusters_applications_prometheus) }
|
||||
let(:application) { create(:clusters_applications_prometheus) }
|
||||
let(:namespace) { Gitlab::Kubernetes::Helm::NAMESPACE }
|
||||
|
||||
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) }
|
||||
|
||||
it 'should set chart as nil' do
|
||||
expect(subject.chart).to be_falsy
|
||||
end
|
||||
end
|
||||
|
||||
context 'when chart_values_file is not set' do
|
||||
subject { described_class.new(prometheus.name, install_helm: true, chart: prometheus.chart) }
|
||||
|
||||
it 'should set chart_values_file as nil' do
|
||||
expect(subject.chart_values_file).to be_falsy
|
||||
end
|
||||
end
|
||||
let(:install_command) do
|
||||
described_class.new(
|
||||
application.name,
|
||||
chart: application.chart,
|
||||
values: application.values
|
||||
)
|
||||
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) }
|
||||
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
|
||||
|
||||
subject { install_command.generate_script }
|
||||
|
||||
it 'should return appropriate command' do
|
||||
is_expected.to eq(command)
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
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
|
||||
MSG
|
||||
end
|
||||
|
||||
it 'should return appropriate command' do
|
||||
is_expected.to eq(command)
|
||||
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/
|
||||
|
||||
helm init --client-only >/dev/null
|
||||
helm install #{prometheus.chart} --name #{prometheus.name} --namespace #{namespace.name} >/dev/null
|
||||
MSG
|
||||
end
|
||||
|
||||
it 'should return appropriate command' do
|
||||
is_expected.to eq(command)
|
||||
end
|
||||
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/
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
|
@ -121,10 +60,27 @@ describe Gitlab::Kubernetes::Helm::InstallCommand do
|
|||
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) }
|
||||
describe '#config_map?' do
|
||||
subject { install_command.config_map? }
|
||||
|
||||
it { is_expected.to eq('install-prometheus') }
|
||||
it { is_expected.to be_truthy }
|
||||
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
|
||||
|
||||
let(:resource) { ::Kubeclient::Resource.new(metadata: metadata, data: { values: application.values }) }
|
||||
|
||||
subject { install_command.config_map_resource }
|
||||
|
||||
it 'returns a KubeClient resource with config map content for the application' do
|
||||
is_expected.to eq(resource)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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
|
||||
let(:helm) { create(:clusters_applications_helm) }
|
||||
|
||||
describe 'status state machine' do
|
||||
describe '#make_installing' do
|
||||
subject { create(:clusters_applications_helm, :scheduled) }
|
||||
subject { helm.install_command }
|
||||
|
||||
it 'is installing' do
|
||||
subject.make_installing!
|
||||
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InitCommand) }
|
||||
|
||||
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) }
|
||||
|
||||
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
|
||||
it 'should be initialized with 1 arguments' do
|
||||
expect(subject.name).to eq('helm')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
69
spec/models/clusters/applications/runner_spec.rb
Normal file
69
spec/models/clusters/applications/runner_spec.rb
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
25
vendor/runner/values.yaml
vendored
Normal file
25
vendor/runner/values.yaml
vendored
Normal file
|
@ -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: {}
|
Loading…
Reference in a new issue