sct 0.1.35 → 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 +4 -4
- data/cluster/lib/cluster/commands_generator.rb +78 -73
- data/cluster/lib/cluster/runner.rb +53 -323
- data/sct/lib/sct/commands/dev.rb +43 -0
- data/sct/lib/sct/commands/mysqlproxy.rb +5 -11
- data/sct/lib/sct/commands_generator.rb +11 -27
- data/sct/lib/sct/version.rb +1 -1
- data/sct_core/lib/sct_core.rb +1 -2
- data/sct_core/lib/sct_core/helper.rb +7 -6
- data/shell/lib/shell/runner.rb +28 -63
- metadata +3 -7
- data/cluster/lib/cluster/resources/.DS_Store +0 -0
- data/cluster/lib/cluster/resources/corefile.yml +0 -45
- data/sct/lib/sct/commands/hostfile.rb +0 -76
- data/sct/lib/sct/commands/init.rb +0 -37
- data/sct_core/lib/sct_core/config.rb +0 -36
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8be150a1d5ddc9339df696d2f7db5d6056dfdba0fbb48884e57cfacc700b79ea
|
4
|
+
data.tar.gz: d6fc67a9a3af7c51bf542353f476ec59b60f1c40e7387da64910c4287be857c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
|
6
|
-
|
5
|
+
class CommandsGenerator
|
6
|
+
include Commander::Methods
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
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
|
-
|
39
|
-
c.syntax = "sct cluster restart"
|
40
|
-
c.description = "restart the cluster"
|
17
|
+
global_option('--verbose') { $verbose = true }
|
41
18
|
|
42
|
-
|
43
|
-
|
44
|
-
|
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
|
-
|
25
|
+
c.action do |args, options|
|
26
|
+
Cluster::Runner.new.start args, options
|
27
|
+
end
|
28
|
+
end
|
47
29
|
|
48
|
-
|
49
|
-
|
50
|
-
|
30
|
+
command :stop do |c|
|
31
|
+
c.syntax = 'sct cluster stop'
|
32
|
+
c.description = 'stop the cluster'
|
51
33
|
|
52
|
-
|
53
|
-
|
54
|
-
|
34
|
+
c.action do |args, options|
|
35
|
+
Cluster::Runner.new.stop
|
36
|
+
end
|
37
|
+
end
|
55
38
|
|
56
|
-
|
39
|
+
command :restart do |c|
|
40
|
+
c.syntax = "sct cluster restart"
|
41
|
+
c.description = "restart the cluster"
|
57
42
|
|
58
|
-
|
59
|
-
|
60
|
-
|
43
|
+
c.action do |args, options|
|
44
|
+
Cluster::Runner.new.restart
|
45
|
+
end
|
46
|
+
end
|
61
47
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
end
|
48
|
+
command :delete do |c|
|
49
|
+
c.syntax = "sct cluster delete"
|
50
|
+
c.description = "delete the cluster"
|
66
51
|
|
67
|
-
|
68
|
-
|
69
|
-
|
52
|
+
c.action do |args, options|
|
53
|
+
Cluster::Runner.new.delete
|
54
|
+
end
|
55
|
+
end
|
70
56
|
|
71
|
-
|
72
|
-
|
73
|
-
|
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
|
-
|
77
|
-
|
78
|
-
|
61
|
+
c.action do |args, options|
|
62
|
+
Cluster::Runner.new.reset args, options
|
63
|
+
end
|
64
|
+
end
|
79
65
|
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
end
|
66
|
+
command :pull do |c|
|
67
|
+
c.syntax = 'sct cluster pull'
|
68
|
+
c.description = 'pull new image versions'
|
84
69
|
|
85
|
-
|
86
|
-
|
87
|
-
|
70
|
+
c.action do |args, options|
|
71
|
+
Cluster::Runner.new.pull
|
72
|
+
end
|
73
|
+
end
|
88
74
|
|
89
|
-
|
90
|
-
|
91
|
-
|
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
|
-
|
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,343 +1,73 @@
|
|
1
1
|
module Cluster
|
2
|
-
|
2
|
+
class Runner
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
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
|
-
create_keycloak_database_user
|
23
|
-
run_command "kubectl apply -f ~/development/spend-cloud/k8s/keycloak-server.yml"
|
24
|
-
wait_for_pods
|
25
|
-
run_command "kubectl apply -f ~/development/spend-cloud/k8s/"
|
26
|
-
end
|
27
|
-
|
28
|
-
post_start
|
29
|
-
end
|
30
|
-
|
31
|
-
def stop
|
32
|
-
run_command "minikube stop"
|
33
|
-
end
|
34
|
-
|
35
|
-
def restart
|
36
|
-
SctCore::Helper.ensure_windows_administrator # "sct hostfile" will need it later on
|
37
|
-
|
38
|
-
stop
|
39
|
-
start
|
40
|
-
end
|
41
|
-
|
42
|
-
def delete
|
43
|
-
run_command "minikube delete"
|
44
|
-
end
|
45
|
-
|
46
|
-
def reset
|
47
|
-
SctCore::Helper.ensure_windows_administrator # "sct hostfile" will need it later on
|
48
|
-
|
49
|
-
delete
|
50
|
-
start
|
51
|
-
end
|
52
|
-
|
53
|
-
def status
|
54
|
-
print_contexts
|
55
|
-
print_minikube_status
|
56
|
-
|
57
|
-
if get_minikube_status.find_all { |status| status[1] == 'Stopped' }.count == 0
|
58
|
-
print_pods_status("kube-system")
|
59
|
-
print_pods_status
|
60
|
-
else
|
61
|
-
UI.important("Please check your minikube status. If all services are stopped you should start the minikube first.")
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def update_config
|
66
|
-
run_command "kubectl config use-context minikube"
|
67
|
-
|
68
|
-
run_command "kubectl replace -n kube-system -f #{File.expand_path('resources/corefile.yml', __dir__)}"
|
69
|
-
run_command "kubectl rollout restart -n kube-system deployment coredns"
|
70
|
-
run_command "kubectl rollout status -n kube-system deployment coredns"
|
71
|
-
end
|
72
|
-
|
73
|
-
def apply_deployments
|
74
|
-
run_command "kubectl apply -f ~/development/spend-cloud/k8s/"
|
75
|
-
end
|
76
|
-
|
77
|
-
|
78
|
-
def cluster_exists?
|
79
|
-
if system "minikube status", { out: "/dev/null" }
|
80
|
-
# cluster exists and is running
|
81
|
-
return true
|
82
|
-
end
|
83
|
-
|
84
|
-
if $?.exitstatus == 85
|
85
|
-
# cluster does not exist
|
86
|
-
return false
|
87
|
-
end
|
88
|
-
|
89
|
-
# cluster exists but is stopped
|
90
|
-
return true
|
91
|
-
end
|
92
|
-
|
93
|
-
def start_cluster
|
94
|
-
if SctCore::Helper.operatingSystem == SctCore::Helper::MAC_OS
|
95
|
-
run_command "minikube start --driver=hyperkit --vm=true --cpus=$(sysctl -n hw.ncpu) --memory=8G"
|
96
|
-
else
|
97
|
-
run_command "minikube start --driver=docker --cpus=$(cat /proc/cpuinfo | grep processor | wc -l) --memory=3G"
|
98
|
-
end
|
99
|
-
update_config
|
100
|
-
end
|
101
|
-
|
102
|
-
def post_start
|
103
|
-
wait_for_pods
|
104
|
-
copy_proactive_accounts_file
|
105
|
-
if SctCore::Helper.operatingSystem == SctCore::Helper::UBUNTU
|
106
|
-
UI.success("\nAdding SSH tunnel to port 443!")
|
107
|
-
run_command "sudo ssh -f -N -i $(minikube ssh-key) docker@$(minikube ip) -L 443:127.0.0.1:443"
|
108
|
-
end
|
109
|
-
# run_command "sudo sct hostfile"
|
110
|
-
run_command "minikube tunnel &", { out: "/dev/null", err: "/dev/null" } if SctCore::Helper::is_windows? # leave this running detached forever in the background
|
111
|
-
UI.success("\n✔️ You can visit your environment at 👉 https://spend-cloud.dev.spend.cloud 👌")
|
112
|
-
end
|
113
|
-
|
114
|
-
def enable_addons
|
115
|
-
enable_addon "registry-creds"
|
116
|
-
enable_addon "ingress"
|
117
|
-
end
|
118
|
-
|
119
|
-
def enable_addon(addon)
|
120
|
-
run_command "minikube addons enable #{addon}"
|
121
|
-
|
122
|
-
deployment = deployments("kube-system").find { |deployment| deployment[:name].include? addon }
|
123
|
-
|
124
|
-
run_command "kubectl rollout status -n kube-system deployment #{deployment[:name]}"
|
125
|
-
end
|
126
|
-
|
127
|
-
def wait_for_pods
|
128
|
-
UI.important("Waiting for pods to become ready...")
|
129
|
-
|
130
|
-
previous_lines = 0
|
131
|
-
|
132
|
-
while ! pods.all? { |pod| pod[:ready] }
|
133
|
-
pods_status_lines = get_pods_status.to_s.lines.map { |line| line.chomp }
|
134
|
-
|
135
|
-
current_lines = pods_status_lines.length
|
136
|
-
|
137
|
-
line_difference = current_lines - previous_lines
|
138
|
-
|
139
|
-
if line_difference < 0 # there are now less lines than before
|
140
|
-
line_difference.abs.times do
|
141
|
-
print "\033[1A\033[K" # move the cursor up a line and clear the line
|
142
|
-
end
|
143
|
-
|
144
|
-
print "\033[#{current_lines}A" # move the cursor all the way up to the start of the table
|
145
|
-
elsif previous_lines > 0
|
146
|
-
print "\033[#{previous_lines}A" # move the cursor all the way up to the start of the table
|
147
|
-
end
|
148
|
-
|
149
|
-
pods_status_lines.each do |line|
|
150
|
-
print "#{line}\033[K#{$/}" # print the content of the line, clear remaining characters and add a new line
|
151
|
-
end
|
152
|
-
|
153
|
-
previous_lines = current_lines
|
154
|
-
|
155
|
-
sleep 5
|
156
|
-
end
|
157
|
-
|
158
|
-
previous_lines.times do
|
159
|
-
print "\033[1A\033[K" # move the cursor up a line and clear the line
|
160
|
-
end
|
161
|
-
|
162
|
-
UI.success("Pods are now ready.")
|
163
|
-
end
|
164
|
-
|
165
|
-
def deployments(namespace = "default")
|
166
|
-
output = `kubectl get deployments -n #{namespace}`
|
167
|
-
|
168
|
-
# split output lines
|
169
|
-
lines = output.split "\n"
|
170
|
-
|
171
|
-
# exclude first line (table header)
|
172
|
-
lines = lines[1..-1]
|
173
|
-
|
174
|
-
# get name and status of each pod
|
175
|
-
lines.map do |line|
|
176
|
-
columns = line.split(" ")
|
177
|
-
|
178
|
-
name = columns[0]
|
179
|
-
|
180
|
-
{
|
181
|
-
name: name
|
182
|
-
}
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
def pods(namespace = "default")
|
187
|
-
output = `kubectl get pods -n #{namespace}`
|
188
|
-
|
189
|
-
# split output lines
|
190
|
-
lines = output.split "\n"
|
191
|
-
|
192
|
-
# exclude first line (table header)
|
193
|
-
lines = lines[1..-1]
|
194
|
-
|
195
|
-
# get name and status of each pod
|
196
|
-
lines.map do |line|
|
197
|
-
columns = line.split(" ")
|
198
|
-
|
199
|
-
name = columns[0]
|
200
|
-
ready = columns[1].split("/").reduce { |l, r| l == r }
|
201
|
-
replicas = columns[1]
|
202
|
-
status = columns[2]
|
203
|
-
|
204
|
-
{
|
205
|
-
name: name,
|
206
|
-
ready: ready,
|
207
|
-
replicas: replicas,
|
208
|
-
status: status
|
209
|
-
}
|
210
|
-
end
|
4
|
+
def run command, options = {}
|
5
|
+
begin
|
6
|
+
if !system command, options
|
7
|
+
raise command.red
|
211
8
|
end
|
9
|
+
rescue Interrupt
|
10
|
+
# user pressed Ctrl+C, do nothing
|
11
|
+
end
|
12
|
+
end
|
212
13
|
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
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\"}}}'"
|
217
|
-
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"
|
218
|
-
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\"}}}'"
|
219
|
-
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\""
|
220
|
-
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\"}}}'"
|
221
|
-
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"
|
222
|
-
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\"}}}'"
|
223
|
-
end
|
224
|
-
|
225
|
-
def wait_for_gcr_secret
|
226
|
-
UI.important("Waiting for Google Cloud Registry secret to become available...")
|
227
|
-
|
228
|
-
while ! `kubectl get secrets`.include? "gcr-secret"
|
229
|
-
sleep 5
|
230
|
-
end
|
231
|
-
|
232
|
-
UI.success("Google Cloud Registry secret is now available.")
|
233
|
-
end
|
234
|
-
|
235
|
-
def wait_for_ingress_ip
|
236
|
-
UI.important("Waiting for ingress IP to become available...")
|
237
|
-
|
238
|
-
while `kubectl describe ingress | grep "Address" | awk '{print $2}'`.empty?
|
239
|
-
sleep 5
|
240
|
-
end
|
241
|
-
|
242
|
-
UI.success("Ingress IP is now available.")
|
243
|
-
end
|
244
|
-
|
245
|
-
def print_contexts
|
246
|
-
output = `kubectl config get-contexts`
|
247
|
-
|
248
|
-
lines = output.split "\n"
|
249
|
-
lines = lines[1..-1]
|
250
|
-
|
251
|
-
rows = lines.map do |line|
|
252
|
-
columns = line.split(" ")
|
253
|
-
|
254
|
-
current_context = columns[0] == "*" ? "Yes".green : "No".red
|
255
|
-
|
256
|
-
[columns[2], current_context]
|
257
|
-
end
|
258
|
-
|
259
|
-
puts Terminal::Table.new title: "Contexts".green, headings: ['Cluster', 'Using context'], rows: rows
|
260
|
-
end
|
261
|
-
|
262
|
-
def print_minikube_status
|
263
|
-
puts Terminal::Table.new title: "Minikube status".green, headings: ['Name', 'Status'], rows: get_minikube_status
|
264
|
-
end
|
265
|
-
|
266
|
-
def get_minikube_status
|
267
|
-
output = `minikube status`
|
268
|
-
|
269
|
-
lines = output.split "\n"
|
270
|
-
|
271
|
-
rows = lines.map do |line|
|
272
|
-
columns = line.split(" ")
|
273
|
-
|
274
|
-
[columns[0][0..-2], columns[1]]
|
275
|
-
end
|
276
|
-
end
|
14
|
+
def run_dc command, options = {}
|
15
|
+
run "docker-compose -f ~/development/spend-cloud/docker-compose.yml #{command}", options
|
16
|
+
end
|
277
17
|
|
278
|
-
|
279
|
-
|
18
|
+
def start args, options
|
19
|
+
if options.pull
|
20
|
+
run_dc "pull"
|
21
|
+
end
|
280
22
|
|
281
|
-
|
282
|
-
|
23
|
+
if options.build
|
24
|
+
run_dc "build #{options.pull ? "--pull" : ""}"
|
25
|
+
end
|
283
26
|
|
284
|
-
|
285
|
-
rows = pods(namespace).map do |pod|
|
286
|
-
status = pod[:status]
|
287
|
-
replicas = pod[:replicas]
|
27
|
+
run_dc "up --detach"
|
288
28
|
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
pod[:ready] ? replicas.green : replicas.red
|
293
|
-
]
|
294
|
-
end
|
29
|
+
if options.pull or options.build
|
30
|
+
system "docker image prune -f"
|
31
|
+
end
|
295
32
|
|
296
|
-
|
297
|
-
|
298
|
-
end
|
33
|
+
UI.success("\n✔️ You can visit your environment at 👉 https://spend-cloud.dev.spend.cloud 👌")
|
34
|
+
end
|
299
35
|
|
300
|
-
|
301
|
-
|
36
|
+
def stop
|
37
|
+
run_dc "down --remove-orphans"
|
38
|
+
end
|
302
39
|
|
303
|
-
|
304
|
-
|
305
|
-
|
40
|
+
def restart
|
41
|
+
run_dc "restart"
|
42
|
+
end
|
306
43
|
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
rescue => e
|
311
|
-
UI.important("Copying ProActive accounts file to deployments...")
|
312
|
-
src_path = "#{Dir.home()}/development/spend-cloud/k8s/conf/proactive_accounts.ini"
|
313
|
-
command = "kubectl cp #{src_path} #{pod_id}:/data/proactive_accounts.ini -c #{container_name}"
|
314
|
-
run_command command
|
315
|
-
end
|
44
|
+
def delete
|
45
|
+
run_dc "down --remove-orphans -v"
|
46
|
+
end
|
316
47
|
|
317
|
-
|
318
|
-
|
48
|
+
def reset args, options
|
49
|
+
delete
|
50
|
+
start args, options
|
51
|
+
end
|
319
52
|
|
320
|
-
|
321
|
-
|
322
|
-
|
53
|
+
def pull
|
54
|
+
run_dc "pull"
|
55
|
+
run "docker image prune -f"
|
56
|
+
end
|
323
57
|
|
324
|
-
|
325
|
-
|
326
|
-
|
58
|
+
def status
|
59
|
+
run_dc "ps"
|
60
|
+
end
|
327
61
|
|
328
|
-
|
329
|
-
|
330
|
-
run_command "kubectl exec #{pod_id} -- mysql -e '#{create_database}' >> /dev/null"
|
62
|
+
def logs args, options
|
63
|
+
command = "logs"
|
331
64
|
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
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
|
336
68
|
|
337
|
-
|
338
|
-
if ! system command, options
|
339
|
-
raise command.red
|
340
|
-
end
|
341
|
-
end
|
69
|
+
run_dc "#{command} #{args.join " "}"
|
342
70
|
end
|
71
|
+
|
72
|
+
end
|
343
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
|
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
|
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!
|
data/sct/lib/sct/version.rb
CHANGED
data/sct_core/lib/sct_core.rb
CHANGED
@@ -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
|
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.
|
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.
|
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
|
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
|
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.
|
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
|
data/shell/lib/shell/runner.rb
CHANGED
@@ -1,83 +1,48 @@
|
|
1
1
|
require 'yaml'
|
2
2
|
|
3
3
|
module Shell
|
4
|
-
|
4
|
+
class Runner
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
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
|
-
|
36
|
-
|
37
|
-
columns = line.split " "
|
11
|
+
def launch
|
12
|
+
command = ARGV.empty? ? "sh" : ARGV.join(" ")
|
38
13
|
|
39
|
-
|
14
|
+
file = "docker-compose.dev.yml"
|
40
15
|
|
41
|
-
|
42
|
-
|
43
|
-
|
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
|
-
|
54
|
-
pods = pods.filter { |pod| pod[:labels]["app"] == deployment }
|
22
|
+
services = manifest["services"].to_a
|
55
23
|
|
56
|
-
|
57
|
-
|
58
|
-
|
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
|
-
|
28
|
+
service, service_spec = services.first
|
63
29
|
|
64
|
-
|
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
|
-
|
32
|
+
project = `docker container inspect --format '{{index .Config.Labels "com.docker.compose.project"}}' #{container}`.chomp
|
68
33
|
|
69
|
-
|
70
|
-
|
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
|
-
|
75
|
-
end
|
37
|
+
answer = $stdin.readline.chomp.downcase
|
76
38
|
|
77
|
-
|
78
|
-
|
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.
|
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:
|
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/
|
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
|
Binary file
|
@@ -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
|