terraform-enterprise-cli 0.0.6

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.
@@ -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