hippo-cli 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 432cb14031538080436b685d9bffb44890296eb4ee2e001f47112d0a60cf10ae
4
+ data.tar.gz: 155f1cfd1ef594b9ad3e863bb40c3ca89df2bbbb77a5b3657ea6abd4dd324d39
5
+ SHA512:
6
+ metadata.gz: dbf149c3462eaf4b7b2fcba7afe450d3a60c472a671ba117a991db9db2ae7b94d3f72c2e2f708cc2d316f1dcadb00e5a60e637bdf3d9dc27af724e5f7595da33
7
+ data.tar.gz: ce1c8ab412478c7d4dc13a3d975d2734c2ad60a75dfd43e60b95fec1c9493a232036056977e395ee6da021a871fef51c7827419eb11395e6c296475a537601ce
checksums.yaml.gz.sig ADDED
@@ -0,0 +1,3 @@
1
+ p3�<x�H񏦀y�::��Ej�>��*@�x '=�����WeW�n~�T�<�t�s�� 䯔�c��[����S�^|�7�~s@��X���`���,D��W��>�n�
2
+ 4m�-S�nFr��F�]<���u��`R���y�$�� �D�q�K��}�aY��%D��3k�|�3}�~���*���ѐC%�K<��<cq��d��j� RFB�T�J
3
+ %|�2�ɰ�� E��E�-g,ں ��B4���s��
data/bin/hippo ADDED
@@ -0,0 +1,36 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ $LOAD_PATH.unshift(File.expand_path('../lib', __dir__))
5
+
6
+ require 'hippo'
7
+ require 'hippo/error'
8
+ require 'hippo/version'
9
+ require 'swamp/cli'
10
+
11
+ COMMANDS_WITHOUT_STAGE = %w[help init].freeze
12
+
13
+ begin
14
+ cli = Swamp::CLI.new(:hippo, version: Hippo::VERSION)
15
+ cli.load_from_directory(File.expand_path('../cli', __dir__))
16
+
17
+ args = ARGV.dup
18
+ stage = args.shift
19
+ command = args.shift
20
+
21
+ if COMMANDS_WITHOUT_STAGE.include?(stage) || (command.nil? && stage.nil?)
22
+ cli.dispatch([stage || 'help'])
23
+ elsif command.nil?
24
+ puts 'usage: hippo [STAGE] [COMMAND] {options}'
25
+ puts '(Be sure to specify the stage name before the command)'
26
+ exit 2
27
+ else
28
+ CURRENT_STAGE = stage
29
+ cli.dispatch([command] + args)
30
+ end
31
+ rescue Swamp::Error, Hippo::Error => e
32
+ warn "\e[31mError: #{e.message}\e[0m"
33
+ exit 2
34
+ rescue Interrupt
35
+ exit 3
36
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ command :'apply-config' do
4
+ desc 'Apply configuration'
5
+
6
+ option '-h', '--hippofile [RECIPE]', 'The path to the Hippofile (defaults: ./Hippofile)' do |value, options|
7
+ options[:hippofile] = value.to_s
8
+ end
9
+
10
+ action do |context|
11
+ require 'hippo/cli_steps'
12
+ steps = Hippo::CLISteps.setup(context)
13
+ steps.apply_namespace
14
+ steps.apply_config
15
+ steps.apply_secrets
16
+ end
17
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ command :'apply-services' do
4
+ desc 'Apply service configuration'
5
+
6
+ option '-h', '--hippofile [RECIPE]', 'The path to the Hippofile (defaults: ./Hippofile)' do |value, options|
7
+ options[:hippofile] = value.to_s
8
+ end
9
+
10
+ action do |context|
11
+ require 'hippo/cli_steps'
12
+ steps = Hippo::CLISteps.setup(context)
13
+ steps.apply_services
14
+ end
15
+ end
data/cli/build.rb ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ command :build do
4
+ desc 'Build an image for the given stage'
5
+
6
+ option '-h', '--hippofile [RECIPE]', 'The path to the Hippofile (defaults: ./Hippofile)' do |value, options|
7
+ options[:hippofile] = value.to_s
8
+ end
9
+
10
+ action do |context|
11
+ require 'hippo/cli_steps'
12
+ steps = Hippo::CLISteps.setup(context)
13
+ steps.prepare_repository
14
+ steps.build
15
+ end
16
+ end
data/cli/console.rb ADDED
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ command :console do
4
+ desc 'Open a console based on the configuration'
5
+
6
+ option '-h', '--hippofile [RECIPE]', 'The path to the Hippofile (defaults: ./Hippofile)' do |value, options|
7
+ options[:hippofile] = value.to_s
8
+ end
9
+
10
+ option '-d', '--deployment [NAME]', 'The name of the deployment to use' do |value, options|
11
+ options[:deployment] = value.to_s
12
+ end
13
+
14
+ option '-c', '--command [NAME]', 'The command to run' do |value, options|
15
+ options[:command] = value.to_s
16
+ end
17
+
18
+ action do |context|
19
+ require 'hippo/cli_steps'
20
+ cli = Hippo::CLISteps.setup(context)
21
+
22
+ if cli.recipe.console.nil?
23
+ raise Error, 'No console configuration has been provided in Hippofile'
24
+ end
25
+
26
+ time = Time.now.to_i
27
+ deployment_name = context.options[:deployment] || cli.recipe.console['deployment']
28
+ command = context.options[:command] || cli.recipe.console['command'] || 'bash'
29
+ exec cli.stage.kubectl("exec -it deployment/#{deployment_name} -- #{command}")
30
+ end
31
+ end
data/cli/deploy.rb ADDED
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ command :deploy do
4
+ desc 'Deploy the application to Kubernetes (including image build/push)'
5
+
6
+ option '-h', '--hippofile [RECIPE]', 'The path to the Hippofile (defaults: ./Hippofile)' do |value, options|
7
+ options[:hippofile] = value.to_s
8
+ end
9
+
10
+ option '--no-jobs', 'Do not run the deploy jobs' do |_value, options|
11
+ options[:jobs] = false
12
+ end
13
+
14
+ option '--no-build', 'Do not build the images' do |_value, options|
15
+ options[:build] = false
16
+ end
17
+
18
+ action do |context|
19
+ require 'hippo/cli_steps'
20
+ steps = Hippo::CLISteps.setup(context)
21
+ if context.options[:build] == false
22
+ commit = steps.recipe.repository.commit_for_branch(steps.stage.branch)
23
+ puts 'Not building an image and just hoping one exists for current commit.'
24
+ puts "Using #{commit.objectish} from #{steps.stage.branch}"
25
+ steps.prepare_repository(fetch: false)
26
+ else
27
+ steps.prepare_repository
28
+ steps.build
29
+ steps.publish
30
+ end
31
+
32
+ steps.apply_namespace
33
+ steps.apply_config
34
+ steps.apply_secrets
35
+
36
+ unless context.options[:jobs] == false
37
+ if steps.run_deploy_jobs == false
38
+ raise Hippo::Error, 'Not all jobs completed successfully. Cannot continue with deployment.'
39
+ end
40
+ end
41
+
42
+ steps.apply_services
43
+ steps.deploy
44
+ end
45
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ command :'edit-secret' do
4
+ desc 'Create/edit an encrypted secrets file'
5
+
6
+ option '--create-key', 'Create a new encryption key if missing' do |_value, options|
7
+ options[:create_key] = true
8
+ end
9
+
10
+ action do |context|
11
+ require 'hippo/cli_steps'
12
+ steps = Hippo::CLISteps.setup(context)
13
+
14
+ secret_name = context.args[0]
15
+ raise Hippo::Error, 'You must provide a secret name' if secret_name.nil?
16
+
17
+ require 'hippo/secret_manager'
18
+ manager = Hippo::SecretManager.new(steps.recipe, steps.stage)
19
+ if !manager.key_available? && context.options[:create_key]
20
+ manager.create_key
21
+ elsif !manager.key_available?
22
+ puts "\e[31mNo key has been published for this stage yet. You can create"
23
+ puts "a key automatically by adding --create-key to this command.\e[0m"
24
+ exit 2
25
+ elsif context.options[:create_key]
26
+ puts "\e[31mThe --create-key option can only be provided when a key has not already"
27
+ puts "been generated. Remove the key from the Kubernetes API to regenerate.\e[0m"
28
+ exit 2
29
+ end
30
+
31
+ secret = manager.secret(secret_name)
32
+ if secret.exists?
33
+ secret.edit
34
+ else
35
+ puts "No secret exists at #{secret.path}. Would you like to create one?"
36
+ response = STDIN.gets.strip.downcase.strip
37
+ if %w[y yes please].include?(response)
38
+ secret.create
39
+ secret.edit
40
+ else
41
+ puts 'Not a problem. You can make it later.'
42
+ end
43
+ end
44
+ end
45
+ end
data/cli/help.rb ADDED
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ command :help do
4
+ desc 'Display this help text'
5
+ action do |context|
6
+ puts "\e[35mWelcome to Hippo v#{Hippo::VERSION}\e[0m"
7
+ puts 'For documentation see https://adam.ac/hippo.'
8
+ puts
9
+
10
+ puts 'The following commands are supported:'
11
+ puts
12
+ context.cli.commands.sort_by { |k, _v| k.to_s }.each do |_, command|
13
+ if command.description
14
+ puts " \e[36m#{command.name.to_s.ljust(18, ' ')}\e[0m #{command.description}"
15
+ end
16
+ end
17
+ puts
18
+ puts 'For details for the options available for each command, use the --help option.'
19
+ puts "For example 'hippo build --help'."
20
+ end
21
+ end
data/cli/init.rb ADDED
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ command :init do
4
+ desc 'Initialize a new application to use Hippo'
5
+
6
+ action do |context|
7
+ require 'fileutils'
8
+
9
+ path = context.args[0]
10
+
11
+ if path.nil?
12
+ raise Error, 'You must pass the name of the directory you wish to create your Hippo manifest'
13
+ end
14
+
15
+ root = File.expand_path(path)
16
+ template_root = File.join(File.expand_path('../', __dir__), 'template')
17
+
18
+ raise Hippo::Error, "File already exists at #{root}" if File.exist?(root)
19
+
20
+ FileUtils.mkdir_p(path)
21
+ FileUtils.cp_r(File.join(template_root, '.'), root)
22
+
23
+ puts "Initialized Hippo manifest in #{root}"
24
+ end
25
+ end
data/cli/install.rb ADDED
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ command :install do
4
+ desc 'Run installation jobs for the application'
5
+
6
+ option '-h', '--hippofile [RECIPE]', 'The path to the Hippofile (defaults: ./Hippofile)' do |value, options|
7
+ options[:hippofile] = value.to_s
8
+ end
9
+
10
+ option '--no-build', 'Do not build the images' do |_value, options|
11
+ options[:build] = false
12
+ end
13
+
14
+ option '--no-deploy', 'Do not deploy after install' do |_value, options|
15
+ options[:deploy] = false
16
+ end
17
+
18
+ action do |context|
19
+ require 'hippo/cli_steps'
20
+ steps = Hippo::CLISteps.setup(context)
21
+ if context.options[:build] == false
22
+ commit = steps.recipe.repository.commit_for_branch(steps.stage.branch)
23
+ puts 'Not building an image and just hoping one exists for current commit.'
24
+ steps.prepare_repository(fetch: false)
25
+ else
26
+ steps.prepare_repository
27
+ steps.build
28
+ steps.publish
29
+ end
30
+
31
+ steps.apply_namespace
32
+ steps.apply_config
33
+ steps.apply_secrets
34
+
35
+ if steps.run_install_jobs == false
36
+ raise Hippo::Error, 'Not all installation jobs completed successfully. Cannot continue to deploy.'
37
+ end
38
+
39
+ unless context.options[:deploy] == false
40
+ steps.apply_services
41
+ steps.deploy
42
+ end
43
+ end
44
+ end
data/cli/kubectl.rb ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ command :kubectl do
4
+ desc 'Execute kubectl commands with the correct namespace for the stage'
5
+
6
+ option '-h', '--hippofile [RECIPE]', 'The path to the Hippofile (defaults: ./Hippofile)' do |value, options|
7
+ options[:hippofile] = value.to_s
8
+ end
9
+
10
+ action do |context|
11
+ require 'hippo/cli_steps'
12
+ cli = Hippo::CLISteps.setup(context)
13
+ ARGV.shift
14
+ exec cli.stage.kubectl(*ARGV)
15
+ end
16
+ end
data/cli/objects.rb ADDED
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ command :objects do
4
+ desc 'Build and publish an image for the given stage'
5
+
6
+ option '-h', '--hippofile [RECIPE]', 'The path to the Hippofile (defaults: ./Hippofile)' do |value, options|
7
+ options[:hippofile] = value.to_s
8
+ end
9
+
10
+ option '--types [TYPES]', 'The types of objects you wish to see' do |value, options|
11
+ options[:types] = value.split(/,/)
12
+ end
13
+
14
+ action do |context|
15
+ require 'hippo/cli_steps'
16
+ steps = Hippo::CLISteps.setup(context)
17
+ commit = steps.prepare_repository(fetch: false)
18
+
19
+ if context.options[:types].nil? || context.options[:types].include?('all')
20
+ types = Hippo::Kubernetes::OBJECT_DIRECTORY_NAMES
21
+ else
22
+ types = context.options[:types]
23
+ end
24
+
25
+ objects = []
26
+ types.each do |type|
27
+ next unless Hippo::Kubernetes::OBJECT_DIRECTORY_NAMES.include?(type)
28
+
29
+ objects |= steps.recipe.kubernetes.objects(type, steps.stage, commit)
30
+ end
31
+
32
+ puts objects.map { |o| o.hash.to_yaml }
33
+ end
34
+ end
data/cli/publish.rb ADDED
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ command :publish do
4
+ desc 'Build and publish an image for the given stage'
5
+
6
+ option '-h', '--hippofile [RECIPE]', 'The path to the Hippofile (defaults: ./Hippofile)' do |value, options|
7
+ options[:hippofile] = value.to_s
8
+ end
9
+
10
+ action do |context|
11
+ require 'hippo/cli_steps'
12
+ steps = Hippo::CLISteps.setup(context)
13
+ steps.prepare_repository
14
+ steps.build
15
+ steps.publish
16
+ end
17
+ end
data/cli/secrets.rb ADDED
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ command :secrets do
4
+ desc 'View all secrets'
5
+
6
+ option '-h', '--hippofile [RECIPE]', 'The path to the Hippofile (defaults: ./Hippofile)' do |value, options|
7
+ options[:hippofile] = value.to_s
8
+ end
9
+
10
+ action do |context|
11
+ require 'hippo/cli_steps'
12
+ cli = Hippo::CLISteps.setup(context)
13
+
14
+ require 'hippo/secret_manager'
15
+ manager = Hippo::SecretManager.new(cli.recipe, cli.stage)
16
+ unless manager.key_available?
17
+ puts "\e[31mNo key has been published for this stage yet.\e[0m"
18
+ exit 2
19
+ end
20
+
21
+ puts manager.secrets.map(&:to_editable_yaml)
22
+ end
23
+ end
data/cli/status.rb ADDED
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ command :status do
4
+ desc 'Print status information from Kubernetes'
5
+
6
+ option '-h', '--hippofile [RECIPE]', 'The path to the Hippofile (defaults: ./Hippofile)' do |value, options|
7
+ options[:hippofile] = value.to_s
8
+ end
9
+
10
+ action do |context|
11
+ require 'hippo/cli_steps'
12
+ cli = Hippo::CLISteps.setup(context)
13
+ exec cli.stage.kubectl('get pods,deployments,job,statefulset,pvc,svc,ingress')
14
+ end
15
+ end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Hippo
4
+ class BuildSpec
5
+ attr_reader :name
6
+
7
+ def initialize(recipe, name, options)
8
+ @recipe = recipe
9
+ @name = name
10
+ @options = options
11
+ end
12
+
13
+ def dockerfile
14
+ @options['dockerfile'] || 'Dockerfile'
15
+ end
16
+
17
+ def image_name
18
+ @options['image-name']
19
+ end
20
+
21
+ def image_name_for_commit(commit_ref)
22
+ "#{image_name}:#{commit_ref}"
23
+ end
24
+
25
+ def template_vars
26
+ {
27
+ 'dockerfile' => dockerfile,
28
+ 'image-name' => image_name
29
+ }
30
+ end
31
+ end
32
+ end