qtc-sdk 0.3.1 → 0.4.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.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +18 -18
  3. data/Changelog.md +23 -18
  4. data/Gemfile +4 -4
  5. data/LICENSE.txt +22 -22
  6. data/README.md +44 -44
  7. data/Rakefile +1 -1
  8. data/bin/qtc-cli +13 -13
  9. data/lib/qtc-sdk.rb +1 -1
  10. data/lib/qtc/cli/commands.rb +15 -15
  11. data/lib/qtc/cli/common.rb +146 -146
  12. data/lib/qtc/cli/eds/base.rb +27 -27
  13. data/lib/qtc/cli/eds/commands.rb +20 -20
  14. data/lib/qtc/cli/eds/instances.rb +30 -30
  15. data/lib/qtc/cli/mar/apps.rb +116 -116
  16. data/lib/qtc/cli/mar/base.rb +60 -60
  17. data/lib/qtc/cli/mar/commands.rb +266 -221
  18. data/lib/qtc/cli/mar/debug.rb +88 -88
  19. data/lib/qtc/cli/mar/domains.rb +35 -35
  20. data/lib/qtc/cli/mar/env.rb +38 -38
  21. data/lib/qtc/cli/mar/repository.rb +24 -24
  22. data/lib/qtc/cli/mar/slugs.rb +80 -0
  23. data/lib/qtc/cli/mar/ssl_certificates.rb +40 -40
  24. data/lib/qtc/cli/mar/stack.rb +29 -29
  25. data/lib/qtc/cli/mdb/base.rb +47 -47
  26. data/lib/qtc/cli/mdb/commands.rb +43 -43
  27. data/lib/qtc/cli/mdb/instances.rb +79 -79
  28. data/lib/qtc/cli/platform/clouds.rb +33 -33
  29. data/lib/qtc/cli/platform/commands.rb +132 -132
  30. data/lib/qtc/cli/platform/datacenters.rb +23 -23
  31. data/lib/qtc/cli/platform/ssh_keys.rb +41 -41
  32. data/lib/qtc/cli/platform/user.rb +25 -25
  33. data/lib/qtc/cli/platform/vpn.rb +93 -93
  34. data/lib/qtc/client.rb +170 -170
  35. data/lib/qtc/eds/client.rb +116 -116
  36. data/lib/qtc/eds/collection.rb +124 -124
  37. data/lib/qtc/eds/user_collection.rb +13 -13
  38. data/lib/qtc/eds/usergroup_collection.rb +41 -41
  39. data/lib/qtc/errors.rb +13 -13
  40. data/lib/qtc/version.rb +3 -3
  41. data/qtc-sdk.gemspec +28 -28
  42. data/spec/unit/qtc/client_spec.rb +147 -147
  43. metadata +4 -3
@@ -1,88 +1,88 @@
1
- require_relative 'base'
2
- require 'open3'
3
-
4
- module Qtc
5
- module Cli
6
- class Mar::Debug < Mar::Base
7
-
8
- def local_debug(commands, options)
9
- app_home = File.realpath('.')
10
- docker_id = nil
11
- stack = options.stack || 'cedar-14'
12
- puts "-----> Starting to build MAR app locally"
13
-
14
- if options.clean == true && File.exists?("#{app_home}/slug.tgz")
15
- File.delete("#{app_home}/slug.tgz")
16
- end
17
-
18
- unless File.exists?("#{app_home}/slug.tgz")
19
- docker_id = build_slug(app_home, stack)
20
- else
21
- puts " Existing slug.tgz found, build not needed."
22
- end
23
- puts "-----> Starting app container"
24
- run_opts = [
25
- '-e PORT=5000',
26
- "-e STACK=#{stack}",
27
- '-e SLUG_URL=file:///tmp/fake_slug.tgz',
28
- '-p 5000',
29
- "-v #{app_home}/slug.tgz:/tmp/fake_slug.tgz"
30
- ]
31
- if File.exists?("#{app_home}/.env")
32
- run_opts << "--env-file=#{app_home}/.env"
33
- end
34
- if commands.size == 0
35
- cmd = 'start web'
36
- else
37
- cmd = commands.join(" ")
38
- end
39
-
40
- exec("docker run -it #{run_opts.join(" ")} qtcs/slugrunner:#{stack} #{cmd}")
41
- end
42
-
43
- def local_build_slug(options)
44
- stack = options.stack || 'cedar-14'
45
- app_home = File.realpath('.')
46
- puts "-----> Starting to build MAR app locally"
47
- build_slug(app_home, stack)
48
- end
49
-
50
- def build_slug(app_home, stack)
51
- docker_id = nil
52
- run_opts = ''
53
- if File.exists?("#{app_home}/.env")
54
- run_opts << "--env-file=#{app_home}/.env"
55
- end
56
- Open3.popen3("docker run -d #{run_opts} -v #{app_home}:/tmp/gitrepo:r qtcs/slugbuilder:#{stack}") {|stdin, stdout, stderr, wait_thr|
57
- docker_id = stdout.gets
58
- if docker_id
59
- docker_id.strip!
60
- else
61
- puts stderr.gets
62
- end
63
- exit_status = wait_thr.value
64
- unless exit_status.success?
65
- raise "ERROR: build failed to start"
66
- end
67
- }
68
- Open3.popen2('docker', 'attach', docker_id){|stdin, stdout, wait_thr|
69
- stdin.close
70
- while line = stdout.gets
71
- puts line
72
- end
73
- exit_status = wait_thr.value
74
- unless exit_status.success?
75
- raise "ERROR: build failed to complete"
76
- end
77
- }
78
- puts "-----> Extracting slug from build image to ./slug.tgz"
79
- system("docker cp #{docker_id}:/tmp/slug.tgz . > /dev/null")
80
-
81
- docker_id
82
- rescue => exc
83
- system("docker rm -f #{docker_id}") if docker_id
84
- raise exc
85
- end
86
- end
87
- end
88
- end
1
+ require_relative 'base'
2
+ require 'open3'
3
+
4
+ module Qtc
5
+ module Cli
6
+ class Mar::Debug < Mar::Base
7
+
8
+ def local_debug(commands, options)
9
+ app_home = File.realpath('.')
10
+ docker_id = nil
11
+ stack = options.stack || 'cedar-14'
12
+ puts "-----> Starting to build MAR app locally"
13
+
14
+ if options.clean == true && File.exists?("#{app_home}/slug.tgz")
15
+ File.delete("#{app_home}/slug.tgz")
16
+ end
17
+
18
+ unless File.exists?("#{app_home}/slug.tgz")
19
+ docker_id = build_slug(app_home, stack)
20
+ else
21
+ puts " Existing slug.tgz found, build not needed."
22
+ end
23
+ puts "-----> Starting app container"
24
+ run_opts = [
25
+ '-e PORT=5000',
26
+ "-e STACK=#{stack}",
27
+ '-e SLUG_URL=file:///tmp/fake_slug.tgz',
28
+ '-p 5000',
29
+ "-v #{app_home}/slug.tgz:/tmp/fake_slug.tgz"
30
+ ]
31
+ if File.exists?("#{app_home}/.env")
32
+ run_opts << "--env-file=#{app_home}/.env"
33
+ end
34
+ if commands.size == 0
35
+ cmd = 'start web'
36
+ else
37
+ cmd = commands.join(" ")
38
+ end
39
+
40
+ exec("docker run -it #{run_opts.join(" ")} qtcs/slugrunner:#{stack} #{cmd}")
41
+ end
42
+
43
+ def local_build_slug(options)
44
+ stack = options.stack || 'cedar-14'
45
+ app_home = File.realpath('.')
46
+ puts "-----> Starting to build MAR app locally"
47
+ build_slug(app_home, stack)
48
+ end
49
+
50
+ def build_slug(app_home, stack)
51
+ docker_id = nil
52
+ run_opts = ''
53
+ if File.exists?("#{app_home}/.env")
54
+ run_opts << "--env-file=#{app_home}/.env"
55
+ end
56
+ Open3.popen3("docker run -d #{run_opts} -v #{app_home}:/tmp/gitrepo:r qtcs/slugbuilder:#{stack}") {|stdin, stdout, stderr, wait_thr|
57
+ docker_id = stdout.gets
58
+ if docker_id
59
+ docker_id.strip!
60
+ else
61
+ puts stderr.gets
62
+ end
63
+ exit_status = wait_thr.value
64
+ unless exit_status.success?
65
+ raise "ERROR: build failed to start"
66
+ end
67
+ }
68
+ Open3.popen2('docker', 'attach', docker_id){|stdin, stdout, wait_thr|
69
+ stdin.close
70
+ while line = stdout.gets
71
+ puts line
72
+ end
73
+ exit_status = wait_thr.value
74
+ unless exit_status.success?
75
+ raise "ERROR: build failed to complete"
76
+ end
77
+ }
78
+ puts "-----> Extracting slug from build image to ./slug.tgz"
79
+ system("docker cp #{docker_id}:/tmp/slug.tgz . > /dev/null")
80
+
81
+ docker_id
82
+ rescue => exc
83
+ system("docker rm -f #{docker_id}") if docker_id
84
+ raise exc
85
+ end
86
+ end
87
+ end
88
+ end
@@ -1,35 +1,35 @@
1
- require_relative 'base'
2
-
3
- module Qtc
4
- module Cli
5
- class Mar::Domains < Mar::Base
6
-
7
- def list(options)
8
- instance_id = resolve_instance_id(options)
9
- instance_data = instance_info(instance_id)
10
- if instance_data
11
- result = client.get("/apps/#{instance_id}/domains", nil, {'Authorization' => "Bearer #{current_cloud_token}"})
12
- result['results'].each do |r|
13
- print color("* #{r['name']}", :bold)
14
- end
15
- end
16
- end
17
-
18
- def create(name, options)
19
- instance_id = resolve_instance_id(options)
20
- instance_data = instance_info(instance_id)
21
- if instance_data
22
- client.post("/apps/#{instance_id}/domains", {name: name}, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
23
- end
24
- end
25
-
26
- def destroy(name, options)
27
- instance_id = resolve_instance_id(options)
28
- instance_data = instance_info(instance_id)
29
- if instance_data
30
- client.delete("/apps/#{instance_id}/domains/#{name}", nil, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
31
- end
32
- end
33
- end
34
- end
35
- end
1
+ require_relative 'base'
2
+
3
+ module Qtc
4
+ module Cli
5
+ class Mar::Domains < Mar::Base
6
+
7
+ def list(options)
8
+ instance_id = resolve_instance_id(options)
9
+ instance_data = instance_info(instance_id)
10
+ if instance_data
11
+ result = client.get("/apps/#{instance_id}/domains", nil, {'Authorization' => "Bearer #{current_cloud_token}"})
12
+ result['results'].each do |r|
13
+ print color("* #{r['name']}", :bold)
14
+ end
15
+ end
16
+ end
17
+
18
+ def create(name, options)
19
+ instance_id = resolve_instance_id(options)
20
+ instance_data = instance_info(instance_id)
21
+ if instance_data
22
+ client.post("/apps/#{instance_id}/domains", {name: name}, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
23
+ end
24
+ end
25
+
26
+ def destroy(name, options)
27
+ instance_id = resolve_instance_id(options)
28
+ instance_data = instance_info(instance_id)
29
+ if instance_data
30
+ client.delete("/apps/#{instance_id}/domains/#{name}", nil, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,38 +1,38 @@
1
- require_relative 'base'
2
-
3
- module Qtc
4
- module Cli
5
- class Mar::Env < Mar::Base
6
-
7
- def set(vars, options)
8
- instance_id = resolve_instance_id(options)
9
- env_vars = {}
10
- vars.each do |type|
11
- arr = type.strip.split('=', 2)
12
- if arr[0]
13
- if arr[1].nil? || arr[1] == ''
14
- env_vars[arr[0]] = nil
15
- else
16
- env_vars[arr[0]] = arr[1]
17
- end
18
- end
19
- end
20
- instance_data = instance_info(instance_id)
21
- if instance_data
22
- client.put("/apps/#{instance_id}/env_vars", env_vars, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
23
- end
24
- end
25
-
26
- def show(options)
27
- instance_id = resolve_instance_id(options)
28
- instance_data = instance_info(instance_id)
29
- if instance_data
30
- env_vars = client.get("/apps/#{instance_id}/env_vars", {}, {'Authorization' => "Bearer #{current_cloud_token}"})
31
- env_vars.each do |key, value|
32
- puts "#{key}=#{value}"
33
- end
34
- end
35
- end
36
- end
37
- end
38
- end
1
+ require_relative 'base'
2
+
3
+ module Qtc
4
+ module Cli
5
+ class Mar::Env < Mar::Base
6
+
7
+ def set(vars, options)
8
+ instance_id = resolve_instance_id(options)
9
+ env_vars = {}
10
+ vars.each do |type|
11
+ arr = type.strip.split('=', 2)
12
+ if arr[0]
13
+ if arr[1].nil? || arr[1] == ''
14
+ env_vars[arr[0]] = nil
15
+ else
16
+ env_vars[arr[0]] = arr[1]
17
+ end
18
+ end
19
+ end
20
+ instance_data = instance_info(instance_id)
21
+ if instance_data
22
+ client.put("/apps/#{instance_id}/env_vars", env_vars, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
23
+ end
24
+ end
25
+
26
+ def show(options)
27
+ instance_id = resolve_instance_id(options)
28
+ instance_data = instance_info(instance_id)
29
+ if instance_data
30
+ env_vars = client.get("/apps/#{instance_id}/env_vars", {}, {'Authorization' => "Bearer #{current_cloud_token}"})
31
+ env_vars.each do |key, value|
32
+ puts "#{key}=#{value}"
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -1,24 +1,24 @@
1
- require_relative 'base'
2
-
3
- module Qtc
4
- module Cli
5
- class Mar::Repository < Mar::Base
6
-
7
- def purge_cache(options)
8
- instance_id = resolve_instance_id(options)
9
- instance_data = instance_info(instance_id)
10
- if instance_data
11
- client.delete("/apps/#{instance_id}/build_cache", nil, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
12
- end
13
- end
14
-
15
- def reset(options)
16
- instance_id = resolve_instance_id(options)
17
- instance_data = instance_info(instance_id)
18
- if instance_data
19
- client.delete("/apps/#{instance_id}/repository", nil, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
20
- end
21
- end
22
- end
23
- end
24
- end
1
+ require_relative 'base'
2
+
3
+ module Qtc
4
+ module Cli
5
+ class Mar::Repository < Mar::Base
6
+
7
+ def purge_cache(options)
8
+ instance_id = resolve_instance_id(options)
9
+ instance_data = instance_info(instance_id)
10
+ if instance_data
11
+ client.delete("/apps/#{instance_id}/build_cache", nil, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
12
+ end
13
+ end
14
+
15
+ def reset(options)
16
+ instance_id = resolve_instance_id(options)
17
+ instance_data = instance_info(instance_id)
18
+ if instance_data
19
+ client.delete("/apps/#{instance_id}/repository", nil, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,80 @@
1
+ require_relative 'base'
2
+
3
+ require 'yaml'
4
+ require 'fileutils'
5
+ require 'httpclient'
6
+ require 'net/http'
7
+
8
+ module Qtc
9
+ module Cli
10
+ class Mar::Slugs < Mar::Base
11
+
12
+ def list(options)
13
+ instance_id = resolve_instance_id(options)
14
+ slugs = client.get("/apps/#{instance_id}/slugs/", {}, {'Authorization' => "Bearer #{current_cloud_token}"})
15
+ if slugs && slugs['results'].size > 0
16
+ template = "%-20.20s %-30.30s %-30.30s"
17
+ puts template % ["TAG", "CREATED", "DEPLOYED"]
18
+ slugs['results'].each do |slug|
19
+ puts template % [slug['tag'], slug['createdAt'], slug['deployedAt']]
20
+ end
21
+ end
22
+ end
23
+
24
+ def remove(slug_id, options)
25
+ instance_id = resolve_instance_id(options)
26
+ client.delete("/apps/#{instance_id}/slugs/#{slug_id}", {}, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
27
+ end
28
+
29
+ def upload(options)
30
+ instance_id = resolve_instance_id(options)
31
+
32
+ slug = create_slug(instance_id, options)
33
+ upload_uri = URI(slug['blob']['url'])
34
+ puts "Starting slug upload, if your slug is large this may take a while"
35
+ # todo Would be nice to have some sort of progress indication...
36
+ begin
37
+ open(File.new(options.slug), 'rb') do |io|
38
+ aws_client = Net::HTTP.new(upload_uri.host)
39
+ req = Net::HTTP::Put.new(upload_uri.request_uri)
40
+ req.content_length = io.size
41
+ req.body_stream = io
42
+ req['Content-Type'] = 'application/octet-stream'
43
+
44
+ aws_client.request(req)
45
+ end
46
+ rescue => exc
47
+ puts "Slug upload failed:#{exc.to_s}"
48
+ raise StandardError "Slug upload failed!"
49
+ end
50
+ puts "Slug uploaded successfully, you may now deploy it using commit tag: #{slug['tag']}"
51
+ end
52
+
53
+ def deploy(slug_id, options)
54
+ instance_id = resolve_instance_id(options)
55
+ client.post("/apps/#{instance_id}/slugs/#{slug_id}/deploy", {}, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
56
+ end
57
+
58
+ def create_slug(instance_id, options)
59
+ process_types = resolve_proc_types(options)
60
+ data = {
61
+ tag: options.tag,
62
+ process_types: process_types
63
+ }
64
+ client.post("/apps/#{instance_id}/slugs", data, {}, {'Authorization' => "Bearer #{current_cloud_token}"})
65
+ end
66
+
67
+ def resolve_proc_types(options)
68
+ if options.procfile
69
+ procfile_hash = {}
70
+ procfile = YAML.load(File.read(options.procfile), :encoding => 'utf-8')
71
+ procfile_hash.merge!(procfile) if procfile
72
+ procfile_hash
73
+ else
74
+ raise StandardError 'Procfile must be given'
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
80
+