awes_cli 0.0.0 → 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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