qtc-sdk 0.3.1 → 0.4.0

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