awes_cli 0.0.0 → 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 77e5eefdce88cb9bf280df1c12b03072a83c0e435383410e1a41b1074caacc94
4
- data.tar.gz: 63a84f12bdf2874d0fa5a9ab5b8a205a3f04208284d9c918ecea658354526732
3
+ metadata.gz: be520b19b3caa21d29f8208eab535c95e728180b7c74e77feb477263933587f4
4
+ data.tar.gz: 1233834f30464477ec72c618857d980bd68c2d750ce5c8cbd508a98db8876371
5
5
  SHA512:
6
- metadata.gz: 28699c477813def96fef6259122461590ebea3786b9fecfa41561b7cccc8a13263fdb6edb395b8710a79661a71073ccf1484b21414d85da1ffd9fcb34ca731ea
7
- data.tar.gz: c1b67ca8631e92766835a395e76c50163b7394115cebaf6e89b8a0b1bf4ad971e64e84861a4ff8cc5e3c7c154c594bd0dd3e22567f9e8bc55df3313d140965a8
6
+ metadata.gz: 655d71c2e1f7563b8bd6f414f2e3ca73ee5a4c50713ab9009dc9a5709a30866682494cd1d2ddf6edd8bc8d8fa2e47d39cf2ae2c57c12bdf76ed45accd4671fa4
7
+ data.tar.gz: e4133b8c0233f5f89352e968daeaad5f31f837b1f0adeed939b83bd986e9d476dcf5e6f6ab8b52d6c56d4ad559754e44e656cad31dbdb21ae1203f15fc39d4b8
data/bin/ather CHANGED
@@ -1,5 +1,25 @@
1
1
  #!/usr/bin/env ruby
2
2
  require 'build_app_image'
3
+ require 'deploy_app'
4
+ require 'deploy_config'
3
5
 
4
- build = BuildAppImage.new
5
- build.main
6
+ primary_cmd = ARGV[0]
7
+ secondary_cmd = ARGV[1]
8
+
9
+ if primary_cmd.nil?
10
+ puts 'Run `ather build|deploy`'
11
+ exit 1
12
+ end
13
+
14
+ if primary_cmd == 'deploy' && secondary_cmd.nil?
15
+ puts 'Run `ather deploy app|config`'
16
+ exit 1
17
+ end
18
+
19
+ if primary_cmd == 'build'
20
+ BuildAppImage.new.main
21
+ elsif primary_cmd == 'deploy' && secondary_cmd == 'app'
22
+ DeployApp.new.main
23
+ elsif primary_cmd == 'deploy' && secondary_cmd == 'config'
24
+ DeployConfig.new.main
25
+ end
@@ -17,7 +17,11 @@ class BuildAppImage
17
17
  require_options_keys = [:project_id, :app_name]
18
18
 
19
19
  opt_parser = OptionParser.new do |opts|
20
- opts.banner = "Usage: ./deploy/build.rb [options]"
20
+ opts.banner = "Usage: ather build [options]"
21
+
22
+ opts.on("--image-tag IMAGE_TAG", "Image tag to deploy [optional]") do |val|
23
+ options[:image_tag] = val
24
+ end
21
25
 
22
26
  opts.on("--project-id PROJECT_ID", "GCP project id [required or set env var PROJECT_ID]") do |val|
23
27
  options[:project_id] = val
@@ -60,13 +64,19 @@ class BuildAppImage
60
64
  def build_image(gcr_url, options)
61
65
  commit_image_tag = ENV['CI_COMMIT_SHORT_SHA'] || `git rev-parse --short HEAD`
62
66
  time_image_tag=`TZ=IST-5:30 date +'%Y.%m.%d.%HH.%MM.%SS'`
63
- image_url = "#{gcr_url}:#{commit_image_tag}".strip
67
+ commit_image_url = "#{gcr_url}:#{commit_image_tag}".strip
68
+ time_image_url = "#{gcr_url}:#{time_image_tag}".strip
69
+
64
70
  project_id = options[:project_id]
65
71
 
66
- shell_cmd("gcloud builds submit --project #{project_id} --timeout=20m --tag #{image_url} || true")
72
+ shell_cmd("gcloud builds submit --project #{project_id} --timeout=20m --tag #{time_image_url} || true")
73
+
74
+ shell_cmd("gcloud container images add-tag --quiet #{time_image_url} #{commit_image_url}")
75
+
76
+ opt_image_url = options[:image_tag] && "#{gcr_url}:#{options[:image_tag]}"
67
77
 
68
- shell_cmd("gcloud container images add-tag --quiet #{image_url} #{gcr_url}:#{time_image_tag}")
78
+ opt_image_url && shell_cmd("gcloud container images add-tag --quiet #{time_image_url} #{opt_image_url}")
69
79
 
70
- image_url
80
+ opt_image_url
71
81
  end
72
82
  end
data/lib/deploy_app.rb ADDED
@@ -0,0 +1,135 @@
1
+ #!/usr/bin/env ruby
2
+ require 'optparse'
3
+
4
+ class DeployApp
5
+ def main
6
+ options = get_options
7
+ take_approval(options)
8
+
9
+ gcr_url = "gcr.io/#{options[:project_id]}/#{options[:app_name]}"
10
+
11
+ if(!options[:image_tag].nil?)
12
+ image_url = validate_image_tag_exists?(gcr_url, options[:image_tag])
13
+ else
14
+ image_url = build_image(gcr_url, options)
15
+ end
16
+
17
+ deploy_image(gcr_url, image_url, options)
18
+ end
19
+
20
+ private
21
+ def get_options
22
+ options = {}
23
+
24
+ require_options_keys = [:project_id, :app_name, :namespace, :cluster, :cluster_location]
25
+
26
+ opt_parser = OptionParser.new do |opts|
27
+ opts.banner = "Usage: ather deploy app [options]"
28
+
29
+ opts.on("-y", "Auto approve") do |flag|
30
+ options[:approve] = flag
31
+ end
32
+
33
+ opts.on("--image-tag IMAGE_TAG", "Image tag to deploy [optional]") do |val|
34
+ options[:image_tag] = val
35
+ end
36
+
37
+ opts.on("--project-id PROJECT_ID", "GCP project id [required or set env var PROJECT_ID]") do |val|
38
+ options[:project_id] = val
39
+ end
40
+
41
+ opts.on("--app-name APP_NAME", "K8s app name [required or set env var APP_NAME]") do |val|
42
+ options[:app_name] = val
43
+ end
44
+
45
+ opts.on("--namespace NAMESPACE", "K8s app namespace [required or set env var NAMESPACE]") do |val|
46
+ options[:namespace] = val
47
+ end
48
+
49
+ opts.on("--cluster CLUSTER", "App name [required or set env var CLUSTER]") do |val|
50
+ options[:cluster] = val
51
+ end
52
+
53
+ opts.on("--cluster-location CLUSTER_LOCATION", "App name [required or set env var CLUSTER_LOCATION]") do |val|
54
+ options[:cluster_location] = val
55
+ end
56
+
57
+ opts.on("-h", "--help", "Prints this help") do
58
+ puts opts
59
+ exit
60
+ end
61
+ end
62
+
63
+ opt_parser.parse!
64
+
65
+ require_options_keys.each do |key|
66
+ options[key] ||= ENV[key.to_s.upcase]
67
+ if options[key].nil?
68
+ puts "ERROR: Required option --#{key.to_s.gsub('_', '-')} or set env var #{key.to_s.upcase} \n"
69
+ opt_parser.parse! %w[--help]
70
+ exit 1
71
+ end
72
+ end
73
+
74
+ options
75
+ end
76
+
77
+ def shell_cmd(cmd)
78
+ puts "EXECUTING : \e[32m\e[1m#{cmd}\e[22m\e[0m"
79
+ op = system(cmd)
80
+ if !op
81
+ puts "FAILED : \e[31m\e[1m#{cmd}\e[22m\e[0m"
82
+ exit 1
83
+ end
84
+ puts "SUCCESS : \e[32m\e[1m#{cmd}\e[22m\e[0m"
85
+ end
86
+
87
+ def take_approval(options)
88
+ puts "\e[32m\e[1mDeployment parameter details \e[22m\e[0m"
89
+ options.each do |key, val|
90
+ puts "\e[1m#{key} = \e[31m#{val}\e[0m \e[22m"
91
+ end
92
+
93
+ return if(options[:approve])
94
+ puts 'Are you sure to want to deploy as per the above deployment parameters?'
95
+ confirmation = STDIN.gets.strip
96
+ return if(confirmation == 'y' || confirmation == 'Y')
97
+ exit
98
+ end
99
+
100
+ def validate_image_tag_exists?(gcr_url, image_tag)
101
+ image_url = "#{gcr_url}:#{image_tag}"
102
+ shell_cmd("gcloud container images describe #{image_url}")
103
+ image_url
104
+ end
105
+
106
+ def build_image(gcr_url, options)
107
+ commit_image_tag = ENV['CI_COMMIT_SHORT_SHA'] || `git rev-parse --short HEAD`
108
+ time_image_tag=`TZ=IST-5:30 date +'%Y.%m.%d.%HH.%MM.%SS'`
109
+ commit_image_url = "#{gcr_url}:#{commit_image_tag}".strip
110
+ time_image_url = "#{gcr_url}:#{time_image_tag}".strip
111
+
112
+ project_id = options[:project_id]
113
+
114
+ shell_cmd("gcloud builds submit --project #{project_id} --timeout=20m --tag #{time_image_url} || true")
115
+
116
+ shell_cmd("gcloud container images add-tag --quiet #{time_image_url} #{commit_image_url}")
117
+
118
+ commit_image_url
119
+ end
120
+
121
+ def deploy_image(gcr_url, image_url, options)
122
+ shell_cmd(
123
+ "gcloud container clusters get-credentials #{options[:cluster]} " \
124
+ "--region #{options[:cluster_location]} " \
125
+ "--project #{options[:project_id]} "
126
+ )
127
+
128
+ app_name = options[:app_name]
129
+ shell_cmd("kubectl set image deployment #{app_name} #{app_name}=#{image_url} -n #{options[:namespace]}")
130
+
131
+ shell_cmd("kubectl rollout status deployment/#{app_name} -n #{options[:namespace]}")
132
+
133
+ shell_cmd("gcloud container images add-tag --quiet #{image_url} #{gcr_url}:current")
134
+ end
135
+ end
@@ -0,0 +1,210 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'optparse'
4
+ require 'json'
5
+ require 'yaml'
6
+ require 'fileutils'
7
+
8
+ class DeployConfig
9
+ def main
10
+ options = get_options
11
+
12
+ take_approval_deploy_params(options)
13
+
14
+ take_approval_app_env(options)
15
+
16
+ gcr_url = "gcr.io/#{options[:project_id]}/#{options[:app_name]}"
17
+
18
+ deploy_config(gcr_url, options)
19
+ end
20
+
21
+ private
22
+
23
+ def get_options
24
+ options = {}
25
+
26
+ require_options_keys = [:project_id, :app_name, :namespace, :cluster, :cluster_location, :kuztomize_env]
27
+
28
+ opt_parser = OptionParser.new do |opts|
29
+ opts.banner = "Usage: ather deploy config [options]"
30
+
31
+ opts.on("-y", "Auto approve") do |flag|
32
+ options[:approve] = flag
33
+ end
34
+
35
+ opts.on("--image-tag IMAGE_TAG", "Image tag to deploy [optional]") do |val|
36
+ options[:image_tag] = val
37
+ end
38
+
39
+ opts.on("--project-id PROJECT_ID", "GCP project id [required or set env var PROJECT_ID]") do |val|
40
+ options[:project_id] = val
41
+ end
42
+
43
+ opts.on("--app-name APP_NAME", "K8s app name [required or set env var APP_NAME]") do |val|
44
+ options[:app_name] = val
45
+ end
46
+
47
+ opts.on("--namespace NAMESPACE", "K8s app namespace [required or set env var NAMESPACE]") do |val|
48
+ options[:namespace] = val
49
+ end
50
+
51
+ opts.on("--cluster CLUSTER", "App name [required or set env var CLUSTER]") do |val|
52
+ options[:cluster] = val
53
+ end
54
+
55
+ opts.on("--cluster-location CLUSTER_LOCATION", "App name [required or set env var CLUSTER_LOCATION]") do |val|
56
+ options[:cluster_location] = val
57
+ end
58
+
59
+ opts.on("--kuztomize-env KUZTOMIZE_ENV", "App name [required or set env var KUZTOMIZE_ENV]") do |val|
60
+ options[:kuztomize_env] = val
61
+ end
62
+
63
+ opts.on("-h", "--help", "Prints this help") do
64
+ puts opts
65
+ exit
66
+ end
67
+ end
68
+
69
+ opt_parser.parse!
70
+
71
+ require_options_keys.each do |key|
72
+ options[key] ||= ENV[key.to_s.upcase]
73
+ if options[key].nil?
74
+ puts "ERROR: Required option --#{key.to_s.gsub('_', '-')} or set env var #{key.to_s.upcase} \n"
75
+ opt_parser.parse! %w[--help]
76
+ exit 1
77
+ end
78
+ end
79
+
80
+ options
81
+ end
82
+
83
+ def shell_cmd(cmd)
84
+ puts "EXECUTING : \e[32m\e[1m#{cmd}\e[22m\e[0m"
85
+ op = system(cmd)
86
+ if !op
87
+ puts "FAILED : \e[31m\e[1m#{cmd}\e[22m\e[0m"
88
+ exit 1
89
+ end
90
+ puts "SUCCESS : \e[32m\e[1m#{cmd}\e[22m\e[0m"
91
+ end
92
+
93
+ def take_approval_deploy_params(options)
94
+ puts "\e[32m\e[1mDeployment parameter details \e[22m\e[0m"
95
+ options.each do |key, val|
96
+ puts "\e[1m#{key} = \e[31m#{val}\e[0m \e[22m"
97
+ end
98
+
99
+ return if(options[:approve])
100
+ puts 'Are you sure to want to deploy as per the above deployment parameters? (y/N)'
101
+ confirmation = STDIN.gets.strip
102
+ return if(confirmation == 'y' || confirmation == 'Y')
103
+ exit
104
+ end
105
+
106
+ def take_approval_app_env(options)
107
+ override_env_filepath = "./deploy/env/#{options[:kuztomize_env]}.sh"
108
+ return if !File.file?(override_env_filepath)
109
+ puts "\e[32m\e[1mOverriding Application enviroment variables \e[22m\e[0m"
110
+
111
+ app_envs = `cat #{override_env_filepath}`.gsub('export ', "\n")
112
+ puts "\e[34m\e[1m#{app_envs}\e[22m\e[0m"
113
+
114
+ return if(options[:approve])
115
+ puts 'Are you sure to want to deploy the above application enviroment variables? (y/N)'
116
+ confirmation = STDIN.gets.strip
117
+ return if(confirmation == 'y' || confirmation == 'Y')
118
+ exit
119
+ end
120
+
121
+ def validate_image_tag_exists?(image_url)
122
+ shell_cmd("gcloud container images describe #{image_url}")
123
+ image_url
124
+ end
125
+
126
+ def deploy_config(gcr_url, options)
127
+ shell_cmd(
128
+ "gcloud container clusters get-credentials #{options[:cluster]} " \
129
+ "--region #{options[:cluster_location]} " \
130
+ "--project #{options[:project_id]} "
131
+ )
132
+
133
+ spec = app_container_spec(options[:app_name], options[:namespace]) || {}
134
+
135
+ override_envs = override_envs(options)
136
+ k8s_deployment_envs = k8s_deployment_envs(options)
137
+
138
+ yaml_file = `kustomize build deploy/overlays/#{options[:kuztomize_env]}`
139
+
140
+ yaml_file.scan(/\$[A-Z_]+/).each do |env_name|
141
+ env_key = env_name[1..-1]
142
+ env_val = override_envs[env_key] || ENV[env_key] || k8s_deployment_envs[env_key]
143
+ next if env_val.nil?
144
+ yaml_file[env_name] = env_val
145
+ end
146
+
147
+ gcr_url = "gcr.io/#{options[:project_id]}/#{options[:app_name]}"
148
+
149
+ opt_image_url = options[:image_tag] && "#{gcr_url}:#{options[:image_tag]}"
150
+
151
+ image_url = opt_image_url || spec[:image] || "#{gcr_url}:current"
152
+ validate_image_tag_exists?(image_url)
153
+
154
+ yaml_file['$IMAGE_URL'] = image_url
155
+
156
+ FileUtils.mkdir_p('./tmp')
157
+
158
+ File.write('./tmp/final.yaml', yaml_file)
159
+
160
+ puts "\e[36m\e[1m#{yaml_file}\e[22m\e[0m"
161
+
162
+ shell_cmd("kubectl apply -f ./tmp/final.yaml")
163
+
164
+ shell_cmd("kubectl rollout status deployment/#{options[:app_name]} -n #{options[:namespace]}")
165
+ end
166
+
167
+ def override_envs(options)
168
+ override_env_filepath = "./deploy/env/#{options[:kuztomize_env]}.yaml"
169
+ override_envs = {}
170
+
171
+ if File.file?(override_env_filepath)
172
+ env = YAML.load_file(override_env_filepath, symbolize_names: true)
173
+ env[:env].each do |env|
174
+ override_envs[env[:name]] = env[:value]
175
+ end
176
+ end
177
+
178
+ override_envs
179
+ end
180
+
181
+ def k8s_deployment_envs(options)
182
+ spec = app_container_spec(options[:app_name], options[:namespace])
183
+
184
+ return {} if spec.nil?
185
+
186
+ k8s_deployment_envs = {}
187
+
188
+ spec[:env].each do |env|
189
+ k8s_deployment_envs[env[:name]] = env[:value]
190
+ end
191
+
192
+ k8s_deployment_envs
193
+ end
194
+
195
+ def app_container_spec(app_name, namespace)
196
+ deploy_containers = `kubectl get deployment -n #{namespace} #{app_name} --output=jsonpath={.spec.template.spec.containers}`
197
+ return nil if deploy_containers == ''
198
+ JSON.parse(deploy_containers, symbolize_names: true).find { |container| container[:name] == app_name }
199
+ end
200
+
201
+ def app_container_env_vars_cmd(spec)
202
+ env_export_cmd = ''
203
+ spec[:env].each do |env|
204
+ env_var_val = ENV.fetch(env[:name]) { env[:value] }
205
+ env_export_cmd += "export #{env[:name]}=#{env_var_val} && "
206
+ end
207
+
208
+ env_export_cmd
209
+ end
210
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: awes_cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.0
4
+ version: 0.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Umar Siddiqui
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-07-20 00:00:00.000000000 Z
11
+ date: 2021-07-22 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Ather cli tool
14
14
  email: umar.siddiqui@atherenergy.com
@@ -20,6 +20,8 @@ files:
20
20
  - bin/ather
21
21
  - lib/awes_cli.rb
22
22
  - lib/build_app_image.rb
23
+ - lib/deploy_app.rb
24
+ - lib/deploy_config.rb
23
25
  homepage: https://rubygems.org/gems/awes_cli
24
26
  licenses:
25
27
  - MIT