terraform-enterprise-cli 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,61 @@
1
+ require 'terraform_enterprise/command_line/command'
2
+
3
+ module TerraformEnterprise
4
+ module CommandLine
5
+ class VariablesCommand < TerraformEnterprise::CommandLine::Command
6
+ ATTR_STR = STRINGS[:variables][:attributes]
7
+ CMD_STR = STRINGS[:variables][:commands]
8
+
9
+ desc 'list', CMD_STR[:list]
10
+ option :table, type: :boolean, default: true, desc: STRINGS[:options][:table]
11
+ option :organization, required: true, type: :string, desc: ATTR_STR[:organization]
12
+ option :workspace, type: :string, desc: ATTR_STR[:workspace]
13
+ def list
14
+ render client.variables.list(options)
15
+ end
16
+
17
+ desc 'create <key> <value>', CMD_STR[:create]
18
+ option :organization, required: true, type: :string, desc: ATTR_STR[:organization]
19
+ option :workspace, required: true, type: :string, desc: ATTR_STR[:workspace]
20
+ option :category, default: 'terraform', type: :string, desc: ATTR_STR[:category], enum:['terraform', 'env']
21
+ option :hcl, default: false, type: :boolean, desc: ATTR_STR[:hcl]
22
+ option :sensitive, default: false, type: :boolean, desc: ATTR_STR[:sensitive]
23
+ def create(key, value)
24
+ params = {
25
+ category: options[:category],
26
+ hcl: options[:hcl],
27
+ key: key,
28
+ organization: options[:organization],
29
+ sensitive: options[:sensitive],
30
+ value: value,
31
+ workspace: options[:workspace],
32
+ }
33
+ render client.variables.create(params)
34
+ end
35
+
36
+ desc 'update <id>', CMD_STR[:update]
37
+ option :hcl, type: :boolean, desc: ATTR_STR[:hcl]
38
+ option :sensitive, type: :boolean, desc: ATTR_STR[:sensitive]
39
+ option :key, type: :string, desc: ATTR_STR[:key]
40
+ option :value, type: :string, desc: ATTR_STR[:value]
41
+ def update(id)
42
+ params = {id: id}
43
+ params[:hcl] = options[:hcl] if options.include?('hcl')
44
+ params[:key] = options[:key] if options[:key]
45
+ params[:sensitive] = options[:sensitive] if options.include?('sensitive')
46
+ params[:value] = options[:value] if options[:value]
47
+ render client.variables.update(params)
48
+ end
49
+
50
+ desc 'get <id>', CMD_STR[:get]
51
+ def get(id)
52
+ render client.variables.get(id:id)
53
+ end
54
+
55
+ desc 'delete <id>', CMD_STR[:delete]
56
+ def delete(id)
57
+ render client.variables.delete(id: id)
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,87 @@
1
+ require 'terraform_enterprise/command_line/command'
2
+
3
+ module TerraformEnterprise
4
+ module CommandLine
5
+ class WorkspacesCommand < TerraformEnterprise::CommandLine::Command
6
+ ATTR_STR = STRINGS[:workspaces][:attributes]
7
+ CMD_STR = STRINGS[:workspaces][:commands]
8
+
9
+ desc 'list', CMD_STR[:list]
10
+ option :organization, required: true, type: :string, desc: ATTR_STR[:organization]
11
+ option :table, type: :boolean, default: true, desc: STRINGS[:options][:table]
12
+ def list
13
+ render client.workspaces.list(options), except:[:permissions, :actions, :environment, 'created-at']
14
+ end
15
+
16
+ desc 'create <name>', CMD_STR[:create]
17
+ option :terraform_version, type: :string, desc: ATTR_STR[:terraform_version]
18
+ option :working_directory, type: :string, desc: ATTR_STR[:working_directory]
19
+ option :oauth_token, type: :string, desc: ATTR_STR[:oauth_token]
20
+ option :branch, type: :string, desc: ATTR_STR[:branch]
21
+ option :ingress_submodules, type: :boolean, desc: ATTR_STR[:ingress_submodules]
22
+ option :repo, type: :string, desc: ATTR_STR[:repos]
23
+ option :import_legacy_environment, type: :string, desc: ATTR_STR[:import_legacy]
24
+ option :organization, required: true, type: :string, desc: ATTR_STR[:organization]
25
+ def create(name)
26
+ params = {
27
+ organization: options[:organization],
28
+ name: name,
29
+ 'working-directory' => options[:working_directory] || '',
30
+ }
31
+ if options[:repo] && options[:oauth_token]
32
+ repo = {}
33
+ repo['branch'] = options[:branch] || ''
34
+ repo['identifier'] = options[:repo]
35
+ repo['oauth-token-id'] = options[:oauth_token]
36
+ repo['ingress-submodules'] = options[:ingress_submodules] || false
37
+ params['vcs-repo'] = repo
38
+ end
39
+
40
+ params['migration-environment'] = options[:import_legacy_environment] if options[:import_legacy_environment]
41
+ params['terraform_version'] = options[:terraform_version] if options[:terraform_version]
42
+ render client.workspaces.create(params), except:[:permissions, :actions, :environment]
43
+ end
44
+
45
+ desc 'get <name>', CMD_STR[:get]
46
+ option :organization, required: true, type: :string, desc: ATTR_STR[:organization]
47
+ def get(name)
48
+ params = {
49
+ organization: options[:organization],
50
+ workspace: name
51
+ }
52
+ render client.workspaces.get(params), except:[:permissions, :environment]
53
+ end
54
+
55
+ desc 'delete <name>', CMD_STR[:delete]
56
+ option :organization, required: true, type: :string, desc: ATTR_STR[:organization]
57
+ def delete(name)
58
+ params = {
59
+ organization: options[:organization],
60
+ workspace: name
61
+ }
62
+ render client.workspaces.delete(params), except:[:permissions, :actions, :environment]
63
+ end
64
+
65
+ desc 'update <name>', CMD_STR[:update]
66
+ option :working_directory, type: :string, desc: ATTR_STR[:working_directory]
67
+ option :terraform_version, type: :string, desc: ATTR_STR[:terraform_version]
68
+ option :auto_apply, type: :boolean, desc: ATTR_STR[:auto_apply]
69
+ option :organization, required: true, type: :string, desc: ATTR_STR[:organization]
70
+ def update(name)
71
+ params = options
72
+ params[:workspace] = name
73
+ render client.workspaces.update(params), except:[:permissions, :environment]
74
+ end
75
+
76
+ desc 'lock <id>', CMD_STR[:lock]
77
+ def lock(id)
78
+ render client.workspaces.action(action: :lock, id: id), except:[:permissions, :environment]
79
+ end
80
+
81
+ desc 'unlock <id>', CMD_STR[:unlock]
82
+ def unlock(id)
83
+ render client.workspaces.action(action: :unlock, id: id), except:[:permissions, :environment]
84
+ end
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,131 @@
1
+ require 'yaml'
2
+ require 'colorize'
3
+ require 'terminal-table'
4
+
5
+ require 'terraform-enterprise-client'
6
+
7
+ module TerraformEnterprise
8
+ module CommandLine
9
+ # Module with render method to render the Resource object
10
+ class Formatter
11
+ def render(obj, options = {})
12
+ String.disable_colorization = !options[:color]
13
+
14
+ if !obj.is_a?(TerraformEnterprise::API::Response)
15
+ unkown_response(obj)
16
+ elsif obj.success?
17
+ render_resource(obj, options)
18
+ elsif obj.errors?
19
+ render_errors(obj)
20
+ else
21
+ unkown_response(obj.body)
22
+ end
23
+ end
24
+
25
+ def error(message)
26
+ puts "Error: #{message}".red
27
+ end
28
+
29
+ def success(message)
30
+ puts message.green
31
+ end
32
+
33
+ private
34
+
35
+ def unkown_response(obj)
36
+ puts 'Unknown response'.yellow
37
+ puts obj
38
+ exit(false)
39
+ end
40
+
41
+ def render_resource(obj, options)
42
+ if obj.resources
43
+ puts render_resource_list(obj.resources, options)
44
+ elsif obj.resource
45
+ puts render_resource_item(obj.resource, options)
46
+ else
47
+ success "Success (#{obj.code})"
48
+ end
49
+ end
50
+
51
+ def render_errors(obj)
52
+ obj.errors.each do |error|
53
+ message = error['detail'] || error['title'] || error.to_s
54
+ code = error['status'] || obj.code
55
+ error "[#{code}] #{message}"
56
+ end
57
+ exit(false)
58
+ end
59
+
60
+ def parse_resource(resource, options)
61
+ parsed_resource = flatten_dotted_hash(resource.attributes)
62
+ if resource.id
63
+ parsed_resource = { 'id' => resource.id }.merge(parsed_resource)
64
+ end
65
+ (options[:except] || []).each do |excluded|
66
+ parsed_resource.delete_if do |key, _|
67
+ key.to_s.start_with?(excluded.to_s)
68
+ end
69
+ end
70
+ if options[:only] && !options[:only].empty?
71
+ parsed_resource.select! do |key, _|
72
+ options[:only].any? do |included|
73
+ key.to_s.start_with?(included.to_s)
74
+ end
75
+ end
76
+ end
77
+ parsed_resource
78
+ end
79
+
80
+ def render_resource_item(resource, options)
81
+ parsed_resource = parse_resource(resource, options)
82
+ parsed_resource.keys.map do |key|
83
+ value = parsed_resource[key]
84
+ options[:value] ? value : "#{key.bold}: #{value}"
85
+ end.join("\n")
86
+ end
87
+
88
+ def render_resource_list(resources, options)
89
+ if options[:table] && !options[:value]
90
+ parsed_resources = resources.map do |resource|
91
+ parse_resource(resource, options)
92
+ end
93
+ keys = parsed_resources.map(&:keys).flatten.uniq
94
+ rows = parsed_resources.map do |resource|
95
+ keys.map { |key| resource[key] }
96
+ end
97
+ table = Terminal::Table.new headings: keys, rows: rows
98
+ table
99
+ else
100
+ line_separator = "\n#{'-' * 10}\n"
101
+ out = resources.map do |resource|
102
+ render_resource_item(resource, options)
103
+ end
104
+ out.join(line_separator)
105
+ end
106
+ end
107
+
108
+ def flatten_hash(hash, new_key = [], new_hash = {})
109
+ if hash.is_a?(Array)
110
+ hash.each_with_index do |item, obj|
111
+ flatten_hash(item, new_key + [obj], new_hash)
112
+ end
113
+ elsif hash.is_a?(Hash)
114
+ hash.each do |key, value|
115
+ flatten_hash(value, new_key + [key], new_hash)
116
+ end
117
+ else
118
+ return new_hash.update(new_key => hash)
119
+ end
120
+ new_hash
121
+ end
122
+
123
+ def flatten_dotted_hash(source)
124
+ flat = flatten_hash(source)
125
+ flat.keys.each_with_object({}) do |key, h|
126
+ h[key.join('.')] = flat[key]
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
@@ -0,0 +1,149 @@
1
+
2
+
3
+ module TerraformEnterprise
4
+ module CommandLine
5
+ STRINGS = {
6
+ options: {
7
+ table: 'Format list output as a table',
8
+ host: 'Set host address for private Terraform Enterprise',
9
+ token: 'Set the auth token, defaults to TFE_TOKEN environment variable',
10
+ color: 'If disabled the ANSI color codes will not be used',
11
+ except: 'List of fields that should not be displayed',
12
+ only: 'List of fields that should be displayed',
13
+ all: 'Return all fields, not just summary',
14
+ value: 'Only return the value; i.e. do not show keys',
15
+ debug: 'Show debug logs'
16
+ },
17
+ push: {
18
+ attributes: {
19
+ path: 'Path of directory or tar.gz file to push to the workspace'
20
+ },
21
+ commands: {
22
+ push: 'Pushes the configuration to the workspace'
23
+ }
24
+ },
25
+ workspaces: {
26
+ attributes: {
27
+ terraform_version: 'Version of Terraform to use for this workspace.',
28
+ working_directory: 'Relative path that Terraform will execute within.',
29
+ oauth_token: 'VCS Connection (OAuth Conection + Token) to use as identified; obtained from the oauth_tokens subcommand.',
30
+ branch: 'Repository branch that Terraform will execute from.',
31
+ ingress_submodules: 'Submodules should be fetched when cloning the VCS repository.',
32
+ repo: 'Reference to VCS repository in the format :org/:repo.',
33
+ import_legacy: 'Specifies the legacy Environment to use as the source of the migration/',
34
+ organization: 'Organization to which this workspaces belongs to.',
35
+ auto_apply: 'Auto-apply enabled'
36
+ },
37
+ commands: {
38
+ create: 'Create a new workspace',
39
+ list: 'List workspaces in the organization',
40
+ get: 'Get workspace details by name',
41
+ delete: 'Delete the workspace',
42
+ update: 'Update the workspace',
43
+ lock: 'Lock the workspace by workspace ID',
44
+ unlock: 'Unlock the workspace by workspace ID'
45
+ }
46
+ },
47
+ configuration_versions: {
48
+ attributes: {
49
+ workspace_id: 'Workspace ID of the workspace to which the configuration version belongs to.',
50
+ path: 'Path to the tar.gz file'
51
+ },
52
+ commands: {
53
+ create: 'Create a new configuration version',
54
+ list: 'List configuration versions in the organization',
55
+ get: 'Get configuration version details by name',
56
+ upload: 'Upload a file to the configuration version'
57
+ }
58
+ },
59
+ organizations: {
60
+ commands: {
61
+ create: 'Create a new organization',
62
+ list: 'List all the organizations',
63
+ get: 'Get organization details by name',
64
+ delete: 'Delete the organization'
65
+ },
66
+ attributes: {}
67
+ },
68
+ teams: {
69
+ commands: {
70
+ create: 'Create a new team',
71
+ delete: 'Delete the team by ID',
72
+ list: 'List teams in organization',
73
+ get: 'Get team details'
74
+ },
75
+ attributes: {
76
+ organization: 'Organization to which this Team belongs to.'
77
+ }
78
+ },
79
+ policies: {
80
+ commands: {
81
+ create: 'Create a new policy',
82
+ delete: 'Delete a policy by ID',
83
+ list: 'List policies in organization',
84
+ get: 'Get policy details',
85
+ upload: 'Upload a policy'
86
+ },
87
+ attributes: {
88
+ organization: 'Organization to which this Team belongs to.',
89
+ mode: 'Policy mode, hard-mandatory, soft-mandatory or advisory',
90
+ name: 'Policy name'
91
+ }
92
+ },
93
+ runs: {
94
+ commands: {
95
+ create: 'Create a new run',
96
+ list: 'List runs in a workspace',
97
+ get: 'Get run details',
98
+ apply: 'Apply the plan',
99
+ discard: 'Discard the plan',
100
+ log: 'Return logs for the plan or apply'
101
+ },
102
+ attributes: {
103
+ workspace_id: 'Workspace ID of which the run belongs to.',
104
+ configuration_version_id: 'Configuration Version ID of the configuration version to run',
105
+ destroy: 'The run should be a destroy plan',
106
+ comment: 'Add a comment for the action',
107
+ follow: 'Follow the logs until output is complete',
108
+ event: 'Run event for which to get logs (plan or apply)'
109
+ }
110
+ },
111
+ policy_checks: {
112
+ commands: {
113
+ list: 'List policy checks on run',
114
+ override: 'Override the soft-mandatory or advisory policy'
115
+ },
116
+ attributes: {
117
+ run_id: 'Run ID to which the policy check belongs to.',
118
+ comment: 'Add a comment for the action'
119
+ }
120
+ },
121
+ oauth_tokens: {
122
+ commands: {
123
+ list: 'List the OAuth tokens in the organization'
124
+ },
125
+ attributes: {
126
+ organization: 'Organization to which this OAuth Token belongs to.'
127
+ }
128
+ },
129
+ variables: {
130
+ commands: {
131
+ create: 'Create a new variable',
132
+ delete: 'Delete the variable by ID',
133
+ get: 'Get variable details',
134
+ list: 'List variables in organization',
135
+ update: 'Update a variable by ID'
136
+ },
137
+ attributes: {
138
+ organization: 'Organization to which this Variable belongs to.',
139
+ workspace: 'Workspace to which this Variable belongs to.',
140
+ category: 'The type of category, probably "terraform" or "env"',
141
+ hcl: 'Variable should be parsed using HCL',
142
+ sensitive: 'Variable should be marked as sensitive',
143
+ value: 'Variable value',
144
+ key: 'Variable key'
145
+ }
146
+ }
147
+ }.freeze
148
+ end
149
+ end
@@ -0,0 +1,50 @@
1
+ require 'rubygems/package'
2
+ require 'zlib'
3
+ require 'fileutils'
4
+
5
+ module TerraformEnterprise
6
+ module CommandLine
7
+ module Util
8
+ # Module to perform a tar and gz of a directory
9
+ module Tar
10
+ def tar(path)
11
+ tarfile = StringIO.new('')
12
+ Gem::Package::TarWriter.new(tarfile) do |tar|
13
+ Dir[File.join(path, '**/*')].each do |file|
14
+ mode = File.stat(file).mode
15
+ relative_file = file.sub /^#{Regexp.escape(path)}\/?/, ''
16
+
17
+ if File.directory?(file)
18
+ tar.mkdir relative_file, mode
19
+ else
20
+ tar.add_file relative_file, mode do |tf|
21
+ File.open(file, 'rb') { |f| tf.write f.read }
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ tarfile.rewind
28
+ tarfile
29
+ end
30
+
31
+ def gzip(tarfile)
32
+ gzip_string = StringIO.new('')
33
+ gzip_writer = Zlib::GzipWriter.new(gzip_string)
34
+ gzip_writer.write tarfile.string
35
+ gzip_writer.close
36
+ gzip_string.string
37
+ end
38
+
39
+ def tarball(path)
40
+ full_path = File.expand_path(path)
41
+ if File.directory?(full_path)
42
+ gzip(tar(full_path))
43
+ else
44
+ File.read(full_path)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end