Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-11-05 09:09:00 +00:00
parent d10e04a10b
commit 015890a1b7
97 changed files with 1694 additions and 895 deletions

View File

@ -1,28 +1,19 @@
<script>
/* eslint-disable vue/no-v-html */
import { GlButton, GlIcon } from '@gitlab/ui';
import { __, sprintf } from '~/locale';
import { GlButton, GlIcon, GlSprintf } from '@gitlab/ui';
import { s__ } from '~/locale';
import notesEventHub from '../event_hub';
export default {
i18n: {
information: s__(
"Notes|You're only seeing %{boldStart}other activity%{boldEnd} in the feed. To add a comment, switch to one of the following options.",
),
},
components: {
GlButton,
GlIcon,
},
computed: {
timelineContent() {
return sprintf(
__(
"You're only seeing %{startTag}other activity%{endTag} in the feed. To add a comment, switch to one of the following options.",
),
{
startTag: `<b>`,
endTag: `</b>`,
},
false,
);
},
GlSprintf,
},
methods: {
selectFilter(value) {
@ -41,12 +32,18 @@ export default {
<gl-icon name="comment" />
</div>
<div class="timeline-content">
<div ref="timelineContent" v-html="timelineContent"></div>
<div data-testid="discussion-filter-timeline-content">
<gl-sprintf :message="$options.i18n.information">
<template #bold="{ content }">
<b>{{ content }}</b>
</template>
</gl-sprintf>
</div>
<div class="discussion-filter-actions mt-2">
<gl-button ref="showAllActivity" variant="default" @click="selectFilter(0)">
<gl-button variant="default" @click="selectFilter(0)">
{{ __('Show all activity') }}
</gl-button>
<gl-button ref="showComments" variant="default" @click="selectFilter(1)">
<gl-button variant="default" @click="selectFilter(1)">
{{ __('Show comments only') }}
</gl-button>
</div>

View File

@ -25,12 +25,5 @@ module Types
description: 'HTTP URL of the issues page, filtered by this release and `state=open`'
field :closed_issues_url, GraphQL::STRING_TYPE, null: true,
description: 'HTTP URL of the issues page, filtered by this release and `state=closed`'
field :merge_requests_url, GraphQL::STRING_TYPE, null: true, method: :opened_merge_requests_url,
description: 'HTTP URL of the merge request page filtered by this release',
deprecated: { reason: 'Use `openedMergeRequestsUrl`', milestone: '13.6' }
field :issues_url, GraphQL::STRING_TYPE, null: true, method: :opened_issues_url,
description: 'HTTP URL of the issues page filtered by this release',
deprecated: { reason: 'Use `openedIssuesUrl`', milestone: '13.6' }
end
end

View File

@ -30,7 +30,7 @@ module Clusters
end
def install_command
Gitlab::Kubernetes::Helm::InstallCommand.new(
helm_command_module::InstallCommand.new(
name: 'certmanager',
repository: repository,
version: VERSION,
@ -43,7 +43,7 @@ module Clusters
end
def uninstall_command
Gitlab::Kubernetes::Helm::DeleteCommand.new(
helm_command_module::DeleteCommand.new(
name: 'certmanager',
rbac: cluster.platform_kubernetes_rbac?,
files: files,

View File

@ -29,7 +29,7 @@ module Clusters
end
def install_command
Gitlab::Kubernetes::Helm::InstallCommand.new(
helm_command_module::InstallCommand.new(
name: 'crossplane',
repository: repository,
version: VERSION,

View File

@ -26,7 +26,7 @@ module Clusters
end
def install_command
Gitlab::Kubernetes::Helm::InstallCommand.new(
helm_command_module::InstallCommand.new(
name: 'elastic-stack',
version: VERSION,
rbac: cluster.platform_kubernetes_rbac?,
@ -39,7 +39,7 @@ module Clusters
end
def uninstall_command
Gitlab::Kubernetes::Helm::DeleteCommand.new(
helm_command_module::DeleteCommand.new(
name: 'elastic-stack',
rbac: cluster.platform_kubernetes_rbac?,
files: files,
@ -96,7 +96,7 @@ module Clusters
def post_install_script
[
"timeout -t60 sh /data/helm/elastic-stack/config/wait-for-elasticsearch.sh http://elastic-stack-elasticsearch-master:9200"
"timeout 60 sh /data/helm/elastic-stack/config/wait-for-elasticsearch.sh http://elastic-stack-elasticsearch-master:9200"
]
end
@ -116,7 +116,7 @@ module Clusters
# Chart version 3.0.0 moves to our own chart at https://gitlab.com/gitlab-org/charts/elastic-stack
# and is not compatible with pre-existing resources. We first remove them.
[
Gitlab::Kubernetes::Helm::DeleteCommand.new(
helm_command_module::DeleteCommand.new(
name: 'elastic-stack',
rbac: cluster.platform_kubernetes_rbac?,
files: files

View File

@ -30,7 +30,7 @@ module Clusters
end
def install_command
Gitlab::Kubernetes::Helm::InstallCommand.new(
helm_command_module::InstallCommand.new(
name: 'fluentd',
repository: repository,
version: VERSION,

View File

@ -4,6 +4,8 @@ require 'openssl'
module Clusters
module Applications
# DEPRECATED: This model represents the Helm 2 Tiller server, and is no longer being actively used.
# It is being kept around for a potential cleanup of the unused Tiller server.
class Helm < ApplicationRecord
self.table_name = 'clusters_applications_helm'
@ -49,7 +51,7 @@ module Clusters
end
def install_command
Gitlab::Kubernetes::Helm::InitCommand.new(
Gitlab::Kubernetes::Helm::V2::InitCommand.new(
name: name,
files: files,
rbac: cluster.platform_kubernetes_rbac?
@ -57,7 +59,7 @@ module Clusters
end
def uninstall_command
Gitlab::Kubernetes::Helm::ResetCommand.new(
Gitlab::Kubernetes::Helm::V2::ResetCommand.new(
name: name,
files: files,
rbac: cluster.platform_kubernetes_rbac?
@ -86,19 +88,19 @@ module Clusters
end
def create_keys_and_certs
ca_cert = Gitlab::Kubernetes::Helm::Certificate.generate_root
ca_cert = Gitlab::Kubernetes::Helm::V2::Certificate.generate_root
self.ca_key = ca_cert.key_string
self.ca_cert = ca_cert.cert_string
end
def tiller_cert
@tiller_cert ||= ca_cert_obj.issue(expires_in: Gitlab::Kubernetes::Helm::Certificate::INFINITE_EXPIRY)
@tiller_cert ||= ca_cert_obj.issue(expires_in: Gitlab::Kubernetes::Helm::V2::Certificate::INFINITE_EXPIRY)
end
def ca_cert_obj
return unless has_ssl?
Gitlab::Kubernetes::Helm::Certificate
Gitlab::Kubernetes::Helm::V2::Certificate
.from_strings(ca_key, ca_cert)
end
end

View File

@ -62,7 +62,7 @@ module Clusters
end
def install_command
Gitlab::Kubernetes::Helm::InstallCommand.new(
helm_command_module::InstallCommand.new(
name: name,
repository: repository,
version: VERSION,

View File

@ -39,7 +39,7 @@ module Clusters
end
def install_command
Gitlab::Kubernetes::Helm::InstallCommand.new(
helm_command_module::InstallCommand.new(
name: name,
version: VERSION,
rbac: cluster.platform_kubernetes_rbac?,

View File

@ -70,7 +70,7 @@ module Clusters
end
def install_command
Gitlab::Kubernetes::Helm::InstallCommand.new(
helm_command_module::InstallCommand.new(
name: name,
version: VERSION,
rbac: cluster.platform_kubernetes_rbac?,
@ -94,7 +94,7 @@ module Clusters
end
def uninstall_command
Gitlab::Kubernetes::Helm::DeleteCommand.new(
helm_command_module::DeleteCommand.new(
name: name,
rbac: cluster.platform_kubernetes_rbac?,
files: files,

View File

@ -67,7 +67,7 @@ module Clusters
end
def install_command
Gitlab::Kubernetes::Helm::InstallCommand.new(
helm_command_module::InstallCommand.new(
name: name,
repository: repository,
version: VERSION,
@ -79,7 +79,7 @@ module Clusters
end
def patch_command(values)
::Gitlab::Kubernetes::Helm::PatchCommand.new(
helm_command_module::PatchCommand.new(
name: name,
repository: repository,
version: version,
@ -90,7 +90,7 @@ module Clusters
end
def uninstall_command
Gitlab::Kubernetes::Helm::DeleteCommand.new(
helm_command_module::DeleteCommand.new(
name: name,
rbac: cluster.platform_kubernetes_rbac?,
files: files,

View File

@ -30,7 +30,7 @@ module Clusters
end
def install_command
Gitlab::Kubernetes::Helm::InstallCommand.new(
helm_command_module::InstallCommand.new(
name: name,
version: VERSION,
rbac: cluster.platform_kubernetes_rbac?,

View File

@ -79,6 +79,9 @@ module Clusters
validates :cluster_type, presence: true
validates :domain, allow_blank: true, hostname: { allow_numeric_hostname: true }
validates :namespace_per_environment, inclusion: { in: [true, false] }
validates :helm_major_version, inclusion: { in: [2, 3] }
default_value_for :helm_major_version, 3
validate :restrict_modification, on: :update
validate :no_groups, unless: :group_type?

View File

@ -12,6 +12,17 @@ module Clusters
after_initialize :set_initial_status
def helm_command_module
case cluster.helm_major_version
when 3
Gitlab::Kubernetes::Helm::V3
when 2
Gitlab::Kubernetes::Helm::V2
else
raise "Invalid Helm major version"
end
end
def set_initial_status
return unless not_installable?

View File

@ -4,7 +4,7 @@ module Clusters
module Concerns
module ApplicationData
def uninstall_command
Gitlab::Kubernetes::Helm::DeleteCommand.new(
helm_command_module::DeleteCommand.new(
name: name,
rbac: cluster.platform_kubernetes_rbac?,
files: files

View File

@ -286,7 +286,7 @@ class PagesDomain < ApplicationRecord
return unless domain
if domain.downcase.ends_with?(Settings.pages.host.downcase)
self.errors.add(:domain, "*.#{Settings.pages.host} is restricted")
self.errors.add(:domain, "*.#{Settings.pages.host} is restricted. Please compare our documentation at https://docs.gitlab.com/ee/administration/pages/#advanced-configuration against your configuration.")
end
end

View File

@ -0,0 +1,5 @@
---
title: Replace v-html with GlSprintf in notes/.../discussion_filter_note.vue
merge_request: 41482
author: Takuya Noguchi
type: other

View File

@ -0,0 +1,5 @@
---
title: Use Helm 3 by default for GitLab-managed apps in new clusters
merge_request: 46267
author:
type: changed

View File

@ -14,7 +14,6 @@ if Gitlab.ee? && Gitlab.dev_or_test_env?
# being unique to licensed names. These feature flags should be reworked to
# be "development" with explicit check
IGNORED_FEATURE_FLAGS = %i[
feature_flags_related_issues
group_wikis
swimlanes
minimal_access_role

View File

@ -0,0 +1,12 @@
# frozen_string_literal: true
# See https://docs.gitlab.com/ee/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddHelmMajorVersionToClusters < ActiveRecord::Migration[6.0]
DOWNTIME = false
def change
add_column(:clusters, :helm_major_version, :integer, default: 2, null: false)
end
end

View File

@ -0,0 +1 @@
5520cca016af07fb2e009c0e3254362f106a9cc808cbb61e280221be82be1b25

View File

@ -10967,7 +10967,8 @@ CREATE TABLE clusters (
namespace_per_environment boolean DEFAULT true NOT NULL,
management_project_id integer,
cleanup_status smallint DEFAULT 1 NOT NULL,
cleanup_status_reason text
cleanup_status_reason text,
helm_major_version integer DEFAULT 2 NOT NULL
);
CREATE TABLE clusters_applications_cert_managers (

View File

@ -17419,16 +17419,6 @@ type ReleaseLinks {
"""
editUrl: String
"""
HTTP URL of the issues page filtered by this release. Deprecated in 13.6: Use `openedIssuesUrl`
"""
issuesUrl: String @deprecated(reason: "Use `openedIssuesUrl`. Deprecated in 13.6")
"""
HTTP URL of the merge request page filtered by this release. Deprecated in 13.6: Use `openedMergeRequestsUrl`
"""
mergeRequestsUrl: String @deprecated(reason: "Use `openedMergeRequestsUrl`. Deprecated in 13.6")
"""
HTTP URL of the merge request page , filtered by this release and `state=merged`
"""

View File

@ -50230,34 +50230,6 @@
"isDeprecated": false,
"deprecationReason": null
},
{
"name": "issuesUrl",
"description": "HTTP URL of the issues page filtered by this release. Deprecated in 13.6: Use `openedIssuesUrl`",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": true,
"deprecationReason": "Use `openedIssuesUrl`. Deprecated in 13.6"
},
{
"name": "mergeRequestsUrl",
"description": "HTTP URL of the merge request page filtered by this release. Deprecated in 13.6: Use `openedMergeRequestsUrl`",
"args": [
],
"type": {
"kind": "SCALAR",
"name": "String",
"ofType": null
},
"isDeprecated": true,
"deprecationReason": "Use `openedMergeRequestsUrl`. Deprecated in 13.6"
},
{
"name": "mergedMergeRequestsUrl",
"description": "HTTP URL of the merge request page , filtered by this release and `state=merged`",

View File

@ -2435,8 +2435,6 @@ Evidence for a release.
| `closedIssuesUrl` | String | HTTP URL of the issues page, filtered by this release and `state=closed` |
| `closedMergeRequestsUrl` | String | HTTP URL of the merge request page , filtered by this release and `state=closed` |
| `editUrl` | String | HTTP URL of the release's edit page |
| `issuesUrl` **{warning-solid}** | String | **Deprecated:** Use `openedIssuesUrl`. Deprecated in 13.6 |
| `mergeRequestsUrl` **{warning-solid}** | String | **Deprecated:** Use `openedMergeRequestsUrl`. Deprecated in 13.6 |
| `mergedMergeRequestsUrl` | String | HTTP URL of the merge request page , filtered by this release and `state=merged` |
| `openedIssuesUrl` | String | HTTP URL of the issues page, filtered by this release and `state=open` |
| `openedMergeRequestsUrl` | String | HTTP URL of the merge request page, filtered by this release and `state=open` |

View File

@ -30,8 +30,6 @@ module API
expose :evidences, using: Entities::Releases::Evidence, expose_nil: false, if: ->(_, _) { can_download_code? }
expose :_links do
expose :self_url, as: :self, expose_nil: false
expose :opened_merge_requests_url, as: :merge_requests_url, expose_nil: false
expose :opened_issues_url, as: :issues_url, expose_nil: false
expose :edit_url, expose_nil: false
end

View File

@ -18,7 +18,6 @@ module Gitlab
validates :config, allowed_keys: ALLOWED_KEYS + PROCESSABLE_ALLOWED_KEYS
with_options allow_nil: true do
validates :allow_failure, boolean: true
validates :when, inclusion: {
in: ALLOWED_WHEN,
message: "should be one of: #{ALLOWED_WHEN.join(', ')}"
@ -48,7 +47,7 @@ module Gitlab
inherit: false,
metadata: { allowed_needs: %i[job bridge] }
attributes :when, :allow_failure
attributes :when
def self.matching?(name, config)
!name.to_s.start_with?('.') &&
@ -60,14 +59,6 @@ module Gitlab
true
end
def manual_action?
self.when == 'manual'
end
def ignored?
allow_failure.nil? ? manual_action? : allow_failure
end
def value
super.merge(
trigger: (trigger_value if trigger_defined?),

View File

@ -24,7 +24,6 @@ module Gitlab
validates :script, presence: true
with_options allow_nil: true do
validates :allow_failure, boolean: true
validates :when, inclusion: {
in: ALLOWED_WHEN,
message: "should be one of: #{ALLOWED_WHEN.join(', ')}"
@ -118,7 +117,7 @@ module Gitlab
description: 'Parallel configuration for this job.',
inherit: false
attributes :script, :tags, :allow_failure, :when, :dependencies,
attributes :script, :tags, :when, :dependencies,
:needs, :retry, :parallel, :start_in,
:interruptible, :timeout, :resource_group, :release
@ -141,18 +140,10 @@ module Gitlab
end
end
def manual_action?
self.when == 'manual'
end
def delayed?
self.when == 'delayed'
end
def ignored?
allow_failure.nil? ? manual_action? : allow_failure
end
def value
super.merge(
before_script: before_script_value,

View File

@ -32,6 +32,7 @@ module Gitlab
with_options allow_nil: true do
validates :extends, array_of_strings_or_string: true
validates :rules, array_of_hashes: true
validates :allow_failure, boolean: true
end
end
@ -64,7 +65,7 @@ module Gitlab
inherit: false,
default: {}
attributes :extends, :rules
attributes :extends, :rules, :allow_failure
end
def compose!(deps = nil)
@ -136,6 +137,14 @@ module Gitlab
root_variables.merge(variables_value.to_h)
end
def manual_action?
self.when == 'manual'
end
def ignored?
allow_failure.nil? ? manual_action? : allow_failure
end
end
end
end

View File

@ -55,9 +55,17 @@ module Gitlab
end
def project_tree
@project_tree ||= Gitlab::ImportExport::Project::TreeRestorer.new(user: current_user,
shared: shared,
project: project)
@project_tree ||= project_tree_class.new(user: current_user,
shared: shared,
project: project)
end
def project_tree_class
sample_data_template? ? Gitlab::ImportExport::Project::Sample::TreeRestorer : Gitlab::ImportExport::Project::TreeRestorer
end
def sample_data_template?
project&.import_data&.data&.dig('sample_data')
end
def avatar_restorer

View File

@ -0,0 +1,42 @@
# frozen_string_literal: true
module Gitlab
module ImportExport
module Project
module Sample
class RelationFactory < Project::RelationFactory
DATE_MODELS = %i[issues milestones].freeze
def initialize(date_calculator:, **args)
super(**args)
@date_calculator = date_calculator
end
private
def setup_models
super
# Override due date attributes in data hash for Sample Data templates
# Dates are moved by taking the closest one to average and moving that (and rest around it) to the date of import
override_date_attributes
end
def override_date_attributes
return unless DATE_MODELS.include?(@relation_name)
@relation_hash['start_date'] = calculate_by_closest_date(@relation_hash['start_date']&.to_time)
@relation_hash['due_date'] = calculate_by_closest_date(@relation_hash['due_date']&.to_time)
end
def calculate_by_closest_date(date)
return unless date
@date_calculator.calculate_by_closest_date_to_average(date)
end
end
end
end
end
end

View File

@ -0,0 +1,33 @@
# frozen_string_literal: true
module Gitlab
module ImportExport
module Project
module Sample
class RelationTreeRestorer < ImportExport::RelationTreeRestorer
def initialize(*args)
super
@date_calculator = Gitlab::ImportExport::Project::Sample::DateCalculator.new(dates)
end
private
def relation_factory_params(*args)
super.merge(date_calculator: @date_calculator)
end
def dates
return [] if relation_reader.legacy?
RelationFactory::DATE_MODELS.flat_map do |tag|
relation_reader.consume_relation(@importable_path, tag, mark_as_consumed: false).map do |model|
model.first['due_date']
end
end
end
end
end
end
end
end

View File

@ -1,50 +0,0 @@
# frozen_string_literal: true
module Gitlab
module ImportExport
module Project
module Sample
class SampleDataRelationTreeRestorer < RelationTreeRestorer
DATE_MODELS = %i[issues milestones].freeze
def initialize(*args)
super
date_calculator
end
private
def build_relation(relation_key, relation_definition, data_hash)
# Override due date attributes in data hash for Sample Data templates
# Dates are moved by taking the closest one to average and moving that (and rest around it) to the date of import
# TODO: To move this logic to RelationFactory (see: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41699#note_430465333)
override_date_attributes!(relation_key, data_hash)
super
end
def override_date_attributes!(relation_key, data_hash)
return unless DATE_MODELS.include?(relation_key.to_sym)
data_hash['start_date'] = date_calculator.calculate_by_closest_date_to_average(data_hash['start_date'].to_time) unless data_hash['start_date'].nil?
data_hash['due_date'] = date_calculator.calculate_by_closest_date_to_average(data_hash['due_date'].to_time) unless data_hash['due_date'].nil?
end
def dates
return if relation_reader.legacy?
DATE_MODELS.flat_map do |tag|
relation_reader.consume_relation(@importable_path, tag, mark_as_consumed: false).map do |model|
model.first['due_date']
end
end
end
def date_calculator
@date_calculator ||= Gitlab::ImportExport::Project::Sample::DateCalculator.new(dates)
end
end
end
end
end
end

View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
module Gitlab
module ImportExport
module Project
module Sample
class TreeRestorer < Project::TreeRestorer
def relation_tree_restorer_class
RelationTreeRestorer
end
def relation_factory
RelationFactory
end
end
end
end
end
end

View File

@ -85,11 +85,7 @@ module Gitlab
end
def relation_tree_restorer_class
sample_data_template? ? Sample::SampleDataRelationTreeRestorer : RelationTreeRestorer
end
def sample_data_template?
@project&.import_data&.data&.dig('sample_data')
RelationTreeRestorer
end
def members_mapper

View File

@ -1,85 +0,0 @@
# frozen_string_literal: true
module Gitlab
module Kubernetes
module Helm
class BaseCommand
attr_reader :name, :files
def initialize(rbac:, name:, files:)
@rbac = rbac
@name = name
@files = files
end
def rbac?
@rbac
end
def pod_resource
pod_service_account_name = rbac? ? service_account_name : nil
Gitlab::Kubernetes::Helm::Pod.new(self, namespace, service_account_name: pod_service_account_name).generate
end
def generate_script
<<~HEREDOC
set -xeo pipefail
HEREDOC
end
def pod_name
"install-#{name}"
end
def config_map_resource
Gitlab::Kubernetes::ConfigMap.new(name, files).generate
end
def service_account_resource
return unless rbac?
Gitlab::Kubernetes::ServiceAccount.new(service_account_name, namespace).generate
end
def cluster_role_binding_resource
return unless rbac?
subjects = [{ kind: 'ServiceAccount', name: service_account_name, namespace: namespace }]
Gitlab::Kubernetes::ClusterRoleBinding.new(
cluster_role_binding_name,
cluster_role_name,
subjects
).generate
end
def file_names
files.keys
end
private
def files_dir
"/data/helm/#{name}/config"
end
def namespace
Gitlab::Kubernetes::Helm::NAMESPACE
end
def service_account_name
Gitlab::Kubernetes::Helm::SERVICE_ACCOUNT
end
def cluster_role_binding_name
Gitlab::Kubernetes::Helm::CLUSTER_ROLE_BINDING
end
def cluster_role_name
Gitlab::Kubernetes::Helm::CLUSTER_ROLE
end
end
end
end
end

View File

@ -1,73 +0,0 @@
# frozen_string_literal: true
module Gitlab
module Kubernetes
module Helm
class Certificate
INFINITE_EXPIRY = 1000.years
SHORT_EXPIRY = 30.minutes
attr_reader :key, :cert
def key_string
@key.to_s
end
def cert_string
@cert.to_pem
end
def self.from_strings(key_string, cert_string)
key = OpenSSL::PKey::RSA.new(key_string)
cert = OpenSSL::X509::Certificate.new(cert_string)
new(key, cert)
end
def self.generate_root
_issue(signed_by: nil, expires_in: INFINITE_EXPIRY, certificate_authority: true)
end
def issue(expires_in: SHORT_EXPIRY)
self.class._issue(signed_by: self, expires_in: expires_in, certificate_authority: false)
end
private
def self._issue(signed_by:, expires_in:, certificate_authority:)
key = OpenSSL::PKey::RSA.new(4096)
public_key = key.public_key
subject = OpenSSL::X509::Name.parse("/C=US")
cert = OpenSSL::X509::Certificate.new
cert.subject = subject
cert.issuer = signed_by&.cert&.subject || subject
cert.not_before = Time.now
cert.not_after = expires_in.from_now
cert.public_key = public_key
cert.serial = 0x0
cert.version = 2
if certificate_authority
extension_factory = OpenSSL::X509::ExtensionFactory.new
extension_factory.subject_certificate = cert
extension_factory.issuer_certificate = cert
cert.add_extension(extension_factory.create_extension('subjectKeyIdentifier', 'hash'))
cert.add_extension(extension_factory.create_extension('basicConstraints', 'CA:TRUE', true))
cert.add_extension(extension_factory.create_extension('keyUsage', 'cRLSign,keyCertSign', true))
end
cert.sign(signed_by&.key || key, OpenSSL::Digest::SHA256.new)
new(key, cert)
end
def initialize(key, cert)
@key = key
@cert = cert
end
end
end
end
end

View File

@ -1,38 +0,0 @@
# frozen_string_literal: true
module Gitlab
module Kubernetes
module Helm
module ClientCommand
def init_command
<<~SHELL.chomp
export HELM_HOST="localhost:44134"
tiller -listen ${HELM_HOST} -alsologtostderr &
helm init --client-only
SHELL
end
def repository_command
['helm', 'repo', 'add', name, repository].shelljoin if repository
end
private
def repository_update_command
'helm repo update'
end
def optional_tls_flags
return [] unless files.key?(:'ca.pem')
[
'--tls',
'--tls-ca-cert', "#{files_dir}/ca.pem",
'--tls-cert', "#{files_dir}/cert.pem",
'--tls-key', "#{files_dir}/key.pem"
]
end
end
end
end
end

View File

@ -1,36 +0,0 @@
# frozen_string_literal: true
module Gitlab
module Kubernetes
module Helm
class DeleteCommand < BaseCommand
include ClientCommand
attr_reader :predelete, :postdelete
def initialize(predelete: nil, postdelete: nil, **args)
super(**args)
@predelete = predelete
@postdelete = postdelete
end
def generate_script
super + [
init_command,
predelete,
delete_command,
postdelete
].compact.join("\n")
end
def pod_name
"uninstall-#{name}"
end
def delete_command
['helm', 'delete', '--purge', name].shelljoin
end
end
end
end
end

View File

@ -1,43 +0,0 @@
# frozen_string_literal: true
module Gitlab
module Kubernetes
module Helm
class InitCommand < BaseCommand
def generate_script
super + [
init_helm_command
].join("\n")
end
private
def init_helm_command
command = %w[helm init] + init_command_flags
command.shelljoin
end
def init_command_flags
tls_flags + optional_service_account_flag
end
def tls_flags
[
'--tiller-tls',
'--tiller-tls-verify',
'--tls-ca-cert', "#{files_dir}/ca.pem",
'--tiller-tls-cert', "#{files_dir}/cert.pem",
'--tiller-tls-key', "#{files_dir}/key.pem"
]
end
def optional_service_account_flag
return [] unless rbac?
['--service-account', service_account_name]
end
end
end
end
end

View File

@ -1,85 +0,0 @@
# frozen_string_literal: true
module Gitlab
module Kubernetes
module Helm
class InstallCommand < BaseCommand
include ClientCommand
attr_reader :chart, :repository, :preinstall, :postinstall
attr_accessor :version
def initialize(chart:, version: nil, repository: nil, preinstall: nil, postinstall: nil, **args)
super(**args)
@chart = chart
@version = version
@repository = repository
@preinstall = preinstall
@postinstall = postinstall
end
def generate_script
super + [
init_command,
repository_command,
repository_update_command,
preinstall,
install_command,
postinstall
].compact.join("\n")
end
private
# Uses `helm upgrade --install` which means we can use this for both
# installation and uprade of applications
def install_command
command = ['helm', 'upgrade', name, chart] +
install_flag +
rollback_support_flag +
reset_values_flag +
optional_version_flag +
rbac_create_flag +
namespace_flag +
value_flag
command.shelljoin
end
def install_flag
['--install']
end
def reset_values_flag
['--reset-values']
end
def value_flag
['-f', "/data/helm/#{name}/config/values.yaml"]
end
def namespace_flag
['--namespace', Gitlab::Kubernetes::Helm::NAMESPACE]
end
def rbac_create_flag
if rbac?
%w[--set rbac.create=true,rbac.enabled=true]
else
%w[--set rbac.create=false,rbac.enabled=false]
end
end
def optional_version_flag
return [] unless version
['--version', version]
end
def rollback_support_flag
['--atomic', '--cleanup-on-fail']
end
end
end
end
end

View File

@ -1,65 +0,0 @@
# frozen_string_literal: true
# PatchCommand is for updating values in installed charts without overwriting
# existing values.
module Gitlab
module Kubernetes
module Helm
class PatchCommand < BaseCommand
include ClientCommand
attr_reader :chart, :repository
attr_accessor :version
def initialize(chart:, version:, repository: nil, **args)
super(**args)
# version is mandatory to prevent chart mismatches
# we do not want our values interpreted in the context of the wrong version
raise ArgumentError, 'version is required' if version.blank?
@chart = chart
@version = version
@repository = repository
end
def generate_script
super + [
init_command,
repository_command,
repository_update_command,
upgrade_command
].compact.join("\n")
end
private
def upgrade_command
command = ['helm', 'upgrade', name, chart] +
reuse_values_flag +
version_flag +
namespace_flag +
value_flag
command.shelljoin
end
def reuse_values_flag
['--reuse-values']
end
def value_flag
['-f', "/data/helm/#{name}/config/values.yaml"]
end
def namespace_flag
['--namespace', Gitlab::Kubernetes::Helm::NAMESPACE]
end
def version_flag
['--version', version]
end
end
end
end
end

View File

@ -27,7 +27,7 @@ module Gitlab
def container_specification
{
name: 'helm',
image: "registry.gitlab.com/gitlab-org/cluster-integration/helm-install-image/releases/#{Gitlab::Kubernetes::Helm::HELM_VERSION}-kube-#{Gitlab::Kubernetes::Helm::KUBECTL_VERSION}",
image: "registry.gitlab.com/gitlab-org/cluster-integration/helm-install-image/releases/#{command.class::HELM_VERSION}-kube-#{Gitlab::Kubernetes::Helm::KUBECTL_VERSION}-alpine-3.12",
env: generate_pod_env(command),
command: %w(/bin/sh),
args: %w(-c $(COMMAND_SCRIPT))
@ -50,11 +50,10 @@ module Gitlab
end
def generate_pod_env(command)
{
HELM_VERSION: Gitlab::Kubernetes::Helm::HELM_VERSION,
TILLER_NAMESPACE: namespace_name,
command.env.merge(
HELM_VERSION: command.class::HELM_VERSION,
COMMAND_SCRIPT: command.generate_script
}.map { |key, value| { name: key, value: value } }
).map { |key, value| { name: key, value: value } }
end
def volumes_specification

View File

@ -1,48 +0,0 @@
# frozen_string_literal: true
module Gitlab
module Kubernetes
module Helm
class ResetCommand < BaseCommand
include ClientCommand
def generate_script
super + [
reset_helm_command,
delete_tiller_replicaset,
delete_tiller_clusterrolebinding
].join("\n")
end
def pod_name
"uninstall-#{name}"
end
private
# This method can be delete once we upgrade Helm to > 12.13.0
# https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/27096#note_159695900
#
# Tracking this method to be removed here:
# https://gitlab.com/gitlab-org/gitlab-foss/issues/52791#note_199374155
def delete_tiller_replicaset
delete_args = %w[replicaset -n gitlab-managed-apps -l name=tiller]
Gitlab::Kubernetes::KubectlCmd.delete(*delete_args)
end
def delete_tiller_clusterrolebinding
delete_args = %w[clusterrolebinding tiller-admin]
Gitlab::Kubernetes::KubectlCmd.delete(*delete_args)
end
def reset_helm_command
command = %w[helm reset] + optional_tls_flags
command.shelljoin
end
end
end
end
end

View File

@ -0,0 +1,93 @@
# frozen_string_literal: true
module Gitlab
module Kubernetes
module Helm
module V2
class BaseCommand
attr_reader :name, :files
HELM_VERSION = '2.16.9'
def initialize(rbac:, name:, files:)
@rbac = rbac
@name = name
@files = files
end
def env
{ TILLER_NAMESPACE: namespace }
end
def rbac?
@rbac
end
def pod_resource
pod_service_account_name = rbac? ? service_account_name : nil
Gitlab::Kubernetes::Helm::Pod.new(self, namespace, service_account_name: pod_service_account_name).generate
end
def generate_script
<<~HEREDOC
set -xeo pipefail
HEREDOC
end
def pod_name
"install-#{name}"
end
def config_map_resource
Gitlab::Kubernetes::ConfigMap.new(name, files).generate
end
def service_account_resource
return unless rbac?
Gitlab::Kubernetes::ServiceAccount.new(service_account_name, namespace).generate
end
def cluster_role_binding_resource
return unless rbac?
subjects = [{ kind: 'ServiceAccount', name: service_account_name, namespace: namespace }]
Gitlab::Kubernetes::ClusterRoleBinding.new(
cluster_role_binding_name,
cluster_role_name,
subjects
).generate
end
def file_names
files.keys
end
private
def files_dir
"/data/helm/#{name}/config"
end
def namespace
Gitlab::Kubernetes::Helm::NAMESPACE
end
def service_account_name
Gitlab::Kubernetes::Helm::SERVICE_ACCOUNT
end
def cluster_role_binding_name
Gitlab::Kubernetes::Helm::CLUSTER_ROLE_BINDING
end
def cluster_role_name
Gitlab::Kubernetes::Helm::CLUSTER_ROLE
end
end
end
end
end
end

View File

@ -0,0 +1,75 @@
# frozen_string_literal: true
module Gitlab
module Kubernetes
module Helm
module V2
class Certificate
INFINITE_EXPIRY = 1000.years
SHORT_EXPIRY = 30.minutes
attr_reader :key, :cert
def key_string
@key.to_s
end
def cert_string
@cert.to_pem
end
def self.from_strings(key_string, cert_string)
key = OpenSSL::PKey::RSA.new(key_string)
cert = OpenSSL::X509::Certificate.new(cert_string)
new(key, cert)
end
def self.generate_root
_issue(signed_by: nil, expires_in: INFINITE_EXPIRY, certificate_authority: true)
end
def issue(expires_in: SHORT_EXPIRY)
self.class._issue(signed_by: self, expires_in: expires_in, certificate_authority: false)
end
private
def self._issue(signed_by:, expires_in:, certificate_authority:)
key = OpenSSL::PKey::RSA.new(4096)
public_key = key.public_key
subject = OpenSSL::X509::Name.parse("/C=US")
cert = OpenSSL::X509::Certificate.new
cert.subject = subject
cert.issuer = signed_by&.cert&.subject || subject
cert.not_before = Time.now.utc
cert.not_after = expires_in.from_now.utc
cert.public_key = public_key
cert.serial = 0x0
cert.version = 2
if certificate_authority
extension_factory = OpenSSL::X509::ExtensionFactory.new
extension_factory.subject_certificate = cert
extension_factory.issuer_certificate = cert
cert.add_extension(extension_factory.create_extension('subjectKeyIdentifier', 'hash'))
cert.add_extension(extension_factory.create_extension('basicConstraints', 'CA:TRUE', true))
cert.add_extension(extension_factory.create_extension('keyUsage', 'cRLSign,keyCertSign', true))
end
cert.sign(signed_by&.key || key, OpenSSL::Digest::SHA256.new)
new(key, cert)
end
def initialize(key, cert)
@key = key
@cert = cert
end
end
end
end
end
end

View File

@ -0,0 +1,40 @@
# frozen_string_literal: true
module Gitlab
module Kubernetes
module Helm
module V2
module ClientCommand
def init_command
<<~SHELL.chomp
export HELM_HOST="localhost:44134"
tiller -listen ${HELM_HOST} -alsologtostderr &
helm init --client-only
SHELL
end
def repository_command
['helm', 'repo', 'add', name, repository].shelljoin if repository
end
private
def repository_update_command
'helm repo update'
end
def optional_tls_flags
return [] unless files.key?(:'ca.pem')
[
'--tls',
'--tls-ca-cert', "#{files_dir}/ca.pem",
'--tls-cert', "#{files_dir}/cert.pem",
'--tls-key', "#{files_dir}/key.pem"
]
end
end
end
end
end
end

View File

@ -0,0 +1,38 @@
# frozen_string_literal: true
module Gitlab
module Kubernetes
module Helm
module V2
class DeleteCommand < BaseCommand
include ClientCommand
attr_reader :predelete, :postdelete
def initialize(predelete: nil, postdelete: nil, **args)
super(**args)
@predelete = predelete
@postdelete = postdelete
end
def generate_script
super + [
init_command,
predelete,
delete_command,
postdelete
].compact.join("\n")
end
def pod_name
"uninstall-#{name}"
end
def delete_command
['helm', 'delete', '--purge', name].shelljoin
end
end
end
end
end
end

View File

@ -0,0 +1,45 @@
# frozen_string_literal: true
module Gitlab
module Kubernetes
module Helm
module V2
class InitCommand < BaseCommand
def generate_script
super + [
init_helm_command
].join("\n")
end
private
def init_helm_command
command = %w[helm init] + init_command_flags
command.shelljoin
end
def init_command_flags
tls_flags + optional_service_account_flag
end
def tls_flags
[
'--tiller-tls',
'--tiller-tls-verify',
'--tls-ca-cert', "#{files_dir}/ca.pem",
'--tiller-tls-cert', "#{files_dir}/cert.pem",
'--tiller-tls-key', "#{files_dir}/key.pem"
]
end
def optional_service_account_flag
return [] unless rbac?
['--service-account', service_account_name]
end
end
end
end
end
end

View File

@ -0,0 +1,87 @@
# frozen_string_literal: true
module Gitlab
module Kubernetes
module Helm
module V2
class InstallCommand < BaseCommand
include ClientCommand
attr_reader :chart, :repository, :preinstall, :postinstall
attr_accessor :version
def initialize(chart:, version: nil, repository: nil, preinstall: nil, postinstall: nil, **args)
super(**args)
@chart = chart
@version = version
@repository = repository
@preinstall = preinstall
@postinstall = postinstall
end
def generate_script
super + [
init_command,
repository_command,
repository_update_command,
preinstall,
install_command,
postinstall
].compact.join("\n")
end
private
# Uses `helm upgrade --install` which means we can use this for both
# installation and uprade of applications
def install_command
command = ['helm', 'upgrade', name, chart] +
install_flag +
rollback_support_flag +
reset_values_flag +
optional_version_flag +
rbac_create_flag +
namespace_flag +
value_flag
command.shelljoin
end
def install_flag
['--install']
end
def reset_values_flag
['--reset-values']
end
def value_flag
['-f', "/data/helm/#{name}/config/values.yaml"]
end
def namespace_flag
['--namespace', Gitlab::Kubernetes::Helm::NAMESPACE]
end
def rbac_create_flag
if rbac?
%w[--set rbac.create=true,rbac.enabled=true]
else
%w[--set rbac.create=false,rbac.enabled=false]
end
end
def optional_version_flag
return [] unless version
['--version', version]
end
def rollback_support_flag
['--atomic', '--cleanup-on-fail']
end
end
end
end
end
end

View File

@ -0,0 +1,67 @@
# frozen_string_literal: true
# PatchCommand is for updating values in installed charts without overwriting
# existing values.
module Gitlab
module Kubernetes
module Helm
module V2
class PatchCommand < BaseCommand
include ClientCommand
attr_reader :chart, :repository
attr_accessor :version
def initialize(chart:, version:, repository: nil, **args)
super(**args)
# version is mandatory to prevent chart mismatches
# we do not want our values interpreted in the context of the wrong version
raise ArgumentError, 'version is required' if version.blank?
@chart = chart
@version = version
@repository = repository
end
def generate_script
super + [
init_command,
repository_command,
repository_update_command,
upgrade_command
].compact.join("\n")
end
private
def upgrade_command
command = ['helm', 'upgrade', name, chart] +
reuse_values_flag +
version_flag +
namespace_flag +
value_flag
command.shelljoin
end
def reuse_values_flag
['--reuse-values']
end
def value_flag
['-f', "/data/helm/#{name}/config/values.yaml"]
end
def namespace_flag
['--namespace', Gitlab::Kubernetes::Helm::NAMESPACE]
end
def version_flag
['--version', version]
end
end
end
end
end
end

View File

@ -0,0 +1,50 @@
# frozen_string_literal: true
module Gitlab
module Kubernetes
module Helm
module V2
class ResetCommand < BaseCommand
include ClientCommand
def generate_script
super + [
reset_helm_command,
delete_tiller_replicaset,
delete_tiller_clusterrolebinding
].join("\n")
end
def pod_name
"uninstall-#{name}"
end
private
# This method can be delete once we upgrade Helm to > 12.13.0
# https://gitlab.com/gitlab-org/gitlab-foss/merge_requests/27096#note_159695900
#
# Tracking this method to be removed here:
# https://gitlab.com/gitlab-org/gitlab-foss/issues/52791#note_199374155
def delete_tiller_replicaset
delete_args = %w[replicaset -n gitlab-managed-apps -l name=tiller]
Gitlab::Kubernetes::KubectlCmd.delete(*delete_args)
end
def delete_tiller_clusterrolebinding
delete_args = %w[clusterrolebinding tiller-admin]
Gitlab::Kubernetes::KubectlCmd.delete(*delete_args)
end
def reset_helm_command
command = %w[helm reset] + optional_tls_flags
command.shelljoin
end
end
end
end
end
end

View File

@ -0,0 +1,101 @@
# frozen_string_literal: true
module Gitlab
module Kubernetes
module Helm
module V3
class BaseCommand
attr_reader :name, :files
HELM_VERSION = '3.2.4'
def initialize(rbac:, name:, files:)
@rbac = rbac
@name = name
@files = files
end
def env
{}
end
def rbac?
@rbac
end
def pod_resource
pod_service_account_name = rbac? ? service_account_name : nil
Gitlab::Kubernetes::Helm::Pod.new(self, namespace, service_account_name: pod_service_account_name).generate
end
def generate_script
<<~HEREDOC
set -xeo pipefail
HEREDOC
end
def pod_name
"install-#{name}"
end
def config_map_resource
Gitlab::Kubernetes::ConfigMap.new(name, files).generate
end
def service_account_resource
return unless rbac?
Gitlab::Kubernetes::ServiceAccount.new(service_account_name, namespace).generate
end
def cluster_role_binding_resource
return unless rbac?
subjects = [{ kind: 'ServiceAccount', name: service_account_name, namespace: namespace }]
Gitlab::Kubernetes::ClusterRoleBinding.new(
cluster_role_binding_name,
cluster_role_name,
subjects
).generate
end
def file_names
files.keys
end
def repository_command
['helm', 'repo', 'add', name, repository].shelljoin if repository
end
private
def repository_update_command
'helm repo update'
end
def namespace_flag
['--namespace', Gitlab::Kubernetes::Helm::NAMESPACE]
end
def namespace
Gitlab::Kubernetes::Helm::NAMESPACE
end
def service_account_name
Gitlab::Kubernetes::Helm::SERVICE_ACCOUNT
end
def cluster_role_binding_name
Gitlab::Kubernetes::Helm::CLUSTER_ROLE_BINDING
end
def cluster_role_name
Gitlab::Kubernetes::Helm::CLUSTER_ROLE
end
end
end
end
end
end

View File

@ -0,0 +1,35 @@
# frozen_string_literal: true
module Gitlab
module Kubernetes
module Helm
module V3
class DeleteCommand < BaseCommand
attr_reader :predelete, :postdelete
def initialize(predelete: nil, postdelete: nil, **args)
super(**args)
@predelete = predelete
@postdelete = postdelete
end
def generate_script
super + [
predelete,
delete_command,
postdelete
].compact.join("\n")
end
def pod_name
"uninstall-#{name}"
end
def delete_command
['helm', 'uninstall', name, *namespace_flag].shelljoin
end
end
end
end
end
end

View File

@ -0,0 +1,80 @@
# frozen_string_literal: true
module Gitlab
module Kubernetes
module Helm
module V3
class InstallCommand < BaseCommand
attr_reader :chart, :repository, :preinstall, :postinstall
attr_accessor :version
def initialize(chart:, version: nil, repository: nil, preinstall: nil, postinstall: nil, **args)
super(**args)
@chart = chart
@version = version
@repository = repository
@preinstall = preinstall
@postinstall = postinstall
end
def generate_script
super + [
repository_command,
repository_update_command,
preinstall,
install_command,
postinstall
].compact.join("\n")
end
private
# Uses `helm upgrade --install` which means we can use this for both
# installation and uprade of applications
def install_command
command = ['helm', 'upgrade', name, chart] +
install_flag +
rollback_support_flag +
reset_values_flag +
optional_version_flag +
rbac_create_flag +
namespace_flag +
value_flag
command.shelljoin
end
def install_flag
['--install']
end
def reset_values_flag
['--reset-values']
end
def value_flag
['-f', "/data/helm/#{name}/config/values.yaml"]
end
def rbac_create_flag
if rbac?
%w[--set rbac.create=true,rbac.enabled=true]
else
%w[--set rbac.create=false,rbac.enabled=false]
end
end
def optional_version_flag
return [] unless version
['--version', version]
end
def rollback_support_flag
['--atomic', '--cleanup-on-fail']
end
end
end
end
end
end

View File

@ -0,0 +1,60 @@
# frozen_string_literal: true
# PatchCommand is for updating values in installed charts without overwriting
# existing values.
module Gitlab
module Kubernetes
module Helm
module V3
class PatchCommand < BaseCommand
attr_reader :chart, :repository
attr_accessor :version
def initialize(chart:, version:, repository: nil, **args)
super(**args)
# version is mandatory to prevent chart mismatches
# we do not want our values interpreted in the context of the wrong version
raise ArgumentError, 'version is required' if version.blank?
@chart = chart
@version = version
@repository = repository
end
def generate_script
super + [
repository_command,
repository_update_command,
upgrade_command
].compact.join("\n")
end
private
def upgrade_command
command = ['helm', 'upgrade', name, chart] +
reuse_values_flag +
version_flag +
namespace_flag +
value_flag
command.shelljoin
end
def reuse_values_flag
['--reuse-values']
end
def value_flag
['-f', "/data/helm/#{name}/config/values.yaml"]
end
def version_flag
['--version', version]
end
end
end
end
end
end

View File

@ -18511,6 +18511,9 @@ msgstr ""
msgid "Notes|This comment has changed since you started editing, please review the %{open_link}updated comment%{close_link} to ensure information is not lost"
msgstr ""
msgid "Notes|You're only seeing %{boldStart}other activity%{boldEnd} in the feed. To add a comment, switch to one of the following options."
msgstr ""
msgid "Nothing found…"
msgstr ""
@ -30920,9 +30923,6 @@ msgstr ""
msgid "You're not allowed to make changes to this project directly. A fork of this project is being created that you can make changes in, so you can submit a merge request."
msgstr ""
msgid "You're only seeing %{startTag}other activity%{endTag} in the feed. To add a comment, switch to one of the following options."
msgstr ""
msgid "You're receiving this email because of your account on %{host}."
msgstr ""

View File

@ -5,7 +5,7 @@ FactoryBot.define do
cluster factory: %i(cluster provided_by_gcp)
before(:create) do
allow(Gitlab::Kubernetes::Helm::Certificate).to receive(:generate_root)
allow(Gitlab::Kubernetes::Helm::V2::Certificate).to receive(:generate_root)
.and_return(
double(
key_string: File.read(Rails.root.join('spec/fixtures/clusters/sample_key.key')),
@ -15,7 +15,7 @@ FactoryBot.define do
end
after(:create) do
allow(Gitlab::Kubernetes::Helm::Certificate).to receive(:generate_root).and_call_original
allow(Gitlab::Kubernetes::Helm::V2::Certificate).to receive(:generate_root).and_call_original
end
trait :not_installable do

View File

@ -21,7 +21,6 @@
},
"commit_path": { "type": "string" },
"tag_path": { "type": "string" },
"name": { "type": "string" },
"evidences": {
"type": "array",
"items": { "$ref": "release/evidence.json" }
@ -42,11 +41,8 @@
"additionalProperties": false
},
"_links": {
"required": ["merge_requests_url", "issues_url"],
"properties": {
"merge_requests_url": { "type": "string" },
"issues_url": { "type": "string" },
"edit_url": { "type": "string"}
"edit_url": { "type": "string" }
}
}
},

View File

@ -26,11 +26,7 @@
"additionalProperties": false
},
"_links": {
"required": ["merge_requests_url", "issues_url"],
"properties": {
"merge_requests_url": { "type": "string" },
"issues_url": { "type": "string" }
}
"properties": {}
}
},
"additionalProperties": false

View File

@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils';
import { GlButton, GlSprintf } from '@gitlab/ui';
import DiscussionFilterNote from '~/notes/components/discussion_filter_note.vue';
import eventHub from '~/notes/event_hub';
@ -6,7 +7,11 @@ describe('DiscussionFilterNote component', () => {
let wrapper;
const createComponent = () => {
wrapper = shallowMount(DiscussionFilterNote);
wrapper = shallowMount(DiscussionFilterNote, {
stubs: {
GlSprintf,
},
});
};
beforeEach(() => {
@ -19,21 +24,27 @@ describe('DiscussionFilterNote component', () => {
});
it('timelineContent renders a string containing instruction for switching feed type', () => {
expect(wrapper.find({ ref: 'timelineContent' }).html()).toBe(
"<div>You're only seeing <b>other activity</b> in the feed. To add a comment, switch to one of the following options.</div>",
expect(wrapper.find('[data-testid="discussion-filter-timeline-content"]').html()).toBe(
'<div data-testid="discussion-filter-timeline-content">You\'re only seeing <b>other activity</b> in the feed. To add a comment, switch to one of the following options.</div>',
);
});
it('emits `dropdownSelect` event with 0 parameter on clicking Show all activity button', () => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
wrapper.find({ ref: 'showAllActivity' }).vm.$emit('click');
wrapper
.findAll(GlButton)
.at(0)
.vm.$emit('click');
expect(eventHub.$emit).toHaveBeenCalledWith('dropdownSelect', 0);
});
it('emits `dropdownSelect` event with 1 parameter on clicking Show comments only button', () => {
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
wrapper.find({ ref: 'showComments' }).vm.$emit('click');
wrapper
.findAll(GlButton)
.at(1)
.vm.$emit('click');
expect(eventHub.$emit).toHaveBeenCalledWith('dropdownSelect', 1);
});

View File

@ -14,8 +14,6 @@ RSpec.describe GitlabSchema.types['ReleaseLinks'] do
openedIssuesUrl
closedIssuesUrl
editUrl
mergeRequestsUrl
issuesUrl
]
expect(described_class).to include_graphql_fields(*expected_fields)

View File

@ -65,10 +65,22 @@ RSpec.describe Gitlab::ImportExport::Importer do
end
end
it 'restores the ProjectTree' do
expect(Gitlab::ImportExport::Project::TreeRestorer).to receive(:new).and_call_original
context 'with sample_data_template' do
it 'initializes the Sample::TreeRestorer' do
project.create_or_update_import_data(data: { sample_data: true })
importer.execute
expect(Gitlab::ImportExport::Project::Sample::TreeRestorer).to receive(:new).and_call_original
importer.execute
end
end
context 'without sample_data_template' do
it 'initializes the ProjectTree' do
expect(Gitlab::ImportExport::Project::TreeRestorer).to receive(:new).and_call_original
importer.execute
end
end
it 'removes the import file' do

View File

@ -0,0 +1,168 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::ImportExport::Project::Sample::RelationFactory do
let(:group) { create(:group) }
let(:project) { create(:project, :repository, group: group) }
let(:members_mapper) { double('members_mapper').as_null_object }
let(:admin) { create(:admin) }
let(:importer_user) { admin }
let(:excluded_keys) { [] }
let(:date_calculator) { instance_double(Gitlab::ImportExport::Project::Sample::DateCalculator) }
let(:original_project_id) { 8 }
let(:start_date) { Time.current - 30.days }
let(:due_date) { Time.current - 20.days }
let(:created_object) do
described_class.create( # rubocop:disable Rails/SaveBang
relation_sym: relation_sym,
relation_hash: relation_hash,
object_builder: Gitlab::ImportExport::Project::ObjectBuilder,
members_mapper: members_mapper,
user: importer_user,
importable: project,
excluded_keys: excluded_keys,
date_calculator: date_calculator
)
end
context 'issue object' do
let(:relation_sym) { :issues }
let(:id) { 999 }
let(:relation_hash) do
{
'id' => id,
'title' => 'Necessitatibus magnam qui at velit consequatur perspiciatis.',
'project_id' => original_project_id,
'created_at' => '2016-08-12T09:41:03.462Z',
'updated_at' => '2016-08-12T09:41:03.462Z',
'description' => 'Molestiae corporis magnam et fugit aliquid nulla quia.',
'state' => 'closed',
'position' => 0,
'confidential' => false,
'due_date' => due_date
}
end
before do
allow(date_calculator).to receive(:closest_date_to_average) { Time.current - 10.days }
allow(date_calculator).to receive(:calculate_by_closest_date_to_average)
end
it 'correctly updated due date', :aggregate_failures do
expect(date_calculator).to receive(:calculate_by_closest_date_to_average)
.with(relation_hash['due_date']).and_return(due_date - 10.days)
expect(created_object.due_date).to eq((due_date - 10.days).to_date)
end
end
context 'milestone object' do
let(:relation_sym) { :milestones }
let(:id) { 1001 }
let(:relation_hash) do
{
'id' => id,
'title' => 'v3.0',
'project_id' => original_project_id,
'created_at' => '2016-08-12T09:41:03.462Z',
'updated_at' => '2016-08-12T09:41:03.462Z',
'description' => 'Rerum at autem exercitationem ea voluptates harum quam placeat.',
'state' => 'closed',
'start_date' => start_date,
'due_date' => due_date
}
end
before do
allow(date_calculator).to receive(:closest_date_to_average).twice { Time.current - 10.days }
allow(date_calculator).to receive(:calculate_by_closest_date_to_average).twice
end
it 'correctly updated due date', :aggregate_failures do
expect(date_calculator).to receive(:calculate_by_closest_date_to_average)
.with(relation_hash['due_date']).and_return(due_date - 10.days)
expect(created_object.due_date).to eq((due_date - 10.days).to_date)
end
it 'correctly updated start date', :aggregate_failures do
expect(date_calculator).to receive(:calculate_by_closest_date_to_average)
.with(relation_hash['start_date']).and_return(start_date - 20.days)
expect(created_object.start_date).to eq((start_date - 20.days).to_date)
end
end
context 'milestone object' do
let(:relation_sym) { :milestones }
let(:id) { 1001 }
let(:relation_hash) do
{
'id' => id,
'title' => 'v3.0',
'project_id' => original_project_id,
'created_at' => '2016-08-12T09:41:03.462Z',
'updated_at' => '2016-08-12T09:41:03.462Z',
'description' => 'Rerum at autem exercitationem ea voluptates harum quam placeat.',
'state' => 'closed',
'start_date' => start_date,
'due_date' => due_date
}
end
before do
allow(date_calculator).to receive(:closest_date_to_average).twice { Time.current - 10.days }
allow(date_calculator).to receive(:calculate_by_closest_date_to_average).twice
end
it 'correctly updated due date', :aggregate_failures do
expect(date_calculator).to receive(:calculate_by_closest_date_to_average)
.with(relation_hash['due_date']).and_return(due_date - 10.days)
expect(created_object.due_date).to eq((due_date - 10.days).to_date)
end
it 'correctly updated start date', :aggregate_failures do
expect(date_calculator).to receive(:calculate_by_closest_date_to_average)
.with(relation_hash['start_date']).and_return(start_date - 20.days)
expect(created_object.start_date).to eq((start_date - 20.days).to_date)
end
end
context 'hook object' do
let(:relation_sym) { :hooks }
let(:id) { 999 }
let(:service_id) { 99 }
let(:token) { 'secret' }
let(:relation_hash) do
{
'id' => id,
'url' => 'https://example.json',
'project_id' => original_project_id,
'created_at' => '2016-08-12T09:41:03.462Z',
'updated_at' => '2016-08-12T09:41:03.462Z',
'service_id' => service_id,
'push_events' => true,
'issues_events' => false,
'confidential_issues_events' => false,
'merge_requests_events' => true,
'tag_push_events' => false,
'note_events' => true,
'enable_ssl_verification' => true,
'job_events' => false,
'wiki_page_events' => true,
'token' => token
}
end
it 'does not calculate the closest date to average' do
expect(date_calculator).not_to receive(:calculate_by_closest_date_to_average)
end
end
end

View File

@ -9,7 +9,7 @@
require 'spec_helper'
RSpec.describe Gitlab::ImportExport::Project::Sample::SampleDataRelationTreeRestorer do
RSpec.describe Gitlab::ImportExport::Project::Sample::RelationTreeRestorer do
include_context 'relation tree restorer shared context'
let(:sample_data_relation_tree_restorer) do
@ -74,13 +74,26 @@ RSpec.describe Gitlab::ImportExport::Project::Sample::SampleDataRelationTreeRest
let(:importable_name) { 'project' }
let(:importable_path) { 'project' }
let(:object_builder) { Gitlab::ImportExport::Project::ObjectBuilder }
let(:relation_factory) { Gitlab::ImportExport::Project::RelationFactory }
let(:relation_factory) { Gitlab::ImportExport::Project::Sample::RelationFactory }
let(:reader) { Gitlab::ImportExport::Reader.new(shared: shared) }
let(:path) { 'spec/fixtures/lib/gitlab/import_export/sample_data/tree' }
let(:relation_reader) { Gitlab::ImportExport::JSON::NdjsonReader.new(path) }
it 'initializes relation_factory with date_calculator as parameter' do
expect(Gitlab::ImportExport::Project::Sample::RelationFactory).to receive(:create).with(hash_including(:date_calculator)).at_least(:once).times
subject
end
context 'when relation tree restorer is initialized' do
it 'initializes date calculator with due dates' do
expect(Gitlab::ImportExport::Project::Sample::DateCalculator).to receive(:new).with(Array)
sample_data_relation_tree_restorer
end
end
context 'using ndjson reader' do
let(:path) { 'spec/fixtures/lib/gitlab/import_export/sample_data/tree' }
let(:relation_reader) { Gitlab::ImportExport::JSON::NdjsonReader.new(path) }
it_behaves_like 'import project successfully'
end
end

View File

@ -1040,41 +1040,6 @@ RSpec.describe Gitlab::ImportExport::Project::TreeRestorer do
it_behaves_like 'project tree restorer work properly', :legacy_reader, true
it_behaves_like 'project tree restorer work properly', :ndjson_reader, true
context 'Sample Data JSON' do
let(:user) { create(:user) }
let!(:project) { create(:project, :builds_disabled, :issues_disabled, name: 'project', path: 'project') }
let(:project_tree_restorer) { described_class.new(user: user, shared: shared, project: project) }
before do
setup_import_export_config('sample_data')
setup_reader(:ndjson_reader)
end
context 'with sample_data_template' do
before do
allow(project).to receive_message_chain(:import_data, :data, :dig).with('sample_data') { true }
end
it 'initialize SampleDataRelationTreeRestorer' do
expect_next_instance_of(Gitlab::ImportExport::Project::Sample::SampleDataRelationTreeRestorer) do |restorer|
expect(restorer).to receive(:restore).and_return(true)
end
expect(project_tree_restorer.restore).to eq(true)
end
end
context 'without sample_data_template' do
it 'initialize RelationTreeRestorer' do
expect_next_instance_of(Gitlab::ImportExport::RelationTreeRestorer) do |restorer|
expect(restorer).to receive(:restore).and_return(true)
end
expect(project_tree_restorer.restore).to eq(true)
end
end
end
end
context 'disable ndjson import' do

View File

@ -13,7 +13,7 @@ RSpec.describe Gitlab::Kubernetes::Helm::API do
let(:files) { {} }
let(:command) do
Gitlab::Kubernetes::Helm::InstallCommand.new(
Gitlab::Kubernetes::Helm::V2::InstallCommand.new(
name: application_name,
chart: 'chart-name',
rbac: rbac,
@ -142,7 +142,7 @@ RSpec.describe Gitlab::Kubernetes::Helm::API do
end
context 'with a service account' do
let(:command) { Gitlab::Kubernetes::Helm::InitCommand.new(name: application_name, files: files, rbac: rbac) }
let(:command) { Gitlab::Kubernetes::Helm::V2::InitCommand.new(name: application_name, files: files, rbac: rbac) }
context 'rbac-enabled cluster' do
let(:rbac) { true }

View File

@ -4,75 +4,84 @@ require 'spec_helper'
RSpec.describe Gitlab::Kubernetes::Helm::Pod do
describe '#generate' do
let(:app) { create(:clusters_applications_prometheus) }
let(:command) { app.install_command }
let(:namespace) { Gitlab::Kubernetes::Helm::NAMESPACE }
let(:service_account_name) { nil }
using RSpec::Parameterized::TableSyntax
subject { described_class.new(command, namespace, service_account_name: service_account_name) }
where(:helm_major_version, :expected_helm_version, :expected_command_env) do
2 | '2.16.9' | [:TILLER_NAMESPACE]
3 | '3.2.4' | nil
end
context 'with a command' do
it 'generates a Kubeclient::Resource' do
expect(subject.generate).to be_a_kind_of(Kubeclient::Resource)
end
with_them do
let(:cluster) { create(:cluster, helm_major_version: helm_major_version) }
let(:app) { create(:clusters_applications_prometheus, cluster: cluster) }
let(:command) { app.install_command }
let(:namespace) { Gitlab::Kubernetes::Helm::NAMESPACE }
let(:service_account_name) { nil }
it 'generates the appropriate metadata' do
metadata = subject.generate.metadata
expect(metadata.name).to eq("install-#{app.name}")
expect(metadata.namespace).to eq('gitlab-managed-apps')
expect(metadata.labels['gitlab.org/action']).to eq('install')
expect(metadata.labels['gitlab.org/application']).to eq(app.name)
end
subject { described_class.new(command, namespace, service_account_name: service_account_name) }
it 'generates a container spec' do
spec = subject.generate.spec
expect(spec.containers.count).to eq(1)
end
context 'with a command' do
it 'generates a Kubeclient::Resource' do
expect(subject.generate).to be_a_kind_of(Kubeclient::Resource)
end
it 'generates the appropriate specifications for the container' do
container = subject.generate.spec.containers.first
expect(container.name).to eq('helm')
expect(container.image).to eq('registry.gitlab.com/gitlab-org/cluster-integration/helm-install-image/releases/2.16.9-kube-1.13.12')
expect(container.env.count).to eq(3)
expect(container.env.map(&:name)).to match_array([:HELM_VERSION, :TILLER_NAMESPACE, :COMMAND_SCRIPT])
expect(container.command).to match_array(["/bin/sh"])
expect(container.args).to match_array(["-c", "$(COMMAND_SCRIPT)"])
end
it 'generates the appropriate metadata' do
metadata = subject.generate.metadata
expect(metadata.name).to eq("install-#{app.name}")
expect(metadata.namespace).to eq('gitlab-managed-apps')
expect(metadata.labels['gitlab.org/action']).to eq('install')
expect(metadata.labels['gitlab.org/application']).to eq(app.name)
end
it 'includes a never restart policy' do
spec = subject.generate.spec
expect(spec.restartPolicy).to eq('Never')
end
it 'includes volumes for the container' do
container = subject.generate.spec.containers.first
expect(container.volumeMounts.first['name']).to eq('configuration-volume')
expect(container.volumeMounts.first['mountPath']).to eq("/data/helm/#{app.name}/config")
end
it 'includes a volume inside the specification' do
spec = subject.generate.spec
expect(spec.volumes.first['name']).to eq('configuration-volume')
end
it 'mounts configMap specification in the volume' do
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.yaml')
expect(volume.configMap['items'].first['path']).to eq(:'values.yaml')
end
it 'has no serviceAccountName' do
spec = subject.generate.spec
expect(spec.serviceAccountName).to be_nil
end
context 'with a service_account_name' do
let(:service_account_name) { 'sa' }
it 'uses the serviceAccountName provided' do
it 'generates a container spec' do
spec = subject.generate.spec
expect(spec.serviceAccountName).to eq(service_account_name)
expect(spec.containers.count).to eq(1)
end
it 'generates the appropriate specifications for the container' do
container = subject.generate.spec.containers.first
expect(container.name).to eq('helm')
expect(container.image).to eq("registry.gitlab.com/gitlab-org/cluster-integration/helm-install-image/releases/#{expected_helm_version}-kube-1.13.12-alpine-3.12")
expect(container.env.map(&:name)).to include(:HELM_VERSION, :COMMAND_SCRIPT, *expected_command_env)
expect(container.command).to match_array(["/bin/sh"])
expect(container.args).to match_array(["-c", "$(COMMAND_SCRIPT)"])
end
it 'includes a never restart policy' do
spec = subject.generate.spec
expect(spec.restartPolicy).to eq('Never')
end
it 'includes volumes for the container' do
container = subject.generate.spec.containers.first
expect(container.volumeMounts.first['name']).to eq('configuration-volume')
expect(container.volumeMounts.first['mountPath']).to eq("/data/helm/#{app.name}/config")
end
it 'includes a volume inside the specification' do
spec = subject.generate.spec
expect(spec.volumes.first['name']).to eq('configuration-volume')
end
it 'mounts configMap specification in the volume' do
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.yaml')
expect(volume.configMap['items'].first['path']).to eq(:'values.yaml')
end
it 'has no serviceAccountName' do
spec = subject.generate.spec
expect(spec.serviceAccountName).to be_nil
end
context 'with a service_account_name' do
let(:service_account_name) { 'sa' }
it 'uses the serviceAccountName provided' do
spec = subject.generate.spec
expect(spec.serviceAccountName).to eq(service_account_name)
end
end
end
end

View File

@ -0,0 +1,50 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Kubernetes::Helm::V2::BaseCommand do
subject(:base_command) do
test_class.new(rbac)
end
let(:application) { create(:clusters_applications_helm) }
let(:rbac) { false }
let(:test_class) do
Class.new(described_class) do
def initialize(rbac)
super(
name: 'test-class-name',
rbac: rbac,
files: { some: 'value' }
)
end
end
end
describe 'HELM_VERSION' do
subject { described_class::HELM_VERSION }
it { is_expected.to match /^2\.\d+\.\d+$/ }
end
describe '#env' do
subject { base_command.env }
it { is_expected.to include(TILLER_NAMESPACE: 'gitlab-managed-apps') }
end
it_behaves_like 'helm command generator' do
let(:commands) { '' }
end
describe '#pod_name' do
subject { base_command.pod_name }
it { is_expected.to eq('install-test-class-name') }
end
it_behaves_like 'helm command' do
let(:command) { base_command }
end
end

View File

@ -1,7 +1,7 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Kubernetes::Helm::Certificate do
RSpec.describe Gitlab::Kubernetes::Helm::V2::Certificate do
describe '.generate_root' do
subject { described_class.generate_root }

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Kubernetes::Helm::DeleteCommand do
RSpec.describe Gitlab::Kubernetes::Helm::V2::DeleteCommand do
subject(:delete_command) { described_class.new(name: app_name, rbac: rbac, files: files) }
let(:app_name) { 'app-name' }

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Kubernetes::Helm::InitCommand do
RSpec.describe Gitlab::Kubernetes::Helm::V2::InitCommand do
subject(:init_command) { described_class.new(name: application.name, files: files, rbac: rbac) }
let(:application) { create(:clusters_applications_helm) }

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Kubernetes::Helm::InstallCommand do
RSpec.describe Gitlab::Kubernetes::Helm::V2::InstallCommand do
subject(:install_command) do
described_class.new(
name: 'app-name',
@ -147,37 +147,6 @@ RSpec.describe Gitlab::Kubernetes::Helm::InstallCommand do
end
end
context 'when there is no ca.pem file' do
let(:files) { { 'file.txt': 'some content' } }
it_behaves_like 'helm command generator' do
let(:commands) do
<<~EOS
export HELM_HOST="localhost:44134"
tiller -listen ${HELM_HOST} -alsologtostderr &
helm init --client-only
helm repo add app-name https://repository.example.com
helm repo update
#{helm_install_command}
EOS
end
let(:helm_install_command) do
<<~EOS.squish
helm upgrade app-name chart-name
--install
--atomic
--cleanup-on-fail
--reset-values
--version 1.2.3
--set rbac.create\\=false,rbac.enabled\\=false
--namespace gitlab-managed-apps
-f /data/helm/app-name/config/values.yaml
EOS
end
end
end
context 'when there is no version' do
let(:version) { nil }

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Kubernetes::Helm::PatchCommand do
RSpec.describe Gitlab::Kubernetes::Helm::V2::PatchCommand do
let(:files) { { 'ca.pem': 'some file content' } }
let(:repository) { 'https://repository.example.com' }
let(:rbac) { false }
@ -69,33 +69,6 @@ RSpec.describe Gitlab::Kubernetes::Helm::PatchCommand do
end
end
context 'when there is no ca.pem file' do
let(:files) { { 'file.txt': 'some content' } }
it_behaves_like 'helm command generator' do
let(:commands) do
<<~EOS
export HELM_HOST="localhost:44134"
tiller -listen ${HELM_HOST} -alsologtostderr &
helm init --client-only
helm repo add app-name https://repository.example.com
helm repo update
#{helm_upgrade_command}
EOS
end
let(:helm_upgrade_command) do
<<~EOS.squish
helm upgrade app-name chart-name
--reuse-values
--version 1.2.3
--namespace gitlab-managed-apps
-f /data/helm/app-name/config/values.yaml
EOS
end
end
end
context 'when there is no version' do
let(:version) { nil }

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Kubernetes::Helm::ResetCommand do
RSpec.describe Gitlab::Kubernetes::Helm::V2::ResetCommand do
subject(:reset_command) { described_class.new(name: name, rbac: rbac, files: files) }
let(:rbac) { true }

View File

@ -2,7 +2,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Kubernetes::Helm::BaseCommand do
RSpec.describe Gitlab::Kubernetes::Helm::V3::BaseCommand do
subject(:base_command) do
test_class.new(rbac)
end
@ -11,7 +11,7 @@ RSpec.describe Gitlab::Kubernetes::Helm::BaseCommand do
let(:rbac) { false }
let(:test_class) do
Class.new(Gitlab::Kubernetes::Helm::BaseCommand) do
Class.new(described_class) do
def initialize(rbac)
super(
name: 'test-class-name',
@ -22,6 +22,12 @@ RSpec.describe Gitlab::Kubernetes::Helm::BaseCommand do
end
end
describe 'HELM_VERSION' do
subject { described_class::HELM_VERSION }
it { is_expected.to match /^3\.\d+\.\d+$/ }
end
it_behaves_like 'helm command generator' do
let(:commands) { '' }
end

View File

@ -0,0 +1,35 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Kubernetes::Helm::V3::DeleteCommand do
subject(:delete_command) { described_class.new(name: app_name, rbac: rbac, files: files) }
let(:app_name) { 'app-name' }
let(:rbac) { true }
let(:files) { {} }
it_behaves_like 'helm command generator' do
let(:commands) do
<<~EOS
helm uninstall app-name --namespace gitlab-managed-apps
EOS
end
end
describe '#pod_name' do
subject { delete_command.pod_name }
it { is_expected.to eq('uninstall-app-name') }
end
it_behaves_like 'helm command' do
let(:command) { delete_command }
end
describe '#delete_command' do
it 'deletes the release' do
expect(subject.delete_command).to eq('helm uninstall app-name --namespace gitlab-managed-apps')
end
end
end

View File

@ -0,0 +1,168 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Kubernetes::Helm::V3::InstallCommand do
subject(:install_command) do
described_class.new(
name: 'app-name',
chart: 'chart-name',
rbac: rbac,
files: files,
version: version,
repository: repository,
preinstall: preinstall,
postinstall: postinstall
)
end
let(:files) { { 'ca.pem': 'some file content' } }
let(:repository) { 'https://repository.example.com' }
let(:rbac) { false }
let(:version) { '1.2.3' }
let(:preinstall) { nil }
let(:postinstall) { nil }
it_behaves_like 'helm command generator' do
let(:commands) do
<<~EOS
helm repo add app-name https://repository.example.com
helm repo update
#{helm_install_comand}
EOS
end
let(:helm_install_comand) do
<<~EOS.squish
helm upgrade app-name chart-name
--install
--atomic
--cleanup-on-fail
--reset-values
--version 1.2.3
--set rbac.create\\=false,rbac.enabled\\=false
--namespace gitlab-managed-apps
-f /data/helm/app-name/config/values.yaml
EOS
end
end
context 'when rbac is true' do
let(:rbac) { true }
it_behaves_like 'helm command generator' do
let(:commands) do
<<~EOS
helm repo add app-name https://repository.example.com
helm repo update
#{helm_install_command}
EOS
end
let(:helm_install_command) do
<<~EOS.squish
helm upgrade app-name chart-name
--install
--atomic
--cleanup-on-fail
--reset-values
--version 1.2.3
--set rbac.create\\=true,rbac.enabled\\=true
--namespace gitlab-managed-apps
-f /data/helm/app-name/config/values.yaml
EOS
end
end
end
context 'when there is a pre-install script' do
let(:preinstall) { ['/bin/date', '/bin/true'] }
it_behaves_like 'helm command generator' do
let(:commands) do
<<~EOS
helm repo add app-name https://repository.example.com
helm repo update
/bin/date
/bin/true
#{helm_install_command}
EOS
end
let(:helm_install_command) do
<<~EOS.squish
helm upgrade app-name chart-name
--install
--atomic
--cleanup-on-fail
--reset-values
--version 1.2.3
--set rbac.create\\=false,rbac.enabled\\=false
--namespace gitlab-managed-apps
-f /data/helm/app-name/config/values.yaml
EOS
end
end
end
context 'when there is a post-install script' do
let(:postinstall) { ['/bin/date', "/bin/false\n"] }
it_behaves_like 'helm command generator' do
let(:commands) do
<<~EOS
helm repo add app-name https://repository.example.com
helm repo update
#{helm_install_command}
/bin/date
/bin/false
EOS
end
let(:helm_install_command) do
<<~EOS.squish
helm upgrade app-name chart-name
--install
--atomic
--cleanup-on-fail
--reset-values
--version 1.2.3
--set rbac.create\\=false,rbac.enabled\\=false
--namespace gitlab-managed-apps
-f /data/helm/app-name/config/values.yaml
EOS
end
end
end
context 'when there is no version' do
let(:version) { nil }
it_behaves_like 'helm command generator' do
let(:commands) do
<<~EOS
helm repo add app-name https://repository.example.com
helm repo update
#{helm_install_command}
EOS
end
let(:helm_install_command) do
<<~EOS.squish
helm upgrade app-name chart-name
--install
--atomic
--cleanup-on-fail
--reset-values
--set rbac.create\\=false,rbac.enabled\\=false
--namespace gitlab-managed-apps
-f /data/helm/app-name/config/values.yaml
EOS
end
end
end
it_behaves_like 'helm command' do
let(:command) { install_command }
end
end

View File

@ -0,0 +1,81 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Kubernetes::Helm::V3::PatchCommand do
let(:files) { { 'ca.pem': 'some file content' } }
let(:repository) { 'https://repository.example.com' }
let(:rbac) { false }
let(:version) { '1.2.3' }
subject(:patch_command) do
described_class.new(
name: 'app-name',
chart: 'chart-name',
rbac: rbac,
files: files,
version: version,
repository: repository
)
end
it_behaves_like 'helm command generator' do
let(:commands) do
<<~EOS
helm repo add app-name https://repository.example.com
helm repo update
#{helm_upgrade_comand}
EOS
end
let(:helm_upgrade_comand) do
<<~EOS.squish
helm upgrade app-name chart-name
--reuse-values
--version 1.2.3
--namespace gitlab-managed-apps
-f /data/helm/app-name/config/values.yaml
EOS
end
end
context 'when rbac is true' do
let(:rbac) { true }
it_behaves_like 'helm command generator' do
let(:commands) do
<<~EOS
helm repo add app-name https://repository.example.com
helm repo update
#{helm_upgrade_command}
EOS
end
let(:helm_upgrade_command) do
<<~EOS.squish
helm upgrade app-name chart-name
--reuse-values
--version 1.2.3
--namespace gitlab-managed-apps
-f /data/helm/app-name/config/values.yaml
EOS
end
end
end
context 'when there is no version' do
let(:version) { nil }
it { expect { patch_command }.to raise_error(ArgumentError, 'version is required') }
end
describe '#pod_name' do
subject { patch_command.pod_name }
it { is_expected.to eq 'install-app-name' }
end
it_behaves_like 'helm command' do
let(:command) { patch_command }
end
end

View File

@ -40,7 +40,7 @@ RSpec.describe Clusters::Applications::CertManager do
subject { cert_manager.install_command }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::InstallCommand) }
it 'is initialized with cert_manager arguments' do
expect(subject.name).to eq('certmanager')
@ -90,7 +90,7 @@ RSpec.describe Clusters::Applications::CertManager do
describe '#uninstall_command' do
subject { cert_manager.uninstall_command }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::DeleteCommand) }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::DeleteCommand) }
it 'is initialized with cert_manager arguments' do
expect(subject.name).to eq('certmanager')

View File

@ -25,7 +25,7 @@ RSpec.describe Clusters::Applications::Crossplane do
subject { crossplane.install_command }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::InstallCommand) }
it 'is initialized with crossplane arguments' do
expect(subject.name).to eq('crossplane')

View File

@ -15,7 +15,7 @@ RSpec.describe Clusters::Applications::ElasticStack do
subject { elastic_stack.install_command }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::InstallCommand) }
it 'is initialized with elastic stack arguments' do
expect(subject.name).to eq('elastic-stack')
@ -57,7 +57,7 @@ RSpec.describe Clusters::Applications::ElasticStack do
it 'includes a preinstall script' do
expect(subject.preinstall).not_to be_empty
expect(subject.preinstall.first).to include("delete")
expect(subject.preinstall.first).to include("helm uninstall")
end
end
@ -69,7 +69,7 @@ RSpec.describe Clusters::Applications::ElasticStack do
it 'includes a preinstall script' do
expect(subject.preinstall).not_to be_empty
expect(subject.preinstall.first).to include("delete")
expect(subject.preinstall.first).to include("helm uninstall")
end
end
@ -123,7 +123,7 @@ RSpec.describe Clusters::Applications::ElasticStack do
subject { elastic_stack.uninstall_command }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::DeleteCommand) }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::DeleteCommand) }
it 'is initialized with elastic stack arguments' do
expect(subject.name).to eq('elastic-stack')

View File

@ -21,7 +21,7 @@ RSpec.describe Clusters::Applications::Fluentd do
describe '#install_command' do
subject { fluentd.install_command }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::InstallCommand) }
it 'is initialized with fluentd arguments' do
expect(subject.name).to eq('fluentd')

View File

@ -56,7 +56,7 @@ RSpec.describe Clusters::Applications::Helm do
subject { application.issue_client_cert }
it 'returns a new cert' do
is_expected.to be_kind_of(Gitlab::Kubernetes::Helm::Certificate)
is_expected.to be_kind_of(Gitlab::Kubernetes::Helm::V2::Certificate)
expect(subject.cert_string).not_to eq(application.ca_cert)
expect(subject.key_string).not_to eq(application.ca_key)
end
@ -67,7 +67,7 @@ RSpec.describe Clusters::Applications::Helm do
subject { helm.install_command }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InitCommand) }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V2::InitCommand) }
it 'is initialized with 1 arguments' do
expect(subject.name).to eq('helm')
@ -104,7 +104,7 @@ RSpec.describe Clusters::Applications::Helm do
subject { helm.uninstall_command }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::ResetCommand) }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V2::ResetCommand) }
it 'has name' do
expect(subject.name).to eq('helm')

View File

@ -131,7 +131,7 @@ RSpec.describe Clusters::Applications::Ingress do
describe '#install_command' do
subject { ingress.install_command }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::InstallCommand) }
it 'is initialized with ingress arguments' do
expect(subject.name).to eq('ingress')

View File

@ -52,7 +52,7 @@ RSpec.describe Clusters::Applications::Jupyter do
subject { jupyter.install_command }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::InstallCommand) }
it 'is initialized with 4 arguments' do
expect(subject.name).to eq('jupyter')

View File

@ -119,7 +119,7 @@ RSpec.describe Clusters::Applications::Knative do
shared_examples 'a command' do
it 'is an instance of Helm::InstallCommand' do
expect(subject).to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand)
expect(subject).to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::InstallCommand)
end
it 'is initialized with knative arguments' do
@ -171,7 +171,7 @@ RSpec.describe Clusters::Applications::Knative do
describe '#uninstall_command' do
subject { knative.uninstall_command }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::DeleteCommand) }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::DeleteCommand) }
it "removes knative deployed services before uninstallation" do
2.times do |i|

View File

@ -148,7 +148,7 @@ RSpec.describe Clusters::Applications::Prometheus do
subject { prometheus.install_command }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::InstallCommand) }
it 'is initialized with 3 arguments' do
expect(subject.name).to eq('prometheus')
@ -195,7 +195,7 @@ RSpec.describe Clusters::Applications::Prometheus do
subject { prometheus.uninstall_command }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::DeleteCommand) }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::DeleteCommand) }
it 'has the application name' do
expect(subject.name).to eq('prometheus')
@ -236,7 +236,7 @@ RSpec.describe Clusters::Applications::Prometheus do
let(:prometheus) { build(:clusters_applications_prometheus) }
let(:values) { prometheus.values }
it { is_expected.to be_an_instance_of(::Gitlab::Kubernetes::Helm::PatchCommand) }
it { is_expected.to be_an_instance_of(::Gitlab::Kubernetes::Helm::V3::PatchCommand) }
it 'is initialized with 3 arguments' do
expect(patch_command.name).to eq('prometheus')

View File

@ -27,7 +27,7 @@ RSpec.describe Clusters::Applications::Runner do
subject { gitlab_runner.install_command }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::InstallCommand) }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::InstallCommand) }
it 'is initialized with 4 arguments' do
expect(subject.name).to eq('runner')

View File

@ -540,6 +540,27 @@ RSpec.describe Clusters::Cluster, :use_clean_rails_memory_store_caching do
end
end
end
describe 'helm_major_version can only be 2 or 3' do
using RSpec::Parameterized::TableSyntax
where(:helm_major_version, :expect_valid) do
2 | true
3 | true
4 | false
-1 | false
end
with_them do
let(:cluster) { build(:cluster, helm_major_version: helm_major_version) }
it { is_expected.to eq(expect_valid) }
end
end
end
it 'has default helm_major_version 3' do
expect(create(:cluster).helm_major_version).to eq(3)
end
describe '.ancestor_clusters_for_clusterable' do

View File

@ -189,8 +189,6 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do
closedMergeRequestsUrl
openedIssuesUrl
closedIssuesUrl
mergeRequestsUrl
issuesUrl
})
end
@ -203,9 +201,7 @@ RSpec.describe 'Query.project(fullPath).release(tagName)' do
'mergedMergeRequestsUrl' => project_merge_requests_url(project, merged_url_params),
'closedMergeRequestsUrl' => project_merge_requests_url(project, closed_url_params),
'openedIssuesUrl' => project_issues_url(project, opened_url_params),
'closedIssuesUrl' => project_issues_url(project, closed_url_params),
'mergeRequestsUrl' => project_merge_requests_url(project, opened_url_params),
'issuesUrl' => project_issues_url(project, opened_url_params)
'closedIssuesUrl' => project_issues_url(project, closed_url_params)
)
end
end

View File

@ -47,8 +47,6 @@ RSpec.describe 'Query.project(fullPath).releases()' do
closedMergeRequestsUrl
openedIssuesUrl
closedIssuesUrl
mergeRequestsUrl
issuesUrl
}
}
}
@ -115,9 +113,7 @@ RSpec.describe 'Query.project(fullPath).releases()' do
'mergedMergeRequestsUrl' => project_merge_requests_url(project, merged_url_params),
'closedMergeRequestsUrl' => project_merge_requests_url(project, closed_url_params),
'openedIssuesUrl' => project_issues_url(project, opened_url_params),
'closedIssuesUrl' => project_issues_url(project, closed_url_params),
'mergeRequestsUrl' => project_merge_requests_url(project, opened_url_params),
'issuesUrl' => project_issues_url(project, opened_url_params)
'closedIssuesUrl' => project_issues_url(project, closed_url_params)
}
)
end

View File

@ -110,22 +110,6 @@ RSpec.describe API::Releases do
expect(json_response.second['commit_path']).to eq("/#{release_1.project.full_path}/-/commit/#{release_1.commit.id}")
expect(json_response.second['tag_path']).to eq("/#{release_1.project.full_path}/-/tags/#{release_1.tag}")
end
it 'returns the merge requests and issues links, with correct query' do
get api("/projects/#{project.id}/releases", maintainer)
links = json_response.first['_links']
release = json_response.first['tag_name']
expected_query = "release_tag=#{release}&scope=all&state=opened"
path_base = "/#{project.namespace.path}/#{project.path}"
mr_uri = URI.parse(links['merge_requests_url'])
issue_uri = URI.parse(links['issues_url'])
expect(mr_uri.path).to eq("#{path_base}/-/merge_requests")
expect(issue_uri.path).to eq("#{path_base}/-/issues")
expect(mr_uri.query).to eq(expected_query)
expect(issue_uri.query).to eq(expected_query)
end
end
it 'returns an upcoming_release status for a future release' do

View File

@ -14,7 +14,7 @@ RSpec.describe Clusters::Applications::UninstallService, '#execute' do
context 'when there are no errors' do
before do
expect(helm_client).to receive(:uninstall).with(kind_of(Gitlab::Kubernetes::Helm::DeleteCommand))
expect(helm_client).to receive(:uninstall).with(kind_of(Gitlab::Kubernetes::Helm::V3::DeleteCommand))
allow(worker_class).to receive(:perform_in).and_return(nil)
end
@ -36,7 +36,7 @@ RSpec.describe Clusters::Applications::UninstallService, '#execute' do
let(:error) { Kubeclient::HttpError.new(500, 'system failure', nil) }
before do
expect(helm_client).to receive(:uninstall).with(kind_of(Gitlab::Kubernetes::Helm::DeleteCommand)).and_raise(error)
expect(helm_client).to receive(:uninstall).with(kind_of(Gitlab::Kubernetes::Helm::V3::DeleteCommand)).and_raise(error)
end
include_examples 'logs kubernetes errors' do
@ -58,7 +58,7 @@ RSpec.describe Clusters::Applications::UninstallService, '#execute' do
let(:error) { StandardError.new('something bad happened') }
before do
expect(helm_client).to receive(:uninstall).with(kind_of(Gitlab::Kubernetes::Helm::DeleteCommand)).and_raise(error)
expect(helm_client).to receive(:uninstall).with(kind_of(Gitlab::Kubernetes::Helm::V3::DeleteCommand)).and_raise(error)
end
include_examples 'logs kubernetes errors' do

View File

@ -15,6 +15,18 @@ RSpec.shared_examples 'helm command generator' do
end
RSpec.shared_examples 'helm command' do
describe 'HELM_VERSION' do
subject { command.class::HELM_VERSION }
it { is_expected.to match(/\d+\.\d+\.\d+/) }
end
describe '#env' do
subject { command.env }
it { is_expected.to be_a Hash }
end
describe '#rbac?' do
subject { command.rbac? }

View File

@ -25,4 +25,21 @@ RSpec.shared_examples 'cluster application core specs' do |application_name|
describe '.association_name' do
it { expect(described_class.association_name).to eq(:"application_#{subject.name}") }
end
describe '#helm_command_module' do
using RSpec::Parameterized::TableSyntax
where(:helm_major_version, :expected_helm_command_module) do
2 | Gitlab::Kubernetes::Helm::V2
3 | Gitlab::Kubernetes::Helm::V3
end
with_them do
subject { described_class.new(cluster: cluster).helm_command_module }
let(:cluster) { build(:cluster, helm_major_version: helm_major_version)}
it { is_expected.to eq(expected_helm_command_module) }
end
end
end

View File

@ -6,7 +6,7 @@ RSpec.shared_examples 'cluster application helm specs' do |application_name|
describe '#uninstall_command' do
subject { application.uninstall_command }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::DeleteCommand) }
it { is_expected.to be_an_instance_of(Gitlab::Kubernetes::Helm::V3::DeleteCommand) }
it 'has files' do
expect(subject.files).to eq(application.files)