Commit 998935a5 authored by Stan Hu's avatar Stan Hu

Merge branch 'ce-to-ee-2018-03-02' into 'master'

CE upstream - 2018-03-02 12:25 UTC

Closes gitaly#1046

See merge request gitlab-org/gitlab-ee!4807
parents 824eeb4a 69c9cbad
......@@ -426,7 +426,7 @@ group :ed25519 do
end
# Gitaly GRPC client
gem 'gitaly-proto', '~> 0.85.0', require: 'gitaly'
gem 'gitaly-proto', '~> 0.87.0', require: 'gitaly'
# Locked until https://github.com/google/protobuf/issues/4210 is closed
gem 'google-protobuf', '= 3.5.1'
......
......@@ -309,7 +309,7 @@ GEM
po_to_json (>= 1.0.0)
rails (>= 3.2.0)
gherkin-ruby (0.3.2)
gitaly-proto (0.85.0)
gitaly-proto (0.87.0)
google-protobuf (~> 3.1)
grpc (~> 1.0)
github-linguist (5.3.3)
......@@ -1091,7 +1091,7 @@ DEPENDENCIES
gettext (~> 3.2.2)
gettext_i18n_rails (~> 1.8.0)
gettext_i18n_rails_js (~> 1.2.0)
gitaly-proto (~> 0.85.0)
gitaly-proto (~> 0.87.0)
github-linguist (~> 5.3.3)
gitlab-flowdock-git-hook (~> 1.0.1)
gitlab-license (~> 1.0)
......
......@@ -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
......
......@@ -14,37 +14,31 @@ class Projects::CommitsController < Projects::ApplicationController
@merge_request = MergeRequestsFinder.new(current_user, project_id: @project.id).execute.opened
.find_by(source_project: @project, source_branch: @ref, target_branch: @repository.root_ref)
# https://gitlab.com/gitlab-org/gitaly/issues/931
Gitlab::GitalyClient.allow_n_plus_1_calls do
respond_to do |format|
format.html
format.atom { render layout: 'xml.atom' }
respond_to do |format|
format.html
format.atom { render layout: 'xml.atom' }
format.json do
pager_json(
'projects/commits/_commits',
@commits.size,
project: @project,
ref: @ref)
end
format.json do
pager_json(
'projects/commits/_commits',
@commits.size,
project: @project,
ref: @ref)
end
end
end
def signatures
# https://gitlab.com/gitlab-org/gitaly/issues/931
Gitlab::GitalyClient.allow_n_plus_1_calls do
respond_to do |format|
format.json do
render json: {
signatures: @commits.select(&:has_signature?).map do |commit|
{
commit_sha: commit.sha,
html: view_to_html_string('projects/commit/_signature', signature: commit.signature)
}
end
}
end
respond_to do |format|
format.json do
render json: {
signatures: @commits.select(&:has_signature?).map do |commit|
{
commit_sha: commit.sha,
html: view_to_html_string('projects/commit/_signature', signature: commit.signature)
}
end
}
end
end
end
......
......@@ -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
......
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
......@@ -8,7 +8,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
......@@ -24,6 +25,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
......@@ -70,7 +72,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
......
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
......@@ -19,6 +19,7 @@ class Commit
attr_accessor :project, :author
attr_accessor :redacted_description_html
attr_accessor :redacted_title_html
attr_reader :gpg_commit
DIFF_SAFE_LINES = Gitlab::Git::DiffCollection::DEFAULT_LIMITS[:max_lines]
......@@ -110,6 +111,7 @@ class Commit
@raw = raw_commit
@project = project
@statuses = {}
@gpg_commit = Gitlab::Gpg::Commit.new(self) if project
end
def id
......@@ -452,8 +454,4 @@ class Commit
def merged_merge_request_no_cache(user)
MergeRequestsFinder.new(user, project_id: project.id).find_by(merge_commit_sha: id) if merge_commit?
end
def gpg_commit
@gpg_commit ||= Gitlab::Gpg::Commit.new(self)
end
end
......@@ -141,7 +141,7 @@ class CommitStatus < ActiveRecord::Base
end
def group_name
name.to_s.gsub(%r{\d+[\s:/\\]+\d+\s*}, '').strip
name.to_s.gsub(%r{\d+[\.\s:/\\]+\d+\s*}, '').strip
end
def failed_but_allowed?
......
......@@ -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,
......
---
title: Allow installation of GitLab Runner with a single click
merge_request: 17134
author:
type: added
---
title: Allow CI/CD Jobs being grouped on version strings
merge_request:
author:
type: added
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
......@@ -677,6 +677,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
......@@ -2531,6 +2544,8 @@ ActiveRecord::Schema.define(version: 20180301084653) do
add_foreign_key "clusters", "users", on_delete: :nullify
add_foreign_key "clusters_applications_helm", "clusters", on_delete: :cascade
add_foreign_key "clusters_applications_ingress", "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
......
......@@ -23,7 +23,7 @@ requests from the API are logged to a separate file in `api_json.log`.
Each line contains a JSON line that can be ingested by Elasticsearch, Splunk, etc. For example:
```json
{"method":"GET","path":"/gitlab/gitlab-ce/issues/1234","format":"html","controller":"Projects::IssuesController","action":"show","status":200,"duration":229.03,"view":174.07,"db":13.24,"time":"2017-08-08T20:15:54.821Z","params":{"namespace_id":"gitlab","project_id":"gitlab-ce","id":"1234"},"remote_ip":"18.245.0.1","user_id":1,"username":"admin"}
{"method":"GET","path":"/gitlab/gitlab-ce/issues/1234","format":"html","controller":"Projects::IssuesController","action":"show","status":200,"duration":229.03,"view":174.07,"db":13.24,"time":"2017-08-08T20:15:54.821Z","params":[{"key":"param_key","value":"param_value"}],"remote_ip":"18.245.0.1","user_id":1,"username":"admin","gitaly_calls":76}
```
In this example, you can see this was a GET request for a specific issue. Notice each line also contains performance data:
......@@ -31,6 +31,7 @@ In this example, you can see this was a GET request for a specific issue. Notice
1. `duration`: the total time taken to retrieve the request
2. `view`: total time taken inside the Rails views
3. `db`: total time to retrieve data from the database
4. `gitaly_calls`: total number of calls made to Gitaly
User clone/fetch activity using http transport appears in this log as `action: git_upload_pack`.
......
......@@ -121,8 +121,9 @@ The basic requirements is that there are two numbers separated with one of
the following (you can even use them interchangeably):
- a space
- a backslash (`/`)
- a forward slash (`/`)
- a colon (`:`)
- a dot (`.`)
>**Note:**
More specifically, [it uses][regexp] this regular expression: `\d+[\s:\/\\]+\d+\s*`.
......
......@@ -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
......
......@@ -250,6 +250,45 @@ module Gitlab
end
end
def extract_signature_lazily(repository, commit_id)
BatchLoader.for({ repository: repository, commit_id: commit_id }).batch do |items, loader|
items_by_repo = items.group_by { |i| i[:repository] }
items_by_repo.each do |repo, items|
commit_ids = items.map { |i| i[:commit_id] }
signatures = batch_signature_extraction(repository, commit_ids)
signatures.each do |commit_sha, signature_data|
loader.call({ repository: repository, commit_id: commit_sha }, signature_data)
end
end
end
end
def batch_signature_extraction(repository, commit_ids)
repository.gitaly_migrate(:extract_commit_signature_in_batch) do |is_enabled|
if is_enabled
gitaly_batch_signature_extraction(repository, commit_ids)
else
rugged_batch_signature_extraction(repository, commit_ids)
end
end
end
def gitaly_batch_signature_extraction(repository, commit_ids)
repository.gitaly_commit_client.get_commit_signatures(commit_ids)
end
def rugged_batch_signature_extraction(repository, commit_ids)
commit_ids.each_with_object({}) do |commit_id, signatures|
signature_data = rugged_extract_signature(repository, commit_id)
next unless signature_data
signatures[commit_id] = signature_data
end
end
def rugged_extract_signature(repository, commit_id)
begin
Rugged::Commit.extract_signature(repository.rugged, commit_id)
......
......@@ -319,6 +319,23 @@ module Gitlab
[signature, signed_text]
end
def get_commit_signatures(commit_ids)
request = Gitaly::GetCommitSignaturesRequest.new(repository: @gitaly_repo, commit_ids: commit_ids)
response = GitalyClient.call(@repository.storage, :commit_service, :get_commit_signatures, request)
signatures = Hash.new { |h, k| h[k] = [''.b, ''.b] }
current_commit_id = nil
response.each do |message|
current_commit_id = message.commit_id if message.commit_id.present?
signatures[current_commit_id].first << message.signature
signatures[current_commit_id].last << message.signed_text
end
signatures
end
private
def call_commit_diff(request_params, options = {})
......
module Gitlab
module Gpg
class Commit
include Gitlab::Utils::StrongMemoize
def initialize(commit)
@commit = commit
repo = commit.project.repository.raw_repository
@signature_text, @signed_text = Gitlab::Git::Commit.extract_signature(repo, commit.sha)
@signature_data = Gitlab::Git::Commit.extract_signature_lazily(repo, commit.sha || commit.id)
end
def signature_text
strong_memoize(:signature_text) do
@signature_data&.itself && @signature_data[0]
end
end
def signed_text
strong_memoize(:signed_text) do
@signature_data&.itself && @signature_data[1]
end
end
def has_signature?
!!(@signature_text && @signed_text)
!!(signature_text && signed_text)
end
def signature
......@@ -53,7 +67,7 @@ module Gitlab
end
def verified_signature
@verified_signature ||= GPGME::Crypto.new.verify(@signature_text, signed_text: @signed_text) do |verified_signature|
@verified_signature ||= GPGME::Crypto.new.verify(signature_text, signed_text: signed_text) do |verified_signature|
break verified_signature
end
end
......
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
......
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
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
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
......
......@@ -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
......
......@@ -8,8 +8,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gitlab 1.0.0\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2018-03-01 22:35+0100\n"
"PO-Revision-Date: 2018-03-01 22:35+0100\n"
"POT-Creation-Date: 2018-03-02 13:39+0100\n"
"PO-Revision-Date: 2018-03-02 13:39+0100\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
......@@ -821,6 +821,9 @@ msgstr ""
msgid "ClusterIntegration|Copy CA Certificate"
msgstr ""
msgid "ClusterIntegration|Copy Ingress IP Address to clipboard"
msgstr ""
msgid "ClusterIntegration|Copy Kubernetes cluster name"
msgstr ""
......@@ -869,6 +872,9 @@ msgstr ""
msgid "ClusterIntegration|Ingress"
msgstr ""
msgid "ClusterIntegration|Ingress IP Address"
msgstr ""
msgid "ClusterIntegration|Install"
msgstr ""
......@@ -2221,6 +2227,9 @@ msgstr ""
msgid "Monitoring"
msgstr ""
msgid "More information"
msgstr ""
msgid "More information is available|here"
msgstr ""
......@@ -3005,6 +3014,9 @@ msgstr ""
msgid "Selective synchronization"
msgstr ""
msgid "Send email"
msgstr ""
msgid "Sep"
msgstr ""
......
......@@ -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', () => {
......
......@@ -393,81 +393,111 @@ describe Gitlab::Git::Commit, seed_helper: true do
end
end
describe '.extract_signature' do
subject { described_class.extract_signature(repository, commit_id) }
shared_examples '.extract_signature' do
context 'when the commit is signed' do
let(:commit_id) { '0b4bc9a49b562e85de7cc9e834518ea6828729b9' }
it 'returns signature and signed text' do
signature, signed_text = subject
expected_signature = <<~SIGNATURE
-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.22 (Darwin)
Comment: GPGTools - https://gpgtools.org
shared_examples 'extracting commit signature' do
context 'when the commit is signed' do
let(:commit_id) { '0b4bc9a49b562e85de7cc9e834518ea6828729b9' }
it 'returns signature and signed text' do
signature, signed_text = subject
expected_signature = <<~SIGNATURE
-----BEGIN PGP SIGNATURE-----
Version: GnuPG/MacGPG2 v2.0.22 (Darwin)
Comment: GPGTools - https://gpgtools.org
iQEcBAABCgAGBQJTDvaZAAoJEGJ8X1ifRn8XfvYIAMuB0yrbTGo1BnOSoDfyrjb0
Kw2EyUzvXYL72B63HMdJ+/0tlSDC6zONF3fc+bBD8z+WjQMTbwFNMRbSSy2rKEh+
mdRybOP3xBIMGgEph0/kmWln39nmFQBsPRbZBWoU10VfI/ieJdEOgOphszgryRar
TyS73dLBGE9y9NIININVaNISet9D9QeXFqc761CGjh4YIghvPpi+YihMWapGka6v
hgKhX+hc5rj+7IEE0CXmlbYR8OYvAbAArc5vJD7UTxAY4Z7/l9d6Ydt9GQ25khfy
ANFgltYzlR6evLFmDjssiP/mx/ZMN91AL0ueJ9nNGv411Mu2CUW+tDCaQf35mdc=
=j51i
-----END PGP SIGNATURE-----
SIGNATURE
expect(signature).to eq(expected_signature.chomp)
expect(signature).to be_a_binary_string
expected_signed_text = <<~SIGNED_TEXT
tree 22bfa2fbd217df24731f43ff43a4a0f8db759dae
parent ae73cb07c9eeaf35924a10f713b364d32b2dd34f
author Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> 1393489561 +0200
committer Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> 1393489561 +0200
Feature added
Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
SIGNED_TEXT
expect(signed_text).to eq(expected_signed_text)
expect(signed_text).to be_a_binary_string
end
end
iQEcBAABCgAGBQJTDvaZAAoJEGJ8X1ifRn8XfvYIAMuB0yrbTGo1BnOSoDfyrjb0
Kw2EyUzvXYL72B63HMdJ+/0tlSDC6zONF3fc+bBD8z+WjQMTbwFNMRbSSy2rKEh+
mdRybOP3xBIMGgEph0/kmWln39nmFQBsPRbZBWoU10VfI/ieJdEOgOphszgryRar
TyS73dLBGE9y9NIININVaNISet9D9QeXFqc761CGjh4YIghvPpi+YihMWapGka6v
hgKhX+hc5rj+7IEE0CXmlbYR8OYvAbAArc5vJD7UTxAY4Z7/l9d6Ydt9GQ25khfy
ANFgltYzlR6evLFmDjssiP/mx/ZMN91AL0ueJ9nNGv411Mu2CUW+tDCaQf35mdc=
=j51i
-----END PGP SIGNATURE-----
SIGNATURE
context 'when the commit has no signature' do
let(:commit_id) { '4b4918a572fa86f9771e5ba40fbd48e1eb03e2c6' }
expect(signature).to eq(expected_signature.chomp)
expect(signature).to be_a_binary_string
it 'returns nil' do
expect(subject).to be_nil
end
end
expected_signed_text = <<~SIGNED_TEXT
tree 22bfa2fbd217df24731f43ff43a4a0f8db759dae
parent ae73cb07c9eeaf35924a10f713b364d32b2dd34f
author Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> 1393489561 +0200
committer Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com> 1393489561 +0200
context 'when the commit cannot be found' do
let(:commit_id) { Gitlab::Git::BLANK_SHA }
Feature added
it 'returns nil' do
expect(subject).to be_nil
end
end
Signed-off-by: Dmitriy Zaporozhets <dmitriy.zaporozhets@gmail.com>
SIGNED_TEXT
context 'when the commit ID is invalid' do
let(:commit_id) { '4b4918a572fa86f9771e5ba40fbd48e' }
expect(signed_text).to eq(expected_signed_text)
expect(signed_text).to be_a_binary_string
end
it 'raises ArgumentError' do
expect { subject }.to raise_error(ArgumentError)
end
end
end
context 'when the commit has no signature' do
let(:commit_id) { '4b4918a572fa86f9771e5ba40fbd48e1eb03e2c6' }
it 'returns nil' do
expect(subject).to be_nil
describe '.extract_signature_lazily' do
shared_examples 'loading signatures in batch once' do
it 'fetches signatures in batch once' do
commit_ids = %w[0b4bc9a49b562e85de7cc9e834518ea6828729b9 4b4918a572fa86f9771e5ba40fbd48e1eb03e2c6]
signatures = commit_ids.map do |commit_id|
described_class.extract_signature_lazily(repository, commit_id)
end
end
context 'when the commit cannot be found' do
let(:commit_id) { Gitlab::Git::BLANK_SHA }
expect(described_class).to receive(:batch_signature_extraction)
.with(repository, commit_ids)
.once
.and_return({})
it 'returns nil' do
expect(subject).to be_nil
end
2.times { signatures.each(&:itself) }
end
end
context 'when the commit ID is invalid' do
let(:commit_id) { '4b4918a572fa86f9771e5ba40fbd48e' }
subject { described_class.extract_signature_lazily(repository, commit_id).itself }
it 'raises ArgumentError' do
expect { subject }.to raise_error(ArgumentError)
end
end
context 'with Gitaly extract_commit_signature_in_batch feature enabled' do
it_behaves_like 'extracting commit signature'
it_behaves_like 'loading signatures in batch once'
end
context 'with Gitaly extract_commit_signature_in_batch feature disabled', :disable_gitaly do
it_behaves_like 'extracting commit signature'
it_behaves_like 'loading signatures in batch once'
end
end
describe '.extract_signature' do
subject { described_class.extract_signature(repository, commit_id) }
context 'with gitaly' do
it_behaves_like '.extract_signature'
it_behaves_like 'extracting commit signature'
end
context 'without gitaly', :skip_gitaly_mock do
it_behaves_like '.extract_signature'
context 'without gitaly', :disable_gitaly do
it_behaves_like 'extracting commit signature'
end
end
end
......
......@@ -38,7 +38,7 @@ describe Gitlab::Gpg::Commit do
end
before do
allow(Gitlab::Git::Commit).to receive(:extract_signature)
allow(Gitlab::Git::Commit).to receive(:extract_signature_lazily)
.with(Gitlab::Git::Repository, commit_sha)
.and_return(
[
......@@ -101,7 +101,7 @@ describe Gitlab::Gpg::Commit do
end
before do
allow(Gitlab::Git::Commit).to receive(:extract_signature)
allow(Gitlab::Git::Commit).to receive(:extract_signature_lazily)
.with(Gitlab::Git::Repository, commit_sha)
.and_return(
[
......@@ -140,7 +140,7 @@ describe Gitlab::Gpg::Commit do
end
before do
allow(Gitlab::Git::Commit).to receive(:extract_signature)
allow(Gitlab::Git::Commit).to receive(:extract_signature_lazily)
.with(Gitlab::Git::Repository, commit_sha)
.and_return(
[
......@@ -175,7 +175,7 @@ describe Gitlab::Gpg::Commit do
end
before do
allow(Gitlab::Git::Commit).to receive(:extract_signature)
allow(Gitlab::Git::Commit).to receive(:extract_signature_lazily)
.with(Gitlab::Git::Repository, commit_sha)
.and_return(
[
......@@ -211,7 +211,7 @@ describe Gitlab::Gpg::Commit do
end
before do
allow(Gitlab::Git::Commit).to receive(:extract_signature)
allow(Gitlab::Git::Commit).to receive(:extract_signature_lazily)
.with(Gitlab::Git::Repository, commit_sha)
.and_return(
[
......@@ -241,7 +241,7 @@ describe Gitlab::Gpg::Commit do
let!(:commit) { create :commit, project: project, sha: commit_sha }
before do
allow(Gitlab::Git::Commit).to receive(:extract_signature)
allow(Gitlab::Git::Commit).to receive(:extract_signature_lazily)
.with(Gitlab::Git::Repository, commit_sha)
.and_return(
[
......
......@@ -26,7 +26,7 @@ RSpec.describe Gitlab::Gpg::InvalidGpgSignatureUpdater do
before do
allow_any_instance_of(Project).to receive(:commit).and_return(commit)
allow(Gitlab::Git::Commit).to receive(:extract_signature)
allow(Gitlab::Git::Commit).to receive(:extract_signature_lazily)
.with(Gitlab::Git::Repository, commit_sha)
.and_return(signature)
end
......
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
......
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
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
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
......@@ -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'
......
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
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
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
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, projects: [project]) }
let(:gitlab_runner) { create(:clusters_applications_runner, cluster: cluster) }
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) }
......@@ -224,9 +225,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
......
......@@ -368,7 +368,9 @@ describe CommitStatus do
'rspec:windows 0 : / 1' => 'rspec:windows',
'rspec:windows 0 : / 1 name' => 'rspec:windows name',
'0 1 name ruby' => 'name ruby',
'0 :/ 1 name ruby' => 'name ruby'
'0 :/ 1 name ruby' => 'name ruby',
'golang test 1.8' => 'golang test',
'1.9 golang test' => 'golang test'
}
tests.each do |name, group_name|
......
......@@ -15,8 +15,8 @@ describe MergeRequests::BuildService do
let(:target_branch) { 'master' }
let(:merge_request) { service.execute }
let(:compare) { double(:compare, commits: commits) }
let(:commit_1) { double(:commit_1, safe_message: "Initial commit\n\nCreate the app") }
let(:commit_2) { double(:commit_2, safe_message: 'This is a bad commit message!') }
let(:commit_1) { double(:commit_1, sha: 'f00ba7', safe_message: "Initial commit\n\nCreate the app") }
let(:commit_2) { double(:commit_2, sha: 'f00ba7', safe_message: 'This is a bad commit message!') }
let(:commits) { nil }
let(:service) do
......
shared_examples 'cluster application specs' do
let(:factory_name) { described_class.to_s.downcase.gsub("::", "_") }
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
......@@ -11,45 +12,9 @@ shared_examples 'cluster application specs' do
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) }
subject { create(application_name, :scheduled) }
it 'is installing' do
subject.make_installing!
......@@ -59,7 +24,7 @@ shared_examples 'cluster application specs' do
end
describe '#make_installed' do
subject { create(factory_name, :installing) }
subject { create(application_name, :installing) }
it 'is installed' do
subject.make_installed
......@@ -69,7 +34,7 @@ shared_examples 'cluster application specs' do
end
describe '#make_errored' do
subject { create(factory_name, :installing) }
subject { create(application_name, :installing) }
let(:reason) { 'some errors' }
it 'is errored' do
......@@ -81,7 +46,7 @@ shared_examples 'cluster application specs' do
end
describe '#make_scheduled' do
subject { create(factory_name, :installable) }
subject { create(application_name, :installable) }
it 'is scheduled' do
subject.make_scheduled
......@@ -90,7 +55,7 @@ shared_examples 'cluster application specs' do
end
describe 'when was errored' do
subject { create(factory_name, :errored) }
subject { create(application_name, :errored) }
it 'clears #status_reason' do
expect(subject.status_reason).not_to be_nil
......
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
## 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: {}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment