sct 0.1.30 → 1.0.0

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: 2dc9c664ca89d649033d4fcfdcad7e8d72d78b448d800caa8c8097ec1ea7ed47
4
- data.tar.gz: f3cdba0dfbaacbf240e4f84f8530cb835308a19203999db78759b17d4eb18150
3
+ metadata.gz: 8be150a1d5ddc9339df696d2f7db5d6056dfdba0fbb48884e57cfacc700b79ea
4
+ data.tar.gz: d6fc67a9a3af7c51bf542353f476ec59b60f1c40e7387da64910c4287be857c7
5
5
  SHA512:
6
- metadata.gz: 56c7e96250c79f3fdb4de6fab3358e4e6eb443f813064d88e9353a766eccecc1ad1c7f2c2878716347676e3c24de1d09456763ccc2c857d13eb6cd4f058f7593
7
- data.tar.gz: 27543415be2aac23a5032b2b96bb7504dd12b5cc3d41f73c489251416d1d3bc3ddd83c8af71f7163b96b0bfe1c22a1f8f06e8c9992a5a54d279a89a40d3c90b6
6
+ metadata.gz: e5046d7b3acb18f4cce8b17b7a8d32586758dfda47ba696b7e0f36192fd5b51d132fe2a770768410728279c08b70ebfeb263a79b82bad5531d889b3fe0b733cc
7
+ data.tar.gz: 3502a15df6d47b547af6dc7a15cd175a23f45700c6771ccf66055542d2df2d21baadb7c26c03c0736d469ead3108c5b09f968adc318c1d572fa036fea047f454
@@ -2,96 +2,101 @@ require 'commander'
2
2
  require_relative 'runner'
3
3
 
4
4
  module Cluster
5
- class CommandsGenerator
6
- include Commander::Methods
5
+ class CommandsGenerator
6
+ include Commander::Methods
7
7
 
8
- def self.start
9
- self.new.run
10
- end
11
-
12
- def run
13
- program :name, 'cluster'
14
- program :version, Sct::VERSION
15
- program :description, 'CLI for \'cluster\' - Manage your local kubernetes cluster'
16
-
17
- global_option('--verbose') { $verbose = true }
18
-
19
- command :start do |c|
20
- c.syntax = "sct cluster start"
21
- c.description = "start the cluster"
22
-
23
- c.action do |args, options|
24
- Cluster::Runner.new.start
25
- end
26
-
27
- end
28
-
29
- command :stop do |c|
30
- c.syntax = 'sct cluster stop'
31
- c.description = 'stop the cluster'
8
+ def self.start
9
+ self.new.run
10
+ end
32
11
 
33
- c.action do |args, options|
34
- Cluster::Runner.new.stop
35
- end
36
- end
12
+ def run
13
+ program :name, 'cluster'
14
+ program :version, Sct::VERSION
15
+ program :description, 'CLI for \'cluster\' - Manage your local Docker cluster'
37
16
 
38
- command :restart do |c|
39
- c.syntax = "sct cluster restart"
40
- c.description = "restart the cluster"
17
+ global_option('--verbose') { $verbose = true }
41
18
 
42
- c.action do |args, options|
43
- Cluster::Runner.new.restart
44
- end
19
+ command :start do |c|
20
+ c.syntax = "sct cluster start"
21
+ c.description = "start the cluster"
22
+ c.option '--build', '(re)build images before starting'
23
+ c.option '--pull', 'pull latest images before starting'
45
24
 
46
- end
25
+ c.action do |args, options|
26
+ Cluster::Runner.new.start args, options
27
+ end
28
+ end
47
29
 
48
- command :delete do |c|
49
- c.syntax = "sct cluster delete"
50
- c.description = "delete the cluster"
30
+ command :stop do |c|
31
+ c.syntax = 'sct cluster stop'
32
+ c.description = 'stop the cluster'
51
33
 
52
- c.action do |args, options|
53
- Cluster::Runner.new.delete
54
- end
34
+ c.action do |args, options|
35
+ Cluster::Runner.new.stop
36
+ end
37
+ end
55
38
 
56
- end
39
+ command :restart do |c|
40
+ c.syntax = "sct cluster restart"
41
+ c.description = "restart the cluster"
57
42
 
58
- command :reset do |c|
59
- c.syntax = 'sct cluster reset'
60
- c.description = 'delete the cluster and start a new cluster'
43
+ c.action do |args, options|
44
+ Cluster::Runner.new.restart
45
+ end
46
+ end
61
47
 
62
- c.action do |args, options|
63
- Cluster::Runner.new.reset
64
- end
65
- end
48
+ command :delete do |c|
49
+ c.syntax = "sct cluster delete"
50
+ c.description = "delete the cluster"
66
51
 
67
- command :status do |c|
68
- c.syntax = 'sct cluster status'
69
- c.description = 'see the status of your cluster'
52
+ c.action do |args, options|
53
+ Cluster::Runner.new.delete
54
+ end
55
+ end
70
56
 
71
- c.action do |args, options|
72
- Cluster::Runner.new.status
73
- end
74
- end
57
+ command :reset do |c|
58
+ c.syntax = 'sct cluster reset'
59
+ c.description = 'delete the cluster and start a new cluster'
75
60
 
76
- command :'update config' do |c|
77
- c.syntax = 'sct cluster update config'
78
- c.description = 'update the cluster configuration'
61
+ c.action do |args, options|
62
+ Cluster::Runner.new.reset args, options
63
+ end
64
+ end
79
65
 
80
- c.action do |args, options|
81
- Cluster::Runner.new.update_config
82
- end
83
- end
66
+ command :pull do |c|
67
+ c.syntax = 'sct cluster pull'
68
+ c.description = 'pull new image versions'
84
69
 
85
- command :'apply deployments' do |c|
86
- c.syntax = 'sct cluster apply deployments'
87
- c.description = 'apply deployments from the k8s folder'
70
+ c.action do |args, options|
71
+ Cluster::Runner.new.pull
72
+ end
73
+ end
88
74
 
89
- c.action do |args, options|
90
- Cluster::Runner.new.apply_deployments
91
- end
92
- end
75
+ command :status do |c|
76
+ c.syntax = 'sct cluster status'
77
+ c.description = 'see the status of your cluster'
93
78
 
94
- run!
79
+ c.action do |args, options|
80
+ Cluster::Runner.new.status
81
+ end
82
+ end
83
+
84
+ command :logs do |c|
85
+ c.syntax = 'sct cluster logs'
86
+ c.description = 'see the logs of your cluster'
87
+ c.option '-f', 'follow log output'
88
+ c.option '--follow', 'follow log output'
89
+ c.option '-t', 'show timestamps'
90
+ c.option '--timestamps', 'show timestamps'
91
+ c.option '--tail LINES', 'number of lines to show from the end of the logs for each container (default: "all")'
92
+
93
+ c.action do |args, options|
94
+ Cluster::Runner.new.logs args, options
95
95
  end
96
+ end
97
+
98
+ run!
96
99
  end
100
+
101
+ end
97
102
  end
@@ -1,318 +1,73 @@
1
1
  module Cluster
2
- class Runner
2
+ class Runner
3
3
 
4
- def start
5
- SctCore::Helper.ensure_windows_administrator # "sct hostfile" will need it later on
6
-
7
- existing_cluster = cluster_exists?
8
-
9
- start_cluster
10
-
11
- if existing_cluster
12
- run_command "kubectl rollout restart -n kube-system deployment registry-creds"
13
- run_command "kubectl rollout status -n kube-system deployment registry-creds"
14
- else
15
- create_secrets
16
- enable_addons
17
- wait_for_gcr_secret
18
- run_command "kubectl apply -f ~/development/spend-cloud/k8s/ingress.yml"
19
- wait_for_ingress_ip
20
- run_command "kubectl apply -f ~/development/spend-cloud/k8s/dependencies.yml"
21
- wait_for_pods
22
- run_command "kubectl apply -f ~/development/spend-cloud/k8s/"
23
- end
24
-
25
- post_start
26
- end
27
-
28
- def stop
29
- run_command "minikube stop"
30
- end
31
-
32
- def restart
33
- SctCore::Helper.ensure_windows_administrator # "sct hostfile" will need it later on
34
-
35
- stop
36
- start
37
- end
38
-
39
- def delete
40
- run_command "minikube delete"
41
- end
42
-
43
- def reset
44
- SctCore::Helper.ensure_windows_administrator # "sct hostfile" will need it later on
45
-
46
- delete
47
- start
48
- end
49
-
50
- def status
51
- print_contexts
52
- print_minikube_status
53
-
54
- if get_minikube_status.find_all { |status| status[1] == 'Stopped' }.count == 0
55
- print_pods_status("kube-system")
56
- print_pods_status
57
- else
58
- UI.important("Please check your minikube status. If all services are stopped you should start the minikube first.")
59
- end
60
- end
61
-
62
- def update_config
63
- run_command "kubectl config use-context minikube"
64
-
65
- run_command "kubectl replace -n kube-system -f #{File.expand_path('resources/corefile.yml', __dir__)}"
66
- run_command "kubectl rollout restart -n kube-system deployment coredns"
67
- run_command "kubectl rollout status -n kube-system deployment coredns"
68
- end
69
-
70
- def apply_deployments
71
- run_command "kubectl apply -f ~/development/spend-cloud/k8s/"
72
- end
73
-
74
-
75
- def cluster_exists?
76
- if system "minikube status", { out: "/dev/null" }
77
- # cluster exists and is running
78
- return true
79
- end
80
-
81
- if $?.exitstatus == 85
82
- # cluster does not exist
83
- return false
84
- end
85
-
86
- # cluster exists but is stopped
87
- return true
88
- end
89
-
90
- def start_cluster
91
- if SctCore::Helper.operatingSystem == SctCore::Helper::MAC_OS
92
- run_command "minikube start --driver=docker --cpus=$(sysctl -n hw.ncpu) --memory=8G"
93
- else
94
- run_command "minikube start --driver=docker --cpus=$(cat /proc/cpuinfo | grep processor | wc -l) --memory=3G"
95
- end
96
- update_config
97
- end
98
-
99
- def post_start
100
- wait_for_pods
101
- copy_proactive_accounts_file
102
- run_command "sudo sct hostfile"
103
- run_command "minikube tunnel &", { out: "/dev/null", err: "/dev/null" } if SctCore::Helper::is_windows? # leave this running detached forever in the background
104
- UI.success("\n✔️ You can visit your environment at 👉 https://spend-cloud.spend.cloud.local 👌")
105
- end
106
-
107
- def enable_addons
108
- enable_addon "registry-creds"
109
- enable_addon "ingress"
110
- end
111
-
112
- def enable_addon(addon)
113
- run_command "minikube addons enable #{addon}"
114
-
115
- deployment = deployments("kube-system").find { |deployment| deployment[:name].include? addon }
116
-
117
- run_command "kubectl rollout status -n kube-system deployment #{deployment[:name]}"
118
- end
119
-
120
- def wait_for_pods
121
- UI.important("Waiting for pods to become ready...")
122
-
123
- previous_lines = 0
124
-
125
- while ! pods.all? { |pod| pod[:ready] }
126
- pods_status_lines = get_pods_status.to_s.lines.map { |line| line.chomp }
127
-
128
- current_lines = pods_status_lines.length
129
-
130
- line_difference = current_lines - previous_lines
131
-
132
- if line_difference < 0 # there are now less lines than before
133
- line_difference.abs.times do
134
- print "\033[1A\033[K" # move the cursor up a line and clear the line
135
- end
136
-
137
- print "\033[#{current_lines}A" # move the cursor all the way up to the start of the table
138
- elsif previous_lines > 0
139
- print "\033[#{previous_lines}A" # move the cursor all the way up to the start of the table
140
- end
141
-
142
- pods_status_lines.each do |line|
143
- print "#{line}\033[K#{$/}" # print the content of the line, clear remaining characters and add a new line
144
- end
145
-
146
- previous_lines = current_lines
147
-
148
- sleep 5
149
- end
150
-
151
- previous_lines.times do
152
- print "\033[1A\033[K" # move the cursor up a line and clear the line
153
- end
154
-
155
- UI.success("Pods are now ready.")
156
- end
157
-
158
- def deployments(namespace = "default")
159
- output = `kubectl get deployments -n #{namespace}`
160
-
161
- # split output lines
162
- lines = output.split "\n"
163
-
164
- # exclude first line (table header)
165
- lines = lines[1..-1]
166
-
167
- # get name and status of each pod
168
- lines.map do |line|
169
- columns = line.split(" ")
170
-
171
- name = columns[0]
172
-
173
- {
174
- name: name
175
- }
176
- end
177
- end
178
-
179
- def pods(namespace = "default")
180
- output = `kubectl get pods -n #{namespace}`
181
-
182
- # split output lines
183
- lines = output.split "\n"
184
-
185
- # exclude first line (table header)
186
- lines = lines[1..-1]
187
-
188
- # get name and status of each pod
189
- lines.map do |line|
190
- columns = line.split(" ")
191
-
192
- name = columns[0]
193
- ready = columns[1].split("/").reduce { |l, r| l == r }
194
- replicas = columns[1]
195
- status = columns[2]
196
-
197
- {
198
- name: name,
199
- ready: ready,
200
- replicas: replicas,
201
- status: status
202
- }
203
- end
204
- end
205
-
206
- def create_secrets
207
- run_command "kubectl create secret generic gcloud-credentials --from-file=\"$(echo ~)/.config/gcloud/application_default_credentials.json\""
208
- run_command "kubectl create secret generic -n kube-system registry-creds-dpr --from-literal DOCKER_PRIVATE_REGISTRY_PASSWORD=changeme --from-literal DOCKER_PRIVATE_REGISTRY_SERVER=changeme --from-literal DOCKER_PRIVATE_REGISTRY_USER=changeme"
209
- run_command "kubectl patch secret -n kube-system registry-creds-dpr -p='{\"metadata\": {\"labels\": { \"app\": \"registry-creds\", \"cloud\": \"dpr\", \"kubernetes.io/minikube-addons\": \"registry-creds\"}}}'"
210
- run_command "kubectl create secret generic -n kube-system registry-creds-ecr --from-literal AWS_ACCESS_KEY_ID=changeme --from-literal AWS_SECRET_ACCESS_KEY=changeme --from-literal AWS_SESSION_TOKEN=\"\" --from-literal aws-account=changeme --from-literal aws-assume-role=changeme --from-literal aws-region=changeme"
211
- run_command "kubectl patch secret -n kube-system registry-creds-ecr -p='{\"metadata\": {\"labels\": { \"app\": \"registry-creds\", \"cloud\": \"ecr\", \"kubernetes.io/minikube-addons\": \"registry-creds\"}}}'"
212
- run_command "kubectl create secret generic -n kube-system registry-creds-gcr --from-file=\"$(echo ~)/.config/gcloud/application_default_credentials.json\" --from-literal=gcrurl=\"https://eu.gcr.io\""
213
- run_command "kubectl patch secret -n kube-system registry-creds-gcr -p='{\"metadata\": {\"labels\": { \"app\": \"registry-creds\", \"cloud\": \"gcr\", \"kubernetes.io/minikube-addons\": \"registry-creds\"}}}'"
214
- run_command "kubectl create secret generic -n kube-system registry-creds-acr --from-literal ACR_PASSWORD=changeme --from-literal ACR_CLIENT_ID=changeme --from-literal ACR_URL=changeme"
215
- run_command "kubectl patch secret -n kube-system registry-creds-acr -p='{\"metadata\": {\"labels\": { \"app\": \"registry-creds\", \"cloud\": \"acr\", \"kubernetes.io/minikube-addons\": \"registry-creds\"}}}'"
216
- end
217
-
218
- def wait_for_gcr_secret
219
- UI.important("Waiting for Google Cloud Registry secret to become available...")
220
-
221
- while ! `kubectl get secrets`.include? "gcr-secret"
222
- sleep 5
223
- end
224
-
225
- UI.success("Google Cloud Registry secret is now available.")
226
- end
227
-
228
- def wait_for_ingress_ip
229
- UI.important("Waiting for ingress IP to become available...")
230
-
231
- while `kubectl describe ingress | grep "Address" | awk '{print $2}'`.empty?
232
- sleep 5
233
- end
234
-
235
- UI.success("Ingress IP is now available.")
236
- end
237
-
238
- def print_contexts
239
- output = `kubectl config get-contexts`
240
-
241
- lines = output.split "\n"
242
- lines = lines[1..-1]
243
-
244
- rows = lines.map do |line|
245
- columns = line.split(" ")
246
-
247
- current_context = columns[0] == "*" ? "Yes".green : "No".red
248
-
249
- [columns[2], current_context]
250
- end
251
-
252
- puts Terminal::Table.new title: "Contexts".green, headings: ['Cluster', 'Using context'], rows: rows
4
+ def run command, options = {}
5
+ begin
6
+ if !system command, options
7
+ raise command.red
253
8
  end
9
+ rescue Interrupt
10
+ # user pressed Ctrl+C, do nothing
11
+ end
12
+ end
254
13
 
255
- def print_minikube_status
256
- puts Terminal::Table.new title: "Minikube status".green, headings: ['Name', 'Status'], rows: get_minikube_status
257
- end
14
+ def run_dc command, options = {}
15
+ run "docker-compose -f ~/development/spend-cloud/docker-compose.yml #{command}", options
16
+ end
258
17
 
259
- def get_minikube_status
260
- output = `minikube status`
18
+ def start args, options
19
+ if options.pull
20
+ run_dc "pull"
21
+ end
261
22
 
262
- lines = output.split "\n"
23
+ if options.build
24
+ run_dc "build #{options.pull ? "--pull" : ""}"
25
+ end
263
26
 
264
- rows = lines.map do |line|
265
- columns = line.split(" ")
27
+ run_dc "up --detach"
266
28
 
267
- [columns[0][0..-2], columns[1]]
268
- end
269
- end
29
+ if options.pull or options.build
30
+ system "docker image prune -f"
31
+ end
270
32
 
271
- def print_pods_status(namespace = "default")
272
- output = get_pods_status(namespace)
33
+ UI.success("\n✔️ You can visit your environment at 👉 https://spend-cloud.dev.spend.cloud 👌")
34
+ end
273
35
 
274
- puts output if output
275
- end
36
+ def stop
37
+ run_dc "down --remove-orphans"
38
+ end
276
39
 
277
- def get_pods_status(namespace = "default")
278
- rows = pods(namespace).map do |pod|
279
- status = pod[:status]
280
- replicas = pod[:replicas]
40
+ def restart
41
+ run_dc "restart"
42
+ end
281
43
 
282
- [
283
- pod[:name],
284
- status == "Running" ? status.green : status.red,
285
- pod[:ready] ? replicas.green : replicas.red
286
- ]
287
- end
44
+ def delete
45
+ run_dc "down --remove-orphans -v"
46
+ end
288
47
 
289
- if rows.empty?
290
- return
291
- end
48
+ def reset args, options
49
+ delete
50
+ start args, options
51
+ end
292
52
 
293
- return Terminal::Table.new title: "Pods (namespace: #{namespace})".green, headings: ['Name', 'Status', 'Replicas ready'], rows: rows
294
- end
53
+ def pull
54
+ run_dc "pull"
55
+ run "docker image prune -f"
56
+ end
295
57
 
296
- def copy_proactive_accounts_file
297
- pod_id = pods().select {|pod| pod[:name].start_with?("proactive-config")}.first[:name]
58
+ def status
59
+ run_dc "ps"
60
+ end
298
61
 
299
- begin
300
- UI.important("Checking ProActive accounts file...")
301
- run_command "kubectl exec #{pod_id} -- test -e /data/proactive_accounts.ini", [:out, :err] => File::NULL
302
- rescue => e
303
- UI.important("Copying ProActive accounts file to deployments...")
304
- src_path = "#{Dir.home()}/development/spend-cloud/k8s/conf/proactive_accounts.ini"
305
- command = "kubectl cp #{src_path} #{pod_id}:/data/proactive_accounts.ini"
306
- run_command command
307
- end
62
+ def logs args, options
63
+ command = "logs"
308
64
 
309
- UI.success("ProActive accounts file is available")
310
- end
65
+ command << " --follow" if options.f or options.follow
66
+ command << " --timestamps" if options.t or options.timestamps
67
+ command << " --tail #{options.tail}" if options.tail
311
68
 
312
- def run_command command, options = {}
313
- if ! system command, options
314
- raise command.red
315
- end
316
- end
69
+ run_dc "#{command} #{args.join " "}"
317
70
  end
71
+
72
+ end
318
73
  end
@@ -0,0 +1,43 @@
1
+ require 'yaml'
2
+
3
+ module Sct
4
+ class DevCommand
5
+
6
+ def error message
7
+ UI.error message
8
+ exit 1
9
+ end
10
+
11
+ def execute args, options
12
+ file = "docker-compose.dev.yml"
13
+
14
+ if !File.exist? file
15
+ error "Could not find file '#{file}'."
16
+ end
17
+
18
+ manifest = YAML.load File.read file
19
+
20
+ services = manifest["services"].to_a
21
+
22
+ if services.length != 1
23
+ error "Currently sct only supports a single service declaration in '#{file}'. Contact the infra guild if you consider this a limitation."
24
+ end
25
+
26
+ service, service_spec = services.first
27
+
28
+ container = service_spec["container_name"]
29
+ command = service_spec["command"] || ""
30
+
31
+ if options.build
32
+ return unless system "docker-compose -f #{file} build #{options.pull ? "--pull" : ""}"
33
+ end
34
+
35
+ return unless system "docker-compose -f ~/development/spend-cloud/docker-compose.yml rm --stop --force #{service}"
36
+
37
+ system "docker-compose -f #{file} run --rm --service-ports --name #{container} #{service} #{command}"
38
+
39
+ system "docker-compose -f ~/development/spend-cloud/docker-compose.yml up --detach #{service}"
40
+ end
41
+
42
+ end
43
+ end
@@ -1,20 +1,14 @@
1
1
  module Sct
2
2
  class MysqlproxyCommand
3
-
3
+
4
4
  DEFAULT_SECRET_NAME = "gcloud-credentials"
5
5
 
6
6
  def execute(args, options)
7
-
8
- return UI.error("SCT has not been initialized. Run 'sct init' first.") unless SctCore::Config.exists
9
-
10
- path = SctCore::Config.get('cloud-proxy-path')
11
-
12
7
  system("kubectl delete secret gcloud-credentials")
13
- system("kubectl create secret generic gcloud-credentials --from-file=#{path}")
14
-
8
+ system("kubectl create secret generic gcloud-credentials --from-file=~/.config/gcloud/application_default_credentials.json")
9
+
15
10
  UI.success("Authenticated with secret-name: '#{DEFAULT_SECRET_NAME}'")
16
11
  end
17
-
18
- end
19
12
 
20
- end
13
+ end
14
+ end
@@ -17,51 +17,35 @@ module Sct
17
17
 
18
18
  global_option('--verbose') { $verbose = true }
19
19
 
20
- command :init do |c|
21
- c.syntax = 'sct init'
22
- c.description = 'setup sct'
23
-
24
- c.action do |args, options|
25
- UI.important("setting up sct")
26
- Sct::InitCommand.new.execute(args, options)
27
- end
28
- end
29
-
30
- command :hostfile do |c|
31
-
32
- c.syntax = 'sct hostfile'
33
- c.description = 'patch hostfile with kubernetes ip'
34
-
35
- c.action do |args, options|
36
- UI.important("Trying to patch hosts file...")
37
- Sct::HostfileCommand.new.execute(args, options)
38
- end
39
- end
40
-
41
20
  command :'mysql-proxy' do |c|
42
-
43
21
  c.syntax = 'sct mysql-proxy'
44
22
  c.description = 'setup google mysql proxy'
45
23
 
46
24
  c.action do |args, options|
47
25
  UI.important("Trying to setup mysql proxy")
48
- Sct::MysqlproxyCommand.new.execute(args, options)
26
+ Sct::MysqlproxyCommand.new.execute args, options
49
27
  end
50
-
51
28
  end
52
29
 
53
30
  command :'cluster' do |c|
54
-
55
31
  c.syntax = 'sct cluster'
56
32
  c.description = 'make changes to the cluster'
57
-
58
33
  end
59
34
 
60
35
  command :'shell' do |c|
61
-
62
36
  c.syntax = 'sct shell'
63
37
  c.description = 'run commands from the shell using docker containers'
38
+ end
39
+
40
+ command :'dev' do |c|
41
+ c.syntax = 'sct dev'
42
+ c.description = 'start development container in the current directory'
43
+ c.option '--build', '(re)build image from Dockerfile before starting'
44
+ c.option '--pull', 'pull latest base image from Dockerfile before (re)building. only used in combination with --build flag'
64
45
 
46
+ c.action do |args, options|
47
+ Sct::DevCommand.new.execute args, options
48
+ end
65
49
  end
66
50
 
67
51
  run!
@@ -1,3 +1,3 @@
1
1
  module Sct
2
- VERSION = "0.1.30"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -1,5 +1,4 @@
1
1
  require_relative 'sct_core/core_ext/string'
2
- require_relative 'sct_core/config'
3
2
  require_relative 'sct_core/helper'
4
3
  require_relative 'sct_core/update_checker/update_checker'
5
4
  require_relative 'sct_core/command_executor'
@@ -11,4 +10,4 @@ require 'colored'
11
10
  require 'commander'
12
11
 
13
12
  # these need to be imported after commander
14
- require_relative 'sct_core/module'
13
+ require_relative 'sct_core/module'
@@ -5,13 +5,13 @@ module SctCore
5
5
  MAC_OS = "MacOS"
6
6
  UBUNTU = "Ubuntu"
7
7
 
8
- def self.to_hash(str)
8
+ def self.to_hash str
9
9
  Hash[
10
10
  str.split("\n").map{|i|i.split('=')}
11
11
  ]
12
12
  end
13
13
 
14
- def self.operatingSystem
14
+ def self.operating_system
15
15
  proc = `uname -a`
16
16
 
17
17
  case proc.downcase
@@ -29,7 +29,7 @@ module SctCore
29
29
  def self.homePath
30
30
  user = ENV["SUDO_USER"] || ENV["USER"]
31
31
 
32
- if self.operatingSystem == MAC_OS
32
+ if self.operating_system == MAC_OS
33
33
  home = "/Users"
34
34
  else
35
35
  home = "/home"
@@ -46,7 +46,7 @@ module SctCore
46
46
  return nil
47
47
  end
48
48
 
49
- def self.convertWindowsToWSLPath(path)
49
+ def self.convertWindowsToWSLPath path
50
50
  if self.is_windows?
51
51
  return path.gsub(/C:\\/, '/mnt/c/').gsub(/\\\\/, "/").gsub(/\\/, '/').gsub(/\r\n?/, '')
52
52
  end
@@ -54,7 +54,7 @@ module SctCore
54
54
  return path
55
55
  end
56
56
 
57
- def self.convertWSLToWindowsPath(path)
57
+ def self.convertWSLToWindowsPath path
58
58
  if self.is_windows?
59
59
  return path.gsub(/\/mnt\/c/, 'C:/').gsub(/\/\//, '/').gsub(/\\\\/, "/").gsub(/\r\n?/, '')
60
60
  end
@@ -67,7 +67,7 @@ module SctCore
67
67
  end
68
68
 
69
69
  def self.is_windows?
70
- return self.operatingSystem == WINDOWS
70
+ return self.operating_system == WINDOWS
71
71
  end
72
72
 
73
73
  def self.is_windows_administrator?
@@ -93,5 +93,6 @@ module SctCore
93
93
  self.ensure_sudo
94
94
  self.ensure_windows_administrator
95
95
  end
96
+
96
97
  end
97
98
  end
@@ -1,83 +1,48 @@
1
1
  require 'yaml'
2
2
 
3
3
  module Shell
4
- class Runner
4
+ class Runner
5
5
 
6
- def launch
7
- command = ARGV.join(" ")
8
-
9
- if ! File.exist? "./okteto.yml"
10
- error "Could not find file 'okteto.yml'."
11
- end
12
-
13
- manifest = YAML.load File.read "./okteto.yml"
14
-
15
- deployment = manifest["name"]
16
-
17
- pod = find_pod deployment
18
-
19
- if command.empty?
20
- system "kubectl exec #{pod} -it -- sh", { in: :in, out: :out, err: :err }
21
- else
22
- system "kubectl exec #{pod} -it -- #{command}", { in: :in, out: :out, err: :err }
23
- end
24
- end
25
-
26
- def find_pod deployment
27
- output = `kubectl get pods --show-labels`
28
-
29
- # split output lines
30
- lines = output.split "\n"
31
-
32
- # exclude first line (table header)
33
- lines = lines[1..-1]
6
+ def error message
7
+ UI.error message
8
+ exit 1
9
+ end
34
10
 
35
- # get the name and labels of each pod
36
- pods = lines.map do |line|
37
- columns = line.split " "
11
+ def launch
12
+ command = ARGV.empty? ? "sh" : ARGV.join(" ")
38
13
 
39
- name = columns[0]
14
+ file = "docker-compose.dev.yml"
40
15
 
41
- labels = columns[5].split(",").reduce({}) do |labels, label|
42
- key, value = label.split "="
43
- labels[key] = value
44
- labels
45
- end
16
+ if !File.exist? file
17
+ error "Could not find file '#{file}'."
18
+ end
46
19
 
47
- {
48
- name: name,
49
- labels: labels
50
- }
51
- end
20
+ manifest = YAML.load File.read file
52
21
 
53
- # filter by deployment
54
- pods = pods.filter { |pod| pod[:labels]["app"] == deployment }
22
+ services = manifest["services"].to_a
55
23
 
56
- if pods.length == 0
57
- error "Could not find pod for deployment #{deployment}."
58
- elsif pods.length > 1
59
- error "Found more than one pod for deployment #{deployment}. Multiple pods are not supported."
60
- end
24
+ if services.length != 1
25
+ error "Currently sct only supports a single service declaration in '#{file}'. Contact the infra guild if you consider this a limitation."
26
+ end
61
27
 
62
- pod = pods.first
28
+ service, service_spec = services.first
63
29
 
64
- if pod[:labels]["dev.okteto.com"] != "true"
65
- print "The current pod is running a production image and was not started by Okteto. Are you sure you want to continue? [y/N] ".red
30
+ container = service_spec["container_name"]
66
31
 
67
- answer = $stdin.readline.chomp.downcase
32
+ project = `docker container inspect --format '{{index .Config.Labels "com.docker.compose.project"}}' #{container}`.chomp
68
33
 
69
- if answer != "y"
70
- exit
71
- end
72
- end
34
+ if project == "spend-cloud"
35
+ print "This container was not started with 'sct dev'. Are you sure you want to continue? [y/N] ".red
73
36
 
74
- pod[:name]
75
- end
37
+ answer = $stdin.readline.chomp.downcase
76
38
 
77
- def error message
78
- UI.error message
79
- exit 1
39
+ if answer != "y"
40
+ exit
80
41
  end
42
+ end
81
43
 
44
+ system "docker exec -it #{container} #{command}"
82
45
  end
46
+
47
+ end
83
48
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sct
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.30
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Reshad Farid
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-27 00:00:00.000000000 Z
11
+ date: 2021-01-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: colored
@@ -200,16 +200,13 @@ files:
200
200
  - cluster/lib/cluster.rb
201
201
  - cluster/lib/cluster/commands_generator.rb
202
202
  - cluster/lib/cluster/module.rb
203
- - cluster/lib/cluster/resources/.DS_Store
204
- - cluster/lib/cluster/resources/corefile.yml
205
203
  - cluster/lib/cluster/runner.rb
206
204
  - sct/lib/.DS_Store
207
205
  - sct/lib/sct.rb
208
206
  - sct/lib/sct/.DS_Store
209
207
  - sct/lib/sct/cli_tools_distributor.rb
210
208
  - sct/lib/sct/command.rb
211
- - sct/lib/sct/commands/hostfile.rb
212
- - sct/lib/sct/commands/init.rb
209
+ - sct/lib/sct/commands/dev.rb
213
210
  - sct/lib/sct/commands/mysqlproxy.rb
214
211
  - sct/lib/sct/commands_generator.rb
215
212
  - sct/lib/sct/tools.rb
@@ -218,7 +215,6 @@ files:
218
215
  - sct_core/lib/sct_core.rb
219
216
  - sct_core/lib/sct_core/.DS_Store
220
217
  - sct_core/lib/sct_core/command_executor.rb
221
- - sct_core/lib/sct_core/config.rb
222
218
  - sct_core/lib/sct_core/core_ext/string.rb
223
219
  - sct_core/lib/sct_core/helper.rb
224
220
  - sct_core/lib/sct_core/module.rb
@@ -241,10 +237,10 @@ metadata:
241
237
  post_install_message:
242
238
  rdoc_options: []
243
239
  require_paths:
244
- - shell/lib
245
240
  - cluster/lib
246
241
  - sct/lib
247
242
  - sct_core/lib
243
+ - shell/lib
248
244
  required_ruby_version: !ruby/object:Gem::Requirement
249
245
  requirements:
250
246
  - - ">="
@@ -1,45 +0,0 @@
1
- apiVersion: v1
2
- data:
3
- Corefile: |
4
- .:53 {
5
- errors
6
- health {
7
- lameduck 5s
8
- }
9
- ready
10
- kubernetes cluster.local in-addr.arpa ip6.arpa {
11
- pods insecure
12
- fallthrough in-addr.arpa ip6.arpa
13
- ttl 30
14
- }
15
- prometheus :9153
16
- forward . 8.8.8.8
17
- cache 30
18
- loop
19
- reload
20
- loadbalance
21
- }
22
- Corefile-backup: |
23
- .:53 {
24
- errors
25
- health {
26
- lameduck 5s
27
- }
28
- ready
29
- kubernetes cluster.local in-addr.arpa ip6.arpa {
30
- pods insecure
31
- fallthrough in-addr.arpa ip6.arpa
32
- ttl 30
33
- }
34
- prometheus :9153
35
- forward . /etc/resolv.conf
36
- cache 30
37
- loop
38
- reload
39
- loadbalance
40
- }
41
- kind: ConfigMap
42
- metadata:
43
- creationTimestamp: null
44
- name: coredns
45
- selfLink: /api/v1/namespaces/kube-system/configmaps/coredns
@@ -1,76 +0,0 @@
1
- module Sct
2
- class HostfileCommand
3
-
4
- def execute(args, options)
5
- SctCore::Helper.ensure_permissions
6
-
7
- entries = [
8
- {
9
- host: "spend.cloud.local",
10
- comment: "The spend cloud ingress url"
11
- },
12
- {
13
- host: "mail.spend.cloud.local",
14
- comment: "The spend cloud mail url"
15
- },
16
- {
17
- host: "config.spend.cloud.local",
18
- comment: "The spend cloud config url"
19
- },
20
- {
21
- host: "spend-cloud.spend.cloud.local",
22
- comment: "The spend cloud web app url"
23
- },
24
- {
25
- host: "docs.spend.cloud.local",
26
- comment: "The spend cloud documentation url"
27
- },
28
- {
29
- host: "henk.spend.cloud.local",
30
- comment: "The spend cloud Henk web-interface"
31
- }
32
- ]
33
-
34
- is_windows = SctCore::Helper::is_windows?
35
-
36
- if is_windows
37
- ingress_address = "127.0.0.1"
38
- else
39
- ingress_address = `sudo -u $SUDO_USER minikube ip`.chomp
40
- end
41
-
42
- windows_hosts_path = "/mnt/c/Windows/System32/drivers/etc/hosts"
43
-
44
- if options.path
45
- hosts_paths = [options.path]
46
- else
47
- hosts_paths = ["/etc/hosts"]
48
-
49
- if is_windows
50
- hosts_paths << windows_hosts_path
51
- end
52
- end
53
-
54
- hosts_paths.each do |hosts_path|
55
- line_ending = hosts_path == windows_hosts_path ? "\r\n" : "\n"
56
-
57
- lines = File.readlines hosts_path
58
-
59
- # select the lines that do not include any entry
60
- lines = lines.select { |line| ! entries.any? { |entry| line.include? " #{entry[:host]}" } }
61
-
62
- # add entries
63
- entries.each do |entry|
64
- lines << "#{ingress_address} #{entry[:host]} # #{entry[:comment]}#{line_ending}"
65
- end
66
-
67
- File.write hosts_path, lines.join
68
-
69
- UI.success("Patched #{hosts_path} with #{ingress_address}")
70
- end
71
-
72
- end
73
-
74
- end
75
-
76
- end
@@ -1,37 +0,0 @@
1
- require 'sct_core/ui/ui'
2
- require 'sct_core/config'
3
-
4
- module Sct
5
-
6
- class InitCommand
7
-
8
- def execute(args, options)
9
-
10
- dir = SctCore::Config.dir
11
-
12
- cli = HighLine.new
13
-
14
- email = cli.ask("What is your email address?") { |q|
15
- q.validate = URI::MailTo::EMAIL_REGEXP
16
- }
17
-
18
- cloud_proxy_path = cli.ask("What is the path of your cloud proxy json credentials?") { |q|
19
- q.default = "~/.config/gcloud/application_default_credentials.json"
20
- }
21
-
22
- contents = ""
23
- contents << "email=#{email}\n"
24
- contents << "cloud-proxy-path=#{File.expand_path(cloud_proxy_path)}\n"
25
-
26
- if !File.directory?(dir)
27
- FileUtils.mkdir_p(dir)
28
- end
29
-
30
- File.write(SctCore::Config.path, contents)
31
-
32
- puts "Generated config file at #{SctCore::Config.path}"
33
- end
34
-
35
- end
36
-
37
- end
@@ -1,36 +0,0 @@
1
- module SctCore
2
- class Config
3
-
4
- def self.dir
5
- return "#{SctCore::Helper.homePath}/.config/sct"
6
- end
7
-
8
- def self.path
9
- return File.expand_path(File.join(self.dir, 'config'))
10
- end
11
-
12
- def self.exists
13
- return File.exists?(Config.path)
14
- end
15
-
16
- def self.get(key)
17
- config = self.read
18
-
19
- if !config.key?(key)
20
- return nil
21
- end
22
-
23
- return config[key]
24
- end
25
-
26
- def self.read
27
- if !self.exists
28
- return {}
29
- end
30
-
31
- contents = File.read(self.path)
32
-
33
- return SctCore::Helper.to_hash(contents)
34
- end
35
- end
36
- end