qtc-sdk 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +18 -18
  3. data/.rspec +2 -0
  4. data/.travis.yml +7 -0
  5. data/Changelog.md +28 -23
  6. data/Gemfile +4 -4
  7. data/LICENSE.txt +22 -22
  8. data/README.md +42 -44
  9. data/Rakefile +1 -1
  10. data/bin/qtc-cli +13 -13
  11. data/lib/qtc-sdk.rb +1 -1
  12. data/lib/qtc/cli/commands.rb +15 -15
  13. data/lib/qtc/cli/common.rb +146 -146
  14. data/lib/qtc/cli/eds/base.rb +27 -27
  15. data/lib/qtc/cli/eds/commands.rb +20 -20
  16. data/lib/qtc/cli/eds/instances.rb +30 -30
  17. data/lib/qtc/cli/mar/apps.rb +116 -116
  18. data/lib/qtc/cli/mar/base.rb +60 -60
  19. data/lib/qtc/cli/mar/commands.rb +268 -266
  20. data/lib/qtc/cli/mar/debug.rb +94 -88
  21. data/lib/qtc/cli/mar/domains.rb +35 -35
  22. data/lib/qtc/cli/mar/env.rb +38 -38
  23. data/lib/qtc/cli/mar/repository.rb +24 -24
  24. data/lib/qtc/cli/mar/slugs.rb +80 -80
  25. data/lib/qtc/cli/mar/ssl_certificates.rb +40 -40
  26. data/lib/qtc/cli/mar/stack.rb +29 -29
  27. data/lib/qtc/cli/mdb/base.rb +47 -47
  28. data/lib/qtc/cli/mdb/commands.rb +43 -43
  29. data/lib/qtc/cli/mdb/instances.rb +79 -79
  30. data/lib/qtc/cli/platform/clouds.rb +33 -33
  31. data/lib/qtc/cli/platform/commands.rb +133 -132
  32. data/lib/qtc/cli/platform/datacenters.rb +23 -23
  33. data/lib/qtc/cli/platform/ssh_keys.rb +41 -41
  34. data/lib/qtc/cli/platform/user.rb +29 -25
  35. data/lib/qtc/cli/platform/vpn.rb +93 -93
  36. data/lib/qtc/client.rb +170 -170
  37. data/lib/qtc/eds/client.rb +116 -116
  38. data/lib/qtc/eds/collection.rb +124 -124
  39. data/lib/qtc/eds/user_collection.rb +13 -13
  40. data/lib/qtc/eds/usergroup_collection.rb +41 -41
  41. data/lib/qtc/errors.rb +13 -13
  42. data/lib/qtc/version.rb +3 -3
  43. data/qtc-sdk.gemspec +28 -28
  44. data/spec/spec_helper.rb +17 -0
  45. data/spec/unit/qtc/client_spec.rb +147 -147
  46. metadata +5 -3
@@ -1,88 +1,94 @@
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
+ stack = options.stack || 'cedar-14'
11
+ branch = options.branch || 'master'
12
+ puts "-----> Starting to build MAR app locally"
13
+ puts " Using stack: #{stack}"
14
+ puts " Using git branch: #{branch}"
15
+
16
+ if options.clean == true && File.exists?("#{app_home}/slug.tgz")
17
+ File.delete("#{app_home}/slug.tgz")
18
+ end
19
+
20
+ unless File.exists?("#{app_home}/slug.tgz")
21
+ build_slug(app_home, stack, branch)
22
+ else
23
+ puts " Existing slug.tgz found, build not needed."
24
+ end
25
+ puts "-----> Starting app container"
26
+ run_opts = [
27
+ '-e PORT=5000',
28
+ "-e STACK=#{stack}",
29
+ '-e SLUG_URL=file:///tmp/fake_slug.tgz',
30
+ '-p 5000',
31
+ "-v #{app_home}/slug.tgz:/tmp/fake_slug.tgz"
32
+ ]
33
+ if File.exists?("#{app_home}/.env")
34
+ run_opts << "--env-file=#{app_home}/.env"
35
+ end
36
+ if commands.size == 0
37
+ cmd = 'start web'
38
+ else
39
+ cmd = commands.join(" ")
40
+ end
41
+
42
+ exec("docker run -it #{run_opts.join(" ")} qtcs/slugrunner:#{stack} #{cmd}")
43
+ end
44
+
45
+ def local_build_slug(options)
46
+ stack = options.stack || 'cedar-14'
47
+ branch = options.branch || 'master'
48
+ app_home = File.realpath('.')
49
+ puts "-----> Starting to build MAR app locally"
50
+ puts " Using stack: #{stack}"
51
+ puts " Using git branch: #{branch}"
52
+ build_slug(app_home, stack, branch)
53
+ end
54
+
55
+ def build_slug(app_home, stack, branch)
56
+ docker_id = nil
57
+ run_opts = '-i -a stdin'
58
+ if File.exists?("#{app_home}/.env")
59
+ run_opts << "--env-file=#{app_home}/.env"
60
+ end
61
+ Open3.popen3("git archive #{branch} | docker run #{run_opts} qtcs/slugbuilder:#{stack}") {|stdin, stdout, stderr, wait_thr|
62
+ stdin.close
63
+ docker_id = stdout.gets
64
+ if docker_id
65
+ docker_id.strip!
66
+ else
67
+ puts stderr.gets
68
+ end
69
+ exit_status = wait_thr.value
70
+ unless exit_status.success?
71
+ raise "ERROR: build failed to start"
72
+ end
73
+ }
74
+ Open3.popen2('docker', 'attach', docker_id){|stdin, stdout, wait_thr|
75
+ stdin.close
76
+ while line = stdout.gets
77
+ puts line
78
+ end
79
+ exit_status = wait_thr.value
80
+ unless exit_status.success?
81
+ raise "ERROR: build failed to complete"
82
+ end
83
+ }
84
+ puts "-----> Extracting slug from build image to ./slug.tgz"
85
+ system("docker cp #{docker_id}:/tmp/slug.tgz . > /dev/null")
86
+
87
+ docker_id
88
+ rescue => exc
89
+ system("docker rm -f #{docker_id}") if docker_id
90
+ raise exc
91
+ end
92
+ end
93
+ end
94
+ 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
@@ -1,80 +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
-
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
+