Skip to content
代码片段 群组 项目
未验证 提交 37a97aaf 编辑于 作者: Andrejs Cunskis's avatar Andrejs Cunskis 提交者: GitLab
浏览文件

Refactor deployment configurations as separate subcommands

Extract timeout arg and remove extra admin cred methods
上级 bf55d037
No related branches found
No related tags found
无相关合并请求
显示
455 个添加349 个删除
......@@ -51,7 +51,14 @@ workflow:
- source scripts/utils.sh
- source scripts/rspec_helpers.sh
- cd qa && bundle install
- bundle exec cng create deployment --gitlab-domain "${GITLAB_DOMAIN}" --ci --with-cluster ${EXTRA_DEPLOY_VALUES}
- |
bundle exec cng create deployment kind \
--gitlab-domain "${GITLAB_DOMAIN}" \
--timeout 5m \
--admin-password "${GITLAB_ADMIN_PASSWORD}" \
--admin-token "${GITLAB_QA_ADMIN_ACCESS_TOKEN}" \
--ci \
${EXTRA_DEPLOY_VALUES}
script:
- export QA_COMMAND="bundle exec bin/qa ${QA_SCENARIO:=Test::Instance::All} $QA_GITLAB_URL -- --force-color --order random --format documentation"
- echo "Running - '$QA_COMMAND'"
......
# frozen_string_literal: true
require_relative "subcommands/deployment"
module Gitlab
module Cng
module Commands
# Create command composed of subcommands that create various resources needed for CNG deployment
#
class Create < Command
# @return [Array] configurations that are used for kind cluster deployments
KIND_CLUSTER_CONFIGURATIONS = %w[kind].freeze
desc "cluster", "Create kind cluster for local deployments"
option :name,
desc: "Cluster name",
......@@ -24,52 +23,20 @@ class Create < Command
desc: "Custom docker hostname if remote docker instance is used, like docker-in-docker",
type: :string,
aliases: "-d"
option :host_http_port,
desc: "Extra port mapping for Gitlab HTTP port",
type: :numeric,
default: 80
option :host_ssh_port,
desc: "Extra port mapping for Gitlab ssh port",
type: :numeric,
default: 22
def cluster
Kind::Cluster.new(**symbolized_options).create
end
desc "deployment [NAME]", "Create CNG deployment from official GitLab Helm chart"
long_desc <<~LONGDESC
This command installs a GitLab chart archive and performs all additional pre-install and post-install setup.
Argument NAME is helm install name and defaults to "gitlab".
Deployment has several optional environment variables it can read before performing chart install:
QA_EE_LICENSE|EE_LICENSE - gitlab test license, if present, will be added to deployment,
LONGDESC
option :configuration,
desc: "Deployment configuration",
default: "kind",
type: :string,
aliases: "-c",
enum: ["kind"]
option :namespace,
desc: "Deployment namespace",
default: "gitlab",
type: :string,
aliases: "-n"
option :set,
desc: "Optional helm chart values (can specify multiple or separate values with commas: key1=val1,key2=val2)",
type: :string,
repeatable: true
option :ci,
desc: "Use CI specific configuration",
default: false,
type: :boolean
option :gitlab_domain,
desc: "Domain for deployed app. Defaults to (your host IP).nip.io",
type: :string
option :with_cluster,
desc: "Create kind cluster for local deployments. \
Only valid for configurations designed to run against local kind cluster",
type: :boolean
def deployment(name = "gitlab")
if options[:with_cluster] && KIND_CLUSTER_CONFIGURATIONS.include?(options[:configuration])
invoke :cluster, [], ci: options[:ci]
end
Deployment::Installation
.new(name, **symbolized_options.slice(:configuration, :namespace, :set, :ci, :gitlab_domain))
.create
end
desc "deployment [TYPE]", "Create specific type of deployment"
subcommand "deployment", Subcommands::Deployment
end
end
end
......
# frozen_string_literal: true
require "socket"
module Gitlab
module Cng
module Commands
module Subcommands
# Different deployment type subcommands
#
# Each public method defines a specific deployment type.
# Each deployment method must call {Deployment::Installaton#create} where installation instance is initialized
# with appropriate configuration class which encapsulates optional deployment hooks and specific helm values
#
class Deployment < Command
class << self
# Add common deployment options for each deployment command defined as public method
#
# @param [String] name
# @return [void]
def method_added(name)
option :namespace,
desc: "Deployment namespace",
default: "gitlab",
type: :string,
aliases: "-n"
option :set,
desc: "Optional helm chart values " \
"(can specify multiple or separate values with commas: key1=val1,key2=val2)",
type: :string,
repeatable: true
option :ci,
desc: "Use CI specific configuration",
default: false,
type: :boolean
option :timeout,
desc: "Timeout for deployment",
default: "10m",
type: :string
super(name)
end
end
desc "kind [NAME]", "Create CNG deployment against local kind k8s cluster where NAME is deployment name"
option :create_cluster,
desc: "Create kind cluster for local deployments before creating deployment",
type: :boolean,
default: true
option :docker_hostname,
desc: "Custom docker hostname if remote docker instance is used, like docker-in-docker, " \
"only applicable when --create-cluster is true",
type: :string
option :gitlab_domain,
desc: "Domain for deployed app, default to (your host IP).nip.io",
type: :string
option :admin_password,
desc: "Admin password for gitlab, defaults to password commonly used across development environments",
type: :string,
default: "5iveL!fe"
option :admin_token,
desc: "Admin token for gitlab, defaults to value used in gitlab development seed data",
type: :string,
default: "ypCa3Dzb23o5nvsixwPA"
option :host_http_port,
desc: "Host HTTP port for gitlab",
type: :numeric,
default: 80
option :host_ssh_port,
desc: "Host ssh port for gitlab",
type: :numeric,
default: 22
def kind(name = "gitlab")
if options[:create_cluster]
invoke(Commands::Create, :cluster, [], **symbolized_options.slice(
:docker_hostname, :ci, :host_http_port, :host_ssh_port
))
end
configuration_args = symbolized_options.slice(
:namespace,
:ci,
:gitlab_domain,
:admin_password,
:admin_token,
:host_http_port,
:host_ssh_port
)
installation(name, Cng::Deployment::Configurations::Kind.new(**configuration_args)).create
end
private
# Installation instance
#
# @param [String] name
# @param [Deployment::Configurations::Base] configuration
# @return [Deployment::Installation]
def installation(name, configuration)
Cng::Deployment::Installation.new(
name, configuration: configuration,
**symbolized_options.slice(:namespace, :set, :ci, :gitlab_domain, :timeout)
)
end
# Populate options with default gitlab domain if missing
#
# @return [Hash]
def symbolized_options
@symbolized_options ||= super.tap do |opts|
next unless opts[:gitlab_domain].nil?
# merge default option lazily to not fetch ip_address_list every time class is loaded
opts.merge!({ gitlab_domain: "#{Socket.ip_address_list.detect(&:ipv4_private?).ip_address}.nip.io" })
end
end
end
end
end
end
end
......@@ -20,9 +20,8 @@ module Configurations
class Base
include Helpers::Output
def initialize(namespace, kubeclient, ci, gitlab_domain)
def initialize(namespace:, ci:, gitlab_domain:)
@namespace = namespace
@kubeclient = kubeclient
@ci = ci
@gitlab_domain = gitlab_domain
end
......@@ -81,7 +80,14 @@ def gitlab_url
private
attr_reader :namespace, :kubeclient, :ci, :gitlab_domain
attr_reader :namespace, :ci, :gitlab_domain
# Instance of {Kubectl::Client}
#
# @return [Kubectl::Client]
def kubeclient
@kubeclient ||= Kubectl::Client.new(namespace)
end
end
end
end
......
......@@ -21,6 +21,23 @@ class Kind < Base
fi
SH
def initialize(
namespace:,
ci:,
gitlab_domain:,
admin_password:,
admin_token:,
host_http_port:,
host_ssh_port:
)
super(namespace: namespace, ci: ci, gitlab_domain: gitlab_domain)
@admin_password = admin_password
@admin_token = admin_token
@host_http_port = host_http_port
@host_ssh_port = host_ssh_port
end
# Run pre-deployment setup
#
# @return [void]
......@@ -42,6 +59,12 @@ def run_post_deployment_setup
def values
{
global: {
shell: {
port: host_ssh_port
},
pages: {
port: host_http_port
},
initialRootPassword: {
secret: ADMIN_PASSWORD_SECRET
},
......@@ -60,8 +83,8 @@ def values
service: {
type: "NodePort",
nodePorts: {
"gitlab-shell": 32022,
http: 32080
"gitlab-shell": Cng::Kind::Cluster::SSH_PORT,
http: Cng::Kind::Cluster::HTTP_PORT
}
}
}
......@@ -73,24 +96,12 @@ def values
#
# @return [String]
def gitlab_url
"http://gitlab.#{gitlab_domain}#{ci ? '' : ':32080'}"
@gitlab_url ||= URI("http://gitlab.#{gitlab_domain}:#{host_http_port}").to_s
end
private
# Gitlab initial admin password, defaults to commonly used password across development environments
#
# @return [String]
def admin_password
@admin_password ||= ENV["GITLAB_ADMIN_PASSWORD"] || "5iveL!fe"
end
# Gitlab admin user personal access token, defaults to value used in development seed data
#
# @return [String]
def admin_token
@admin_token ||= ENV["GITLAB_ADMIN_ACCESS_TOKEN"] || "ypCa3Dzb23o5nvsixwPA"
end
attr_reader :admin_password, :admin_token, :host_http_port, :host_ssh_port
# Token seed script for root user
#
......
......@@ -47,22 +47,22 @@ def common_values(domain)
# @return [Hash]
def component_ci_versions
{
"gitaly.image.repository" => "#{IMAGE_REPOSITORY}/gitaly",
"gitaly.image.tag" => gitaly_version,
"gitlab-shell.image.repository" => "#{IMAGE_REPOSITORY}/gitlab-shell",
"gitlab-shell.image.tag" => "v#{gitlab_shell_version}",
"migrations.image.repository" => "#{IMAGE_REPOSITORY}/gitlab-toolbox-ee",
"migrations.image.tag" => commit_sha,
"toolbox.image.repository" => "#{IMAGE_REPOSITORY}/gitlab-toolbox-ee",
"toolbox.image.tag" => commit_sha,
"sidekiq.annotations.commit" => commit_short_sha,
"sidekiq.image.repository" => "#{IMAGE_REPOSITORY}/gitlab-sidekiq-ee",
"sidekiq.image.tag" => commit_sha,
"webservice.annotations.commit" => commit_short_sha,
"webservice.image.repository" => "#{IMAGE_REPOSITORY}/gitlab-webservice-ee",
"webservice.image.tag" => commit_sha,
"webservice.workhorse.image" => "#{IMAGE_REPOSITORY}/gitlab-workhorse-ee",
"webservice.workhorse.tag" => commit_sha
"gitlab.gitaly.image.repository" => "#{IMAGE_REPOSITORY}/gitaly",
"gitlab.gitaly.image.tag" => gitaly_version,
"gitlab.gitlab-shell.image.repository" => "#{IMAGE_REPOSITORY}/gitlab-shell",
"gitlab.gitlab-shell.image.tag" => "v#{gitlab_shell_version}",
"gitlab.migrations.image.repository" => "#{IMAGE_REPOSITORY}/gitlab-toolbox-ee",
"gitlab.migrations.image.tag" => commit_sha,
"gitlab.toolbox.image.repository" => "#{IMAGE_REPOSITORY}/gitlab-toolbox-ee",
"gitlab.toolbox.image.tag" => commit_sha,
"gitlab.sidekiq.annotations.commit" => commit_short_sha,
"gitlab.sidekiq.image.repository" => "#{IMAGE_REPOSITORY}/gitlab-sidekiq-ee",
"gitlab.sidekiq.image.tag" => commit_sha,
"gitlab.webservice.annotations.commit" => commit_short_sha,
"gitlab.webservice.image.repository" => "#{IMAGE_REPOSITORY}/gitlab-webservice-ee",
"gitlab.webservice.image.tag" => commit_sha,
"gitlab.webservice.workhorse.image" => "#{IMAGE_REPOSITORY}/gitlab-workhorse-ee",
"gitlab.webservice.workhorse.tag" => commit_sha
}
end
end
......
# frozen_string_literal: true
require "socket"
require "yaml"
require "active_support/core_ext/hash"
......@@ -15,12 +14,13 @@ class Installation
LICENSE_SECRET = "gitlab-license"
def initialize(name, configuration:, namespace:, ci:, gitlab_domain: nil, set: [])
def initialize(name, configuration:, namespace:, ci:, gitlab_domain:, timeout:, set: [])
@name = name
@configuration = configuration
@namespace = namespace
@ci = ci
@gitlab_domain = gitlab_domain
@timeout = timeout
@set = set
end
......@@ -28,7 +28,7 @@ def initialize(name, configuration:, namespace:, ci:, gitlab_domain: nil, set: [
#
# @return [void]
def create
log("Creating CNG deployment '#{name}' using '#{configuration}' configuration", :info, bright: true)
log("Creating CNG deployment '#{name}'", :info, bright: true)
run_pre_deploy_setup
run_deploy
run_post_deploy_setup
......@@ -36,9 +36,16 @@ def create
exit(1)
end
# Specific component version values used in CI
#
# @return [String]
def component_version_values
@component_version_values ||= DefaultValues.component_ci_versions.map { |k, v| "#{k}=#{v}" }
end
private
attr_reader :name, :configuration, :namespace, :ci, :set
attr_reader :name, :configuration, :namespace, :ci, :set, :gitlab_domain, :timeout
alias_method :cli_values, :set
# Kubectl client instance
......@@ -48,25 +55,6 @@ def kubeclient
@kubeclient ||= Kubectl::Client.new(namespace)
end
# Gitlab app domain
#
# @return [String]
def gitlab_domain
@gitlab_domain ||= "#{Socket.ip_address_list.detect(&:ipv4_private?).ip_address}.nip.io"
end
# Configuration class instance
#
# @return [Configuration::Base]
def config_instance
@config_instance ||= Configurations.const_get(configuration.capitalize, false).new(
namespace,
kubeclient,
ci,
gitlab_domain
)
end
# Gitlab license
#
# @return [String]
......@@ -105,7 +93,7 @@ def run_pre_deploy_setup
create_namespace
create_license
config_instance.run_pre_deployment_setup
configuration.run_pre_deployment_setup
end
end
......@@ -117,26 +105,26 @@ def run_deploy
"upgrade",
"--install", name, "gitlab/gitlab",
"--namespace", namespace,
"--timeout", "5m",
"--timeout", timeout,
"--wait"
]
cmd.push(*DefaultValues.component_ci_versions.flat_map { |k, v| ["--set", "gitlab.#{k}=#{v}"] }) if ci
cmd.push(*cli_values.flat_map { |v| ["--set", v] })
cmd.push(*component_version_values.flat_map { |v| ["--set", v] }) if ci
cmd.push("--set", cli_values.join(",")) unless cli_values.empty?
cmd.push("--values", "-")
values = DefaultValues.common_values(gitlab_domain)
.deep_merge(license_values)
.deep_merge(config_instance.values)
.deep_merge(configuration.values)
.deep_stringify_keys
Helpers::Spinner.spin("running helm deployment") { puts run_helm_cmd(cmd, values.to_yaml) }
log("Deployment successfull and app is available via: #{config_instance.gitlab_url}", :success, bright: true)
log("Deployment successful and app is available via: #{configuration.gitlab_url}", :success, bright: true)
end
# Execute post-deployment setup
#
# @return [void]
def run_post_deploy_setup
Helpers::Spinner.spin("running post-deployment setup") { config_instance.run_post_deployment_setup }
Helpers::Spinner.spin("running post-deployment setup") { configuration.run_post_deployment_setup }
end
# Add helm chart repo
......
# frozen_string_literal: true
require "uri"
require_relative "configs"
require "tmpdir"
require "erb"
module Gitlab
module Cng
......@@ -12,11 +12,15 @@ module Kind
class Cluster
include Helpers::Output
include Helpers::Shell
include Configs
def initialize(ci:, name:, docker_hostname: nil)
HTTP_PORT = 32080
SSH_PORT = 32022
def initialize(ci:, name:, host_http_port:, host_ssh_port:, docker_hostname: nil)
@ci = ci
@name = name
@host_http_port = host_http_port
@host_ssh_port = host_ssh_port
@docker_hostname = ci ? docker_hostname || "docker" : docker_hostname
end
......@@ -34,14 +38,7 @@ def create
private
attr_reader :ci, :name, :docker_hostname
# Check if cluster exists
#
# @return [Boolean]
def cluster_exists?
execute_shell(%w[kind get clusters]).include?(name)
end
attr_reader :ci, :name, :docker_hostname, :host_http_port, :host_ssh_port
# Create kind cluster
#
......@@ -54,7 +51,7 @@ def create_cluster
"cluster",
"--name", name,
"--wait", "30s",
"--config", ci ? ci_config(docker_hostname) : default_config(docker_hostname)
"--config", ci ? ci_config : default_config
])
end
end
......@@ -75,6 +72,91 @@ def update_server_url
execute_shell(%W[kubectl config set-cluster #{cluster_name} --server=#{uri}])
end
end
# Check if cluster exists
#
# @return [Boolean]
def cluster_exists?
execute_shell(%w[kind get clusters]).include?(name)
end
# Create temporary kind config file
#
# @param [String] config_yml
# @return [String]
def tmp_config_file(config_yml)
File.join(Dir.tmpdir, "kind-config.yml").tap do |path|
File.write(path, config_yml)
end
end
# Temporary ci specific kind configuration file
#
# @return [String] file path
def ci_config
config_yml = <<~YML
apiVersion: kind.x-k8s.io/v1alpha4
kind: Cluster
networking:
apiServerAddress: "0.0.0.0"
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
- |
kind: ClusterConfiguration
apiServer:
certSANs:
- "#{docker_hostname}"
extraPortMappings:
- containerPort: #{HTTP_PORT}
hostPort: #{host_http_port}
listenAddress: "0.0.0.0"
- containerPort: #{SSH_PORT}
hostPort: #{host_ssh_port}
listenAddress: "0.0.0.0"
YML
tmp_config_file(config_yml)
end
# Temporary kind configuration file
#
# @return [String] file path
def default_config
template = ERB.new(<<~YML, trim_mode: "-")
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
<% if docker_hostname -%>
- |
kind: ClusterConfiguration
apiServer:
certSANs:
- "<%= docker_hostname %>"
<% end -%>
extraPortMappings:
- containerPort: #{HTTP_PORT}
hostPort: #{host_http_port}
listenAddress: "0.0.0.0"
- containerPort: #{SSH_PORT}
hostPort: #{host_ssh_port}
listenAddress: "0.0.0.0"
YML
tmp_config_file(template.result(binding))
end
end
end
end
......
# frozen_string_literal: true
require "tmpdir"
require "erb"
module Gitlab
module Cng
module Kind
# Kind configuration file templates
#
module Configs
# Temporary ci specific kind configuration file
#
# @param [String] docker_hostname
# @return [String] file path
def ci_config(docker_hostname)
config_yml = <<~YML
apiVersion: kind.x-k8s.io/v1alpha4
kind: Cluster
networking:
apiServerAddress: "0.0.0.0"
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
- |
kind: ClusterConfiguration
apiServer:
certSANs:
- "#{docker_hostname}"
extraPortMappings:
# containerPort below must match the values file:
# nginx-ingress.controller.service.nodePorts.http
- containerPort: 32080
hostPort: 80
listenAddress: "0.0.0.0"
# containerPort below must match the values file:
# nginx-ingress.controller.service.nodePorts.gitlab-shell
- containerPort: 32022
hostPort: 22
listenAddress: "0.0.0.0"
YML
tmp_config_file(config_yml)
end
# Temporary kind configuration file
#
# @param [String, nil] docker_hostname
# @return [String] file path
def default_config(docker_hostname)
template = ERB.new(<<~YML, trim_mode: "-")
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
kubeadmConfigPatches:
- |
kind: InitConfiguration
nodeRegistration:
kubeletExtraArgs:
node-labels: "ingress-ready=true"
<% if docker_hostname -%>
- |
kind: ClusterConfiguration
apiServer:
certSANs:
- "<%= docker_hostname %>"
<% end -%>
extraPortMappings:
# containerPort below must match the values file:
# nginx-ingress.controller.service.nodePorts.http
- containerPort: 32080
hostPort: 32080
listenAddress: "0.0.0.0"
# containerPort below must match the values file:
# nginx-ingress.controller.service.nodePorts.ssh
- containerPort: 32022
hostPort: 32022
listenAddress: "0.0.0.0"
YML
tmp_config_file(template.result(binding))
end
# Create temporary kind config file
#
# @param [String] config_yml
# @return [String]
def tmp_config_file(config_yml)
File.join(Dir.tmpdir, "kind-config.yml").tap do |path|
File.write(path, config_yml)
end
end
end
end
end
end
......@@ -3,17 +3,17 @@
RSpec.describe Gitlab::Cng::CLI do
shared_examples "command with help" do |args, help_output|
it "shows help" do
expect { cli.invoke(*args) }.to output(/#{help_output}/).to_stdout
expect { cli.start(args) }.to output(/#{help_output}/).to_stdout
end
end
subject(:cli) { described_class.new }
subject(:cli) { described_class }
describe "version command" do
it_behaves_like "command with help", [:help, ["version"]], /Print cng orchestrator version/
it_behaves_like "command with help", %w[help version], /Print cng orchestrator version/
it "executes version command" do
expect { cli.invoke(:version) }.to output(/#{Gitlab::Cng::VERSION}/o).to_stdout
expect { cli.start(%w[version]) }.to output(/#{Gitlab::Cng::VERSION}/o).to_stdout
end
end
......@@ -25,10 +25,10 @@
allow(command_instance).to receive(:doctor)
end
it_behaves_like "command with help", [:help, ["doctor"]], /Validate presence of all required system dependencies/
it_behaves_like "command with help", %w[help doctor], /Validate presence of all required system dependencies/
it "invokes doctor command" do
cli.invoke(:doctor)
cli.start(%w[doctor])
expect(command_instance).to have_received(:doctor)
end
......@@ -42,12 +42,13 @@
allow(Gitlab::Cng::Kind::Cluster).to receive(:new).and_return(cluster_instance)
end
it_behaves_like "command with help", [:create, %w[help cluster]], /Create kind cluster for local deployments/
it_behaves_like "command with help", %w[create help cluster], /Create kind cluster for local deployments/
it "invokes cluster create command" do
cli.invoke(:create, %w[cluster])
cli.start(%w[create cluster])
expect(Gitlab::Cng::Kind::Cluster).to have_received(:new).with(ci: false, name: "gitlab")
expect(Gitlab::Cng::Kind::Cluster).to have_received(:new)
.with(ci: false, name: "gitlab", host_http_port: 80, host_ssh_port: 22)
expect(cluster_instance).to have_received(:create)
end
end
......@@ -55,23 +56,22 @@
context "with deployment subcommand" do
let(:installation_instance) { instance_double(Gitlab::Cng::Deployment::Installation, create: nil) }
before do
allow(Gitlab::Cng::Deployment::Installation).to receive(:new).and_return(installation_instance)
end
context "with kind deployment" do
let(:configuration_instance) { instance_double(Gitlab::Cng::Deployment::Configurations::Kind) }
it_behaves_like "command with help", [:create, %w[help deployment]],
/This command installs a GitLab chart archive/
before do
allow(Gitlab::Cng::Deployment::Installation).to receive(:new).and_return(installation_instance)
allow(Gitlab::Cng::Deployment::Configurations::Kind).to receive(:new)
end
it "invokes cluster create command" do
cli.invoke(:create, %w[deployment])
expect(Gitlab::Cng::Deployment::Installation).to have_received(:new).with(
"gitlab",
configuration: "kind",
namespace: "gitlab",
ci: false
)
expect(installation_instance).to have_received(:create)
it_behaves_like "command with help", %w[create deployment help kind],
/Create CNG deployment against local kind k8s cluster/
it "invokes kind deployment" do
cli.start(%w[create deployment kind --gitlab-domain 127.0.0.1.nip.io --skip-create-cluster])
expect(installation_instance).to have_received(:create)
end
end
end
end
......
......@@ -26,58 +26,10 @@
expect(kind_cluster).to have_received(:create)
expect(Gitlab::Cng::Kind::Cluster).to have_received(:new).with({
ci: true,
name: "test-cluster"
name: "test-cluster",
host_http_port: 80,
host_ssh_port: 22
})
end
end
describe "deployment command" do
let(:command_name) { "deployment" }
let(:deployment_install) { instance_double(Gitlab::Cng::Deployment::Installation, create: nil) }
before do
allow(Gitlab::Cng::Deployment::Installation).to receive(:new).and_return(deployment_install)
end
it "defines deployment command" do
expect_command_to_include_attributes(command_name, {
description: "Create CNG deployment from official GitLab Helm chart",
name: command_name,
usage: "#{command_name} [NAME]"
})
end
it "invokes kind cluster creation with correct arguments" do
invoke_command(command_name, [], {
configuration: "kind",
ci: true,
namespace: "gitlab",
gitlab_domain: "127.0.0.1.nip.io"
})
expect(deployment_install).to have_received(:create)
expect(Gitlab::Cng::Deployment::Installation).to have_received(:new).with(
"gitlab",
configuration: "kind",
ci: true,
namespace: "gitlab",
gitlab_domain: "127.0.0.1.nip.io"
)
end
it "invokes kind cluster creation when --with-cluster argument is passed" do
invoke_command(command_name, [], {
configuration: "kind",
ci: true,
with_cluster: true
})
expect(kind_cluster).to have_received(:create)
expect(Gitlab::Cng::Kind::Cluster).to have_received(:new).with({
ci: true,
name: "gitlab"
})
expect(deployment_install).to have_received(:create)
end
end
end
# frozen_string_literal: true
RSpec.describe Gitlab::Cng::Commands::Subcommands::Deployment do
include_context "with command testing helper"
describe "kind deployment command" do
let(:command_name) { "kind" }
let(:installation_instance) { instance_double(Gitlab::Cng::Deployment::Installation, create: nil) }
let(:configuration_instance) { instance_double(Gitlab::Cng::Deployment::Configurations::Kind) }
let(:cluster_instance) { instance_double(Gitlab::Cng::Kind::Cluster, create: nil) }
let(:ip) { instance_double(Addrinfo, ipv4_private?: true, ip_address: "127.0.0.1") }
before do
allow(Gitlab::Cng::Deployment::Installation).to receive(:new).and_return(installation_instance)
allow(Gitlab::Cng::Deployment::Configurations::Kind).to receive(:new).and_return(configuration_instance)
allow(Gitlab::Cng::Kind::Cluster).to receive(:new).and_return(cluster_instance)
allow(Socket).to receive(:ip_address_list).and_return([ip])
end
it "defines kind deployment" do
expect_command_to_include_attributes(command_name, {
description: "Create CNG deployment against local kind k8s cluster where NAME is deployment name",
name: command_name,
usage: "#{command_name} [NAME]"
})
end
it "invokes kind cluster creation with correct arguments" do
invoke_command(command_name, [], {
namespace: "gitlab",
ci: false
})
expect(Gitlab::Cng::Deployment::Installation).to have_received(:new).with(
"gitlab",
configuration: configuration_instance,
namespace: "gitlab",
ci: false,
gitlab_domain: "127.0.0.1.nip.io",
timeout: "10m"
)
expect(Gitlab::Cng::Deployment::Configurations::Kind).to have_received(:new).with(
namespace: "gitlab",
ci: false,
gitlab_domain: "127.0.0.1.nip.io",
admin_password: "5iveL!fe",
admin_token: "ypCa3Dzb23o5nvsixwPA",
host_http_port: 80,
host_ssh_port: 22
)
expect(installation_instance).to have_received(:create)
end
it "create kind cluster before deployment" do
invoke_command(command_name, [], {
namespace: "gitlab",
ci: true
})
expect(Gitlab::Cng::Kind::Cluster).to have_received(:new)
.with(name: "gitlab", ci: true, host_http_port: 80, host_ssh_port: 22)
expect(cluster_instance).to have_received(:create)
end
end
end
......@@ -4,7 +4,11 @@
subject(:configuration) { Class.new(described_class) }
let(:config) do
configuration.new("gitlab", Gitlab::Cng::Kubectl::Client.new("gitlab"), false, "domain")
configuration.new(
namespace: "gitlab",
ci: false,
gitlab_domain: "domain"
)
end
it "returns empty values by default" do
......
# frozen_string_literal: true
RSpec.describe Gitlab::Cng::Deployment::Configurations::Kind do
subject(:configuration) { described_class.new("gitlab", kubeclient, true, "127.0.0.1.nip.io") }
subject(:configuration) do
described_class.new(
namespace: "gitlab",
ci: true,
gitlab_domain: "127.0.0.1.nip.io",
admin_password: "password",
admin_token: "token",
host_http_port: 80,
host_ssh_port: 22
)
end
let(:kubeclient) { instance_double(Gitlab::Cng::Kubectl::Client, create_resource: "", execute: "") }
let(:env) do
{
"GITLAB_ADMIN_PASSWORD" => "password",
"GITLAB_ADMIN_ACCESS_TOKEN" => "token"
}
end
around do |example|
ClimateControl.modify(env) { example.run }
before do
allow(Gitlab::Cng::Kubectl::Client).to receive(:new).and_return(kubeclient)
end
it "runs pre-deployment setup", :aggregate_failures do
......@@ -69,6 +72,12 @@
it "returns configuration specific values" do
expect(configuration.values).to eq({
global: {
shell: {
port: 22
},
pages: {
port: 80
},
initialRootPassword: {
secret: "gitlab-initial-root-password"
},
......
......@@ -4,16 +4,17 @@
subject(:installation) do
described_class.new(
"gitlab",
configuration: "kind",
configuration: configuration,
namespace: "gitlab",
ci: ci
ci: ci,
gitlab_domain: gitlab_domain,
timeout: "10m"
)
end
let(:stdin) { StringIO.new }
let(:config_values) { { configuration_specific: true } }
let(:ip) { instance_double(Addrinfo, ipv4_private?: true, ip_address: "127.0.0.1") }
let(:gitlab_domain) { "#{ip.ip_address}.nip.io" }
let(:kubeclient) do
instance_double(Gitlab::Cng::Kubectl::Client, create_namespace: "", create_resource: "", execute: "")
......@@ -25,7 +26,7 @@
run_pre_deployment_setup: nil,
run_post_deployment_setup: nil,
values: config_values,
gitlab_url: "http://gitlab.#{ip.ip_address}.nip.io"
gitlab_url: "http://gitlab.#{gitlab_domain}"
)
end
......@@ -42,7 +43,7 @@
{
global: {
hosts: {
domain: "#{ip.ip_address}.nip.io",
domain: gitlab_domain,
https: false
},
ingress: {
......@@ -77,7 +78,6 @@
allow(Gitlab::Cng::Deployment::Configurations::Kind).to receive(:new).and_return(configuration)
allow(installation).to receive(:execute_shell)
allow(Socket).to receive(:ip_address_list).and_return([ip])
end
around do |example|
......@@ -88,14 +88,8 @@
let(:ci) { false }
it "runs setup and helm deployment" do
expect { installation.create }.to output(/Creating CNG deployment 'gitlab' using 'kind' configuration/).to_stdout
expect { installation.create }.to output(/Creating CNG deployment 'gitlab'/).to_stdout
expect(Gitlab::Cng::Deployment::Configurations::Kind).to have_received(:new).with(
"gitlab",
kubeclient,
ci,
"#{ip.ip_address}.nip.io"
)
expect(installation).to have_received(:execute_shell).with(
%w[helm repo add gitlab https://charts.gitlab.io],
stdin_data: nil
......@@ -113,7 +107,7 @@
helm upgrade
--install gitlab gitlab/gitlab
--namespace gitlab
--timeout 5m
--timeout 10m
--wait
--values -
],
......@@ -133,14 +127,14 @@
let(:ci) { true }
it "runs helm install with correctly merged values and component versions" do
expect { installation.create }.to output(/Creating CNG deployment 'gitlab' using 'kind' configuration/).to_stdout
expect { installation.create }.to output(/Creating CNG deployment 'gitlab'/).to_stdout
expect(installation).to have_received(:execute_shell).with(
%W[
helm upgrade
--install gitlab gitlab/gitlab
--namespace gitlab
--timeout 5m
--timeout 10m
--wait
--set gitlab.gitaly.image.repository=registry.gitlab.com/gitlab-org/build/cng-mirror/gitaly
--set gitlab.gitaly.image.tag=7aa06a578d76bdc294ee8e9acb4f063e7d9f1d5f
......
# frozen_string_literal: true
RSpec.describe Gitlab::Cng::Kind::Cluster do
subject(:cluster) { described_class.new(ci: ci, name: name, docker_hostname: docker_hostname) }
subject(:cluster) do
described_class.new(
ci: ci,
name: name,
docker_hostname: docker_hostname,
host_http_port: 32080,
host_ssh_port: 32022
)
end
let(:ci) { false }
let(:name) { "gitlab" }
......@@ -51,15 +59,11 @@
certSANs:
- "#{docker_hostname}"
extraPortMappings:
# containerPort below must match the values file:
# nginx-ingress.controller.service.nodePorts.http
- containerPort: 32080
hostPort: 80
hostPort: 32080
listenAddress: "0.0.0.0"
# containerPort below must match the values file:
# nginx-ingress.controller.service.nodePorts.gitlab-shell
- containerPort: 32022
hostPort: 22
hostPort: 32022
listenAddress: "0.0.0.0"
YML
end
......@@ -97,16 +101,12 @@
kubeletExtraArgs:
node-labels: "ingress-ready=true"
extraPortMappings:
# containerPort below must match the values file:
# nginx-ingress.controller.service.nodePorts.http
- containerPort: 32080
hostPort: 32080
listenAddress: "0.0.0.0"
# containerPort below must match the values file:
# nginx-ingress.controller.service.nodePorts.ssh
- containerPort: 32022
hostPort: 32022
listenAddress: "0.0.0.0"
- containerPort: 32080
hostPort: 32080
listenAddress: "0.0.0.0"
- containerPort: 32022
hostPort: 32022
listenAddress: "0.0.0.0"
YML
end
......
......@@ -29,15 +29,15 @@ function save_install_logs() {
log_with_header "Events of namespace ${NAMESPACE}"
kubectl get events --output wide --namespace ${NAMESPACE}
for pod in $(kubectl get pods --no-headers --namespace ${NAMESPACE} --output jsonpath={.items[*].metadata.name}); do
for pod in $(kubectl get pods --no-headers --namespace ${NAMESPACE} --output 'jsonpath={.items[*].metadata.name}'); do
log_with_header "Description of pod ${pod}"
kubectl describe pod ${pod} --namespace ${NAMESPACE}
for container in $(kubectl get pods ${pod} --no-headers --namespace ${NAMESPACE} --output jsonpath={.spec.initContainers[*].name}); do
for container in $(kubectl get pods ${pod} --no-headers --namespace ${NAMESPACE} --output 'jsonpath={.spec.initContainers[*].name}'); do
kubectl logs ${pod} --namespace ${NAMESPACE} --container ${container} >"${container}.log"
done
for container in $(kubectl get pods ${pod} --no-headers --namespace ${NAMESPACE} --output jsonpath={.spec.containers[*].name}); do
for container in $(kubectl get pods ${pod} --no-headers --namespace ${NAMESPACE} --output 'jsonpath={.spec.containers[*].name}'); do
kubectl logs ${pod} --namespace ${NAMESPACE} --container ${container} >"${container}.log"
done
done
......
0% 加载中 .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册