ops_manager_cli 0.5.4 → 0.7.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e200f84440299495f24ab5116f42ee811619f202
4
- data.tar.gz: 34f6349b50099e31de0995fc004d602a47712cdb
3
+ metadata.gz: 8992b156cebae9e672d078b6da9b8657a650b093
4
+ data.tar.gz: 70fab26214ffab2248756aa0e281fb287acd0e5e
5
5
  SHA512:
6
- metadata.gz: adb1d901dd22f681e4f14e1d90a92216d978d650747f3359895a5db86b8ea13716a71608c8729dc653a7b373ea7532c103ce1e5b7f969e1e9f3ae9d071a1a54e
7
- data.tar.gz: 3336b1e3aecfcc730fff8e74ddbd5f928640f3bff5047f690b83c63477b91f25695cb77b0c0441f675270324ee732b3e660a4e4cd4350601d624e34208dec29c
6
+ metadata.gz: c2e769b03f59448e5e415f141d2dac8d6009ae272c748c20aabb98b8c6ea6b70d38ada89d20c335e13daafe79fbb9ec9a44be775a7ca3750d69396a20459606e
7
+ data.tar.gz: 3ef3595a66344221983bdde63e1c770a3422453286656bdf572f2d8b4f66c6e8a4e01ed8549e2bd4672246c4f508e3d789fcee5542fd5f67acc69f138f07d201
data/CHANGELOG.md CHANGED
@@ -1,17 +1,28 @@
1
1
  # Change Log
2
2
 
3
+ ## [v0.5.4](https://github.com/compozed/ops_manager_cli/tree/v0.5.4) (2017-06-27)
4
+ [Full Changelog](https://github.com/compozed/ops_manager_cli/compare/v0.5.3...v0.5.4)
5
+
6
+ ## [v0.5.3](https://github.com/compozed/ops_manager_cli/tree/v0.5.3) (2017-06-27)
7
+ [Full Changelog](https://github.com/compozed/ops_manager_cli/compare/v0.5.2...v0.5.3)
8
+
3
9
  ## [v0.5.2](https://github.com/compozed/ops_manager_cli/tree/v0.5.2) (2017-06-27)
4
10
  [Full Changelog](https://github.com/compozed/ops_manager_cli/compare/v0.5.1...v0.5.2)
5
11
 
6
12
  **Closed issues:**
7
13
 
14
+ - CLI should check that UAA is available after Ops Manager upgrades [\#29](https://github.com/compozed/ops_manager_cli/issues/29)
15
+ - When upgrading opsman the token does not reset [\#27](https://github.com/compozed/ops_manager_cli/issues/27)
8
16
  - Support refresh tokens for re-authentication with UAA [\#24](https://github.com/compozed/ops_manager_cli/issues/24)
9
- - Upgrading product does not work with opsman\_cli 0.5.0 on opsman 1.9 [\#23](https://github.com/compozed/ops_manager_cli/issues/23)
10
17
  - Allow toggling ops\_manager.log [\#21](https://github.com/compozed/ops_manager_cli/issues/21)
11
18
 
12
19
  ## [v0.5.1](https://github.com/compozed/ops_manager_cli/tree/v0.5.1) (2017-01-25)
13
20
  [Full Changelog](https://github.com/compozed/ops_manager_cli/compare/v0.5.0...v0.5.1)
14
21
 
22
+ **Closed issues:**
23
+
24
+ - Upgrading product does not work with opsman\_cli 0.5.0 on opsman 1.9 [\#23](https://github.com/compozed/ops_manager_cli/issues/23)
25
+
15
26
  ## [v0.5.0](https://github.com/compozed/ops_manager_cli/tree/v0.5.0) (2017-01-24)
16
27
  [Full Changelog](https://github.com/compozed/ops_manager_cli/compare/v0.4.1...v0.5.0)
17
28
 
@@ -21,6 +32,7 @@
21
32
 
22
33
  **Closed issues:**
23
34
 
35
+ - Upgrade does not merge product installation settings [\#22](https://github.com/compozed/ops_manager_cli/issues/22)
24
36
  - ops\_manager curl -x PUT not working [\#17](https://github.com/compozed/ops_manager_cli/issues/17)
25
37
  - When uploading stemcell it does not show the correct output [\#15](https://github.com/compozed/ops_manager_cli/issues/15)
26
38
 
@@ -30,6 +42,7 @@
30
42
  **Fixed bugs:**
31
43
 
32
44
  - Director template generator does not delete UAA sensitive data [\#13](https://github.com/compozed/ops_manager_cli/issues/13)
45
+ - Product template generator does not delete stemcell metadata properties [\#12](https://github.com/compozed/ops_manager_cli/issues/12)
33
46
 
34
47
  ## [v0.4.0](https://github.com/compozed/ops_manager_cli/tree/v0.4.0) (2016-10-20)
35
48
  [Full Changelog](https://github.com/compozed/ops_manager_cli/compare/v0.3.0...v0.4.0)
@@ -37,12 +50,14 @@
37
50
  **Implemented enhancements:**
38
51
 
39
52
  - Improve output for appliance deploy/upgrade [\#11](https://github.com/compozed/ops_manager_cli/issues/11)
53
+ - Improve output for product deploy/upgrade [\#10](https://github.com/compozed/ops_manager_cli/issues/10)
40
54
  - Run errands when applying changes [\#9](https://github.com/compozed/ops_manager_cli/issues/9)
41
55
  - 1.8 support [\#5](https://github.com/compozed/ops_manager_cli/pull/5) ([bonzofenix](https://github.com/bonzofenix))
42
56
 
43
57
  **Fixed bugs:**
44
58
 
45
59
  - delete-unused-products command not working [\#8](https://github.com/compozed/ops_manager_cli/issues/8)
60
+ - Hardcoded user name admin when logging agains ops\_manager [\#2](https://github.com/compozed/ops_manager_cli/issues/2)
46
61
 
47
62
  **Closed issues:**
48
63
 
data/Dockerfile CHANGED
@@ -1,7 +1,7 @@
1
1
  FROM ruby:2.3.0
2
2
 
3
3
  ENV GEM_NAME ops_manager_cli
4
- ENV GEM_VERSION 0.5.4
4
+ ENV GEM_VERSION 0.7.1
5
5
  ENV OVFTOOL_VERSION 4.1.0-2459827
6
6
  ENV OVFTOOL_INSTALLER VMware-ovftool-${OVFTOOL_VERSION}-lin.x86_64.bundle
7
7
  ARG DOWNLOAD_URL
@@ -154,6 +154,9 @@ class OpsManager
154
154
  http.use_ssl = true
155
155
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE
156
156
  http.read_timeout = 1200
157
+
158
+ ctx = OpenSSL::SSL::SSLContext.new
159
+ ctx.ssl_version = :TLSv1_2
157
160
  end
158
161
  end
159
162
 
@@ -25,6 +25,10 @@ class OpsManager
25
25
  authenticated_get("/api/v0/staged/products", opts)
26
26
  end
27
27
 
28
+ def get_pending_changes(opts = {})
29
+ authenticated_get("/api/v0/staged/pending_changes", opts)
30
+ end
31
+
28
32
  def get_installation_settings(opts = {})
29
33
  print_green '====> Downloading installation settings ...'
30
34
  res = authenticated_get("/api/installation_settings", opts)
@@ -117,7 +121,7 @@ class OpsManager
117
121
 
118
122
  def get_diagnostic_report
119
123
  authenticated_get("/api/v0/diagnostic_report")
120
- rescue Errno::ETIMEDOUT , Errno::EHOSTUNREACH, Net::HTTPFatalError, Net::OpenTimeout
124
+ rescue Errno::ETIMEDOUT , Errno::EHOSTUNREACH, Net::HTTPFatalError, Net::OpenTimeout, HTTPClient::ConnectTimeoutError
121
125
  nil
122
126
  end
123
127
 
@@ -153,6 +157,23 @@ class OpsManager
153
157
  nil
154
158
  end
155
159
 
160
+ def pending_changes(opts = {})
161
+ print_green '====> Getting pending changes ...'
162
+ res = authenticated_get('/api/v0/staged/pending_changes')
163
+ pendingChanges = JSON.parse(res.body)
164
+
165
+ if pendingChanges['product_changes'].count == 0
166
+ puts "\nNo pending changes"
167
+ else
168
+ pendingChanges['product_changes'].each do |product|
169
+ puts "\n#{product['guid']}"
170
+ end
171
+ end
172
+
173
+ say_green 'done'
174
+ res
175
+ end
176
+
156
177
  def username
157
178
  @username ||= OpsManager.get_conf(:username)
158
179
  end
@@ -174,7 +195,23 @@ class OpsManager
174
195
  @access_token ||= get_token.info['access_token']
175
196
  end
176
197
 
198
+ def wait_for_https_alive(limit)
199
+ @retry_counter = 0
200
+ res = nil
201
+ until(@retry_counter >= limit or (res = check_alive).code.to_i < 400) do
202
+ sleep 1
203
+ @retry_counter += 1
204
+ end
205
+ res
206
+ end
207
+
177
208
  private
209
+ def check_alive
210
+ get("/")
211
+ rescue Net::OpenTimeout, Net::HTTPError, Net::HTTPFatalError, Errno::ETIMEDOUT, Errno::ECONNREFUSED, Errno::ECONNRESET => e
212
+ Net::HTTPInternalServerError.new(1.0, 500, e.inspect)
213
+ end
214
+
178
215
  def token_issuer
179
216
  @token_issuer ||= CF::UAA::TokenIssuer.new(
180
217
  "https://#{target}/uaa", 'opsman', nil, skip_ssl_validation: true )
@@ -0,0 +1,89 @@
1
+ require 'fog/aws'
2
+ require 'ops_manager/appliance/base'
3
+
4
+ class OpsManager
5
+ module Appliance
6
+ class AWS < Base
7
+
8
+ def deploy_vm
9
+ image_id = ::YAML.load_file(ami_mapping_file)[config[:opts][:region]]
10
+
11
+ server = connection.servers.create(
12
+ block_device_mapping: [{
13
+ 'DeviceName' => '/dev/xvda',
14
+ 'Ebs.VolumeSize' => config[:opts][:disk_size_in_gb],
15
+ }],
16
+ key_name: config[:opts][:ssh_keypair_name],
17
+ flavor_id: config[:opts][:instance_type],
18
+ subnet_id: config[:opts][:subnet_id],
19
+ image_id: image_id,
20
+ private_ip_address: config[:ip],
21
+ security_group_ids: security_group_ids,
22
+ availability_zone: config[:opts][:availability_zone],
23
+ iam_instance_profile_name: config[:opts][:instance_profile_name],
24
+ tags: {
25
+ 'Name' => vm_name,
26
+ }
27
+ )
28
+ server.wait_for { ready? }
29
+ return server
30
+ end
31
+
32
+ def stop_current_vm(name)
33
+ server = connection.servers.all("private-ip-address" => config[:ip], "tag:Name" => name).first
34
+ if ! server
35
+ fail "VM not found matching IP '#{config[:ip]}', named '#{name}'"
36
+ end
37
+ server.stop
38
+ server.wait_for { server.state == "stopped" }
39
+
40
+ # Create ami of stopped server
41
+ response = connection.create_image(server.id, "#{name}-backup", "Backup of #{name}")
42
+ image = connection.images.get( response.data[:body]['imageId'])
43
+ image.wait_for { image.state == "available" }
44
+ if image.state != "available"
45
+ fail "Error creating backup AMI, bailing out before destroying the VM"
46
+ end
47
+
48
+ puts "Saved #{name} to AMI #{image.id} (#{name}-backup) for safe-keeping"
49
+
50
+ server.destroy
51
+ if !Fog.mocking?
52
+ server.wait_for { server.state == 'terminated' }
53
+ else
54
+ # Fog's mock doesn't support transitioning state from terminating -> terminated
55
+ # so we have to hack this here
56
+ server.wait_for { server.state == 'terminating' }
57
+ end
58
+ end
59
+
60
+ private
61
+ def ami_mapping_file
62
+ Dir.glob(config[:opts][:ami_mapping_file]).first
63
+ end
64
+
65
+ def security_group_ids
66
+ config[:opts][:security_groups].collect do |sg|
67
+ connection.security_groups.get(sg).group_id
68
+ end
69
+ end
70
+
71
+ def connection
72
+ if config[:opts][:use_iam_profile]
73
+ @connection ||= Fog::Compute.new({
74
+ provider: config[:provider],
75
+ use_iam_profile: config[:opts][:use_iam_profile],
76
+ aws_access_key_id: "",
77
+ aws_secret_access_key: "",
78
+ })
79
+ else
80
+ @connection ||= Fog::Compute.new({
81
+ provider: config[:provider],
82
+ aws_access_key_id: config[:opts][:access_key],
83
+ aws_secret_access_key: config[:opts][:secret_key],
84
+ })
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,23 @@
1
+
2
+ class OpsManager
3
+ module Appliance
4
+ class Base
5
+ attr_reader :config
6
+
7
+ def initialize(config)
8
+ @config = config
9
+ end
10
+ def deploy_vm
11
+ raise NotImplementedError.new("You must implement deploy_vm.")
12
+ end
13
+ def stop_current_vm(name)
14
+ raise NotImplementedError.new("You must implement stop_current_vm.")
15
+ end
16
+
17
+ private
18
+ def vm_name
19
+ @vm_name ||= "#{config[:name]}-#{config[:desired_version]}"
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,47 @@
1
+ require 'rbvmomi'
2
+ require "uri"
3
+ require 'shellwords'
4
+ require "ops_manager/logging"
5
+ require 'ops_manager/appliance/base'
6
+
7
+ class OpsManager
8
+ module Appliance
9
+ class Vsphere < Base
10
+ include OpsManager::Logging
11
+ attr_reader :config
12
+
13
+ def deploy_vm
14
+ print '====> Deploying ova ...'.green
15
+ vcenter_target= "vi://#{vcenter_username}:#{vcenter_password}@#{config[:opts][:vcenter][:host]}/#{config[:opts][:vcenter][:datacenter]}/host/#{config[:opts][:vcenter][:cluster]}"
16
+ cmd = "echo yes | ovftool --acceptAllEulas --noSSLVerify --powerOn --X:waitForIp --net:\"Network 1=#{config[:opts][:portgroup]}\" --name=#{vm_name} -ds=#{config[:opts][:datastore]} --prop:ip0=#{config[:ip]} --prop:netmask0=#{config[:opts][:netmask]} --prop:gateway=#{config[:opts][:gateway]} --prop:DNS=#{config[:opts][:dns]} --prop:ntp_servers=#{config[:opts][:ntp_servers].join(',')} --prop:admin_password=#{config[:password]} #{config[:opts][:ova_path]} #{vcenter_target}"
17
+ logger.info "Running: #{cmd}"
18
+ logger.info `#{cmd}`
19
+ puts 'done'.green
20
+ end
21
+
22
+ def stop_current_vm(name)
23
+ print "====> Stopping vm #{name} ...".green
24
+ dc = vim.serviceInstance.find_datacenter(config[:opts][:vcenter][:datacenter])
25
+ logger.info "finding vm: #{name}"
26
+ vm = dc.find_vm(name) or fail "VM not found"
27
+ vm.PowerOffVM_Task.wait_for_completion
28
+ puts 'done'.green
29
+ end
30
+
31
+ private
32
+ def vim
33
+ RbVmomi::VIM.connect host: config[:opts][:vcenter][:host], user: URI.unescape(config[:opts][:vcenter][:username]), password: URI.unescape(config[:opts][:vcenter][:password]), insecure: true
34
+ end
35
+
36
+ def vcenter_username
37
+ Shellwords.escape(URI.encode(config[:opts][:vcenter][:username]))
38
+ end
39
+
40
+ def vcenter_password
41
+ Shellwords.escape(URI.encode(config[:opts][:vcenter][:password]))
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+
@@ -1,15 +1,18 @@
1
1
  require "ops_manager/api/opsman"
2
2
  require "ops_manager/api/pivnet"
3
- require 'ops_manager/configs/opsman_deployment'
3
+ require 'ops_manager/config/opsman_deployment'
4
4
  require 'fileutils'
5
5
 
6
6
  class OpsManager::ApplianceDeployment
7
7
  extend Forwardable
8
+ attr_reader :config
9
+
8
10
  def_delegators :pivnet_api, :get_product_releases, :accept_product_release_eula,
9
11
  :get_product_release_files, :download_product_release_file
10
- def_delegators :opsman_api, :create_user, :trigger_installation, :get_installation_assets,
12
+ def_delegators :opsman_api, :create_user, :get_installation_assets,
11
13
  :get_installation_settings, :get_diagnostic_report, :upload_installation_assets, :get_ensure_availability,
12
- :import_stemcell, :target, :password, :username, :ops_manager_version= , :reset_access_token
14
+ :import_stemcell, :target, :password, :username, :ops_manager_version= , :reset_access_token, :get_pending_changes,
15
+ :wait_for_https_alive
13
16
 
14
17
  attr_reader :config_file
15
18
 
@@ -18,35 +21,37 @@ class OpsManager::ApplianceDeployment
18
21
  end
19
22
 
20
23
  def run
21
- OpsManager.set_conf(:target, config.ip)
22
- OpsManager.set_conf(:username, config.username)
23
- OpsManager.set_conf(:password, config.password)
24
- OpsManager.set_conf(:pivnet_token, config.pivnet_token)
24
+ OpsManager.set_conf(:target, config[:ip])
25
+ OpsManager.set_conf(:username, config[:username])
26
+ OpsManager.set_conf(:password, config[:password])
27
+ OpsManager.set_conf(:pivnet_token, config[:pivnet_token])
25
28
 
26
- self.extend(OpsManager::Deployments::Vsphere)
27
29
 
28
30
  case
29
31
  when current_version.empty?
30
- puts "No OpsManager deployed at #{config.ip}. Deploying ...".green
32
+ puts "No OpsManager deployed at #{config[:ip]}. Deploying ...".green
31
33
  deploy
32
34
  create_first_user
33
35
  when current_version < desired_version then
34
- puts "OpsManager at #{config.ip} version is #{current_version}. Upgrading to #{desired_version} .../".green
36
+ puts "OpsManager at #{config[:ip]} version is #{current_version}. Upgrading to #{desired_version} .../".green
35
37
  upgrade
36
38
  when current_version == desired_version then
37
- puts "OpsManager at #{config.ip} version is already #{config.desired_version}. Skiping ...".green
39
+ if pending_changes?
40
+ puts "OpsManager at #{config[:ip]} version has pending changes. Applying changes...".green
41
+ OpsManager::InstallationRunner.trigger!.wait_for_result
42
+ else
43
+ puts "OpsManager at #{config[:ip]} version is already #{config[:desired_version]}. Skiping ...".green
44
+ end
38
45
  end
39
46
 
40
47
  puts '====> Finish!'.green
41
48
  end
42
49
 
43
- def deploy
44
- deploy_vm(desired_vm_name , config.ip)
45
- end
46
-
47
- %w{ stop_current_vm deploy_vm }.each do |m|
48
- define_method(m) do
49
- raise NotImplementedError
50
+ def appliance
51
+ @appliance ||= if config[:provider] =~/vsphere/i
52
+ OpsManager::Appliance::Vsphere.new(config)
53
+ else
54
+ OpsManager::Appliance::AWS.new(config)
50
55
  end
51
56
  end
52
57
 
@@ -57,10 +62,15 @@ class OpsManager::ApplianceDeployment
57
62
  end
58
63
  end
59
64
 
65
+ def deploy
66
+ appliance.deploy_vm
67
+ wait_for_https_alive 300
68
+ end
69
+
60
70
  def upgrade
61
71
  get_installation_assets
62
72
  download_current_stemcells
63
- stop_current_vm(current_vm_name)
73
+ appliance.stop_current_vm(current_name)
64
74
  deploy
65
75
  upload_installation_assets
66
76
  wait_for_uaa
@@ -113,21 +123,30 @@ class OpsManager::ApplianceDeployment
113
123
  list_current_stemcells.each do |stemcell_version|
114
124
  release_id = find_stemcell_release(stemcell_version)
115
125
  accept_product_release_eula('stemcells', release_id )
116
- file_id, file_name = find_stemcell_file(release_id, /vsphere/)
126
+ stemcell_regex = /vsphere/
127
+ if config[:provider] == "AWS"
128
+ stemcell_regex = /aws/
129
+ end
130
+
131
+ file_id, file_name = find_stemcell_file(release_id, stemcell_regex)
117
132
  download_product_release_file('stemcells', release_id, file_id, write_to: "#{current_stemcell_dir}/#{file_name}")
118
133
  end
119
134
  end
120
135
 
121
136
  def new_vm_name
122
- @new_vm_name ||= "#{config.name}-#{config.desired_version}"
137
+ @new_vm_name ||= "#{config[:name]}-#{config[:desired_version]}"
123
138
  end
124
139
 
125
140
  def current_version
126
141
  @current_version ||= OpsManager::Semver.new(version_from_diagnostic_report)
127
142
  end
128
143
 
144
+ def current_name
145
+ @current_name ||= "#{config[:name]}-#{current_version}"
146
+ end
147
+
129
148
  def desired_version
130
- @desired_version ||= OpsManager::Semver.new(config.desired_version)
149
+ @desired_version ||= OpsManager::Semver.new(config[:desired_version])
131
150
  end
132
151
 
133
152
  def provision_stemcells
@@ -167,12 +186,9 @@ class OpsManager::ApplianceDeployment
167
186
  end
168
187
 
169
188
  def current_vm_name
170
- @current_vm_name ||= "#{config.name}-#{current_version}"
189
+ @current_vm_name ||= "#{config[:name]}-#{current_version}"
171
190
  end
172
191
 
173
- def desired_vm_name
174
- @desired_vm_name ||= "#{config.name}-#{config.desired_version}"
175
- end
176
192
 
177
193
  def pivnet_api
178
194
  @pivnet_api ||= OpsManager::Api::Pivnet.new
@@ -183,10 +199,10 @@ class OpsManager::ApplianceDeployment
183
199
  end
184
200
 
185
201
  def config
186
- parsed_yml = ::YAML.load_file(@config_file)
187
- @config ||= OpsManager::Configs::OpsmanDeployment.new(parsed_yml)
202
+ @config ||= OpsManager::Config::OpsmanDeployment.new(YAML.load_file(@config_file))
188
203
  end
189
204
 
205
+
190
206
  def desired_version?(version)
191
207
  !!(desired_version.to_s =~/#{version}/)
192
208
  end
@@ -206,4 +222,8 @@ class OpsManager::ApplianceDeployment
206
222
  def current_stemcell_dir
207
223
  "/tmp/current_stemcells"
208
224
  end
225
+
226
+ def pending_changes?
227
+ !JSON.parse(get_pending_changes.body).fetch('product_changes').empty?
228
+ end
209
229
  end
@@ -72,6 +72,12 @@ class OpsManager
72
72
  end
73
73
  end
74
74
 
75
+ class PendingChanges < Clamp::Command
76
+ def execute
77
+ OpsManager::Api::Opsman.new.pending_changes
78
+ end
79
+ end
80
+
75
81
  class DeleteUnusedProducts < Clamp::Command
76
82
 
77
83
  def execute
@@ -158,6 +164,7 @@ class OpsManager
158
164
  subcommand "get-installation-settings", "Gets installation settings", GetInstallationSettings
159
165
  subcommand "get-installation-logs", "Gets installation logs", GetInstallationLogs
160
166
  subcommand "import-stemcell", "Uploads stemcell to OpsManager", ImportStemcell
167
+ subcommand "pending-changes", "View pending changes in OpsManager", PendingChanges
161
168
 
162
169
  end
163
170
  end
@@ -0,0 +1,42 @@
1
+ require 'ostruct'
2
+
3
+ class OpsManager
4
+ module Config
5
+ class Base < OpenStruct
6
+ def initialize(config)
7
+ super(config.to_symbolize)
8
+ end
9
+
10
+ def validate_presence_of!(*attrs)
11
+ attrs.each do |attr|
12
+ raise "missing #{attr} on config" unless self.to_h.has_key?(attr)
13
+ end
14
+ end
15
+
16
+ def expand_path_for!(*attrs)
17
+ attrs.each do |attr|
18
+ path = self[attr]
19
+ self[attr] = if path =~ %r{^file://}
20
+ path = Dir.glob(path.gsub!('file://','')).first
21
+ "file://#{path}"
22
+ else
23
+ Dir.glob(path).first
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+
31
+ class Hash
32
+ def to_symbolize
33
+ Hash[self.map do |k, v|
34
+ if v.kind_of?(Hash)
35
+ [k.to_sym, v.to_symbolize]
36
+ else
37
+ [k.to_sym, v]
38
+ end
39
+ end]
40
+ end
41
+ end
42
+
@@ -1,7 +1,7 @@
1
- require 'ops_manager/configs/base'
1
+ require 'ops_manager/config/base'
2
2
 
3
3
  class OpsManager
4
- class Configs
4
+ module Config
5
5
  class OpsmanDeployment < Base
6
6
  def initialize(config)
7
7
  super(config)
@@ -0,0 +1,13 @@
1
+ require 'ops_manager/config/base'
2
+
3
+ class OpsManager
4
+ module Config
5
+ class ProductDeployment < Base
6
+ def initialize(config)
7
+ super(config)
8
+ validate_presence_of! :name, :desired_version
9
+ expand_path_for! :stemcell
10
+ end
11
+ end
12
+ end
13
+ end
@@ -2,7 +2,7 @@ require 'ostruct'
2
2
 
3
3
  class OpsManager
4
4
  class Configs
5
- class Base < OpenStruct
5
+ class Base < Hash
6
6
  def initialize(config)
7
7
  @config = config
8
8
  super(config)
@@ -6,7 +6,7 @@ class OpsManager
6
6
  attr_reader :id
7
7
 
8
8
  def trigger!
9
- res = trigger_installation( body: body )
9
+ res = trigger_installation( :headers => {"Content-Type"=>"application/json"}, :body => body )
10
10
  @id = JSON.parse(res.body).fetch('install').fetch('id').to_i
11
11
  self
12
12
  end
@@ -25,27 +25,19 @@ class OpsManager
25
25
 
26
26
  private
27
27
  def body
28
- @body ||= [ 'ignore_warnings=true' ]
29
- @body << errands_body
30
- @body.join('&')
28
+ @body ||= {'errands' => errands, 'ignore_warnings' => true }.to_json
31
29
  end
32
-
33
30
  def opsman_api
34
31
  @opsman_api ||= OpsManager::Api::Opsman.new
35
32
  end
36
33
 
37
- def errands_body
38
- staged_products_guids.collect { |product_guid| post_deploy_errands_body_for(product_guid) }
39
- end
40
-
41
- def post_deploy_errands_body_for(product_guid)
42
- post_deploy_errands = post_deploy_errands_for(product_guid)
43
-
44
- if post_deploy_errands.empty?
45
- "enabled_errands[#{product_guid}]{}"
46
- else
47
- post_deploy_errands.collect{ |e| "enabled_errands[#{product_guid}][post_deploy_errands][]=#{e}" }
34
+ def errands
35
+ res = { }
36
+ staged_products_guids.each do |product_guid|
37
+ errands = errands_for(product_guid).keep_if { |an_errand| an_errand['post_deploy'] }
38
+ errands.each { |e| res[product_guid] = {'run_post_deploy' => { e['name'] => true}}}
48
39
  end
40
+ res
49
41
  end
50
42
 
51
43
  def staged_products_guids
@@ -56,9 +48,6 @@ class OpsManager
56
48
  JSON.parse(get_staged_products.body)
57
49
  end
58
50
 
59
- def post_deploy_errands_for(product_guid)
60
- errands_for(product_guid).keep_if{ |errand| errand['post_deploy'] }.map{ |o| o['name']}
61
- end
62
51
 
63
52
  def errands_for(product_guid)
64
53
  res = get_staged_products_errands(product_guid)
@@ -7,6 +7,8 @@ require "ops_manager/semver"
7
7
  class OpsManager
8
8
  class ProductDeployment
9
9
  extend Forwardable
10
+ attr_reader :config
11
+
10
12
  def_delegators :opsman_api, :current_version, :upload_product, :get_installation_settings,
11
13
  :upgrade_product_installation, :get_installation, :get_available_products, :upload_installation_settings,
12
14
  :trigger_installation, :import_stemcell, :add_staged_products
@@ -19,12 +21,12 @@ class OpsManager
19
21
  end
20
22
 
21
23
  def installation
22
- OpsManager::ProductInstallation.find(config.name)
24
+ OpsManager::ProductInstallation.find(config[:name])
23
25
  end
24
26
 
25
27
  def run
26
- OpsManager.target_and_login(config.target, config.username, config.password)
27
- import_stemcell(config.stemcell)
28
+ OpsManager.target_and_login(config[:target], config[:username], config[:password])
29
+ import_stemcell(config[:stemcell])
28
30
 
29
31
  case
30
32
  when installation.nil? || forced_deployment?
@@ -37,15 +39,15 @@ class OpsManager
37
39
  end
38
40
 
39
41
  def desired_version
40
- Semver.new(config.desired_version)
42
+ Semver.new(config[:desired_version])
41
43
  end
42
44
 
43
45
  def upload
44
46
  print "====> Uploading product ...".green
45
- if ProductDeployment.exists?(config.name, config.desired_version)
47
+ if ProductDeployment.exists?(config[:name], config[:desired_version])
46
48
  puts "product already exists".green
47
- elsif config.filepath
48
- upload_product(config.filepath)
49
+ elsif config[:filepath]
50
+ upload_product(config[:filepath])
49
51
  puts "done".green
50
52
  else
51
53
  puts "no filepath provided, skipping product upload.".green
@@ -57,9 +59,9 @@ class OpsManager
57
59
  puts "====> Skipping as this product has a pending installation!".red
58
60
  return
59
61
  end
60
- puts "====> Upgrading #{config.name} version from #{installation.current_version.to_s} to #{config.desired_version}...".green
62
+ puts "====> Upgrading #{config[:name]} version from #{installation.current_version.to_s} to #{config[:desired_version]}...".green
61
63
  upload
62
- upgrade_product_installation(installation.guid, config.desired_version)
64
+ upgrade_product_installation(installation.guid, config[:desired_version])
63
65
  merge_product_installation_settings
64
66
  OpsManager::InstallationRunner.trigger!.wait_for_result
65
67
 
@@ -68,12 +70,12 @@ class OpsManager
68
70
 
69
71
  def add_to_installation
70
72
  unless installation
71
- add_staged_products(config.name, config.desired_version)
73
+ add_staged_products(config[:name], config[:desired_version])
72
74
  end
73
75
  end
74
76
 
75
77
  def deploy
76
- puts "====> Deploying #{config.name} version #{config.desired_version}...".green
78
+ puts "====> Deploying #{config[:name]} version #{config[:desired_version]}...".green
77
79
  upload
78
80
  add_to_installation
79
81
  merge_product_installation_settings
@@ -85,7 +87,7 @@ class OpsManager
85
87
 
86
88
  def merge_product_installation_settings
87
89
  get_installation_settings({write_to: '/tmp/is.yml'})
88
- puts `DEBUG=false spruce merge /tmp/is.yml #{config.installation_settings_file} > /tmp/new_is.yml`
90
+ puts `DEBUG=false spruce merge /tmp/is.yml #{config[:installation_settings_file]} > /tmp/new_is.yml`
89
91
  upload_installation_settings('/tmp/new_is.yml')
90
92
  end
91
93
 
@@ -96,7 +98,7 @@ class OpsManager
96
98
 
97
99
  private
98
100
  def desired_version
99
- @desired_version ||= OpsManager::Semver.new(config.desired_version)
101
+ @desired_version ||= OpsManager::Semver.new(config[:desired_version])
100
102
  end
101
103
 
102
104
  def forced_deployment?
@@ -108,7 +110,7 @@ class OpsManager
108
110
  end
109
111
 
110
112
  def config
111
- OpsManager::Configs::ProductDeployment.new(::YAML.load_file(@config_file))
113
+ OpsManager::Config::ProductDeployment.new(::YAML.load_file(@config_file))
112
114
  end
113
115
  end
114
116
  end
@@ -1,3 +1,3 @@
1
1
  class OpsManager
2
- VERSION = "0.5.4"
2
+ VERSION = "0.7.1"
3
3
  end
data/lib/ops_manager.rb CHANGED
@@ -83,9 +83,10 @@ end
83
83
 
84
84
  require "ops_manager/version"
85
85
  require "ops_manager/semver"
86
- require "ops_manager/deployments/vsphere"
87
- require 'ops_manager/configs/product_deployment'
88
- require 'ops_manager/configs/opsman_deployment'
86
+ require "ops_manager/appliance/vsphere"
87
+ require "ops_manager/appliance/aws"
88
+ require 'ops_manager/config/product_deployment'
89
+ require 'ops_manager/config/opsman_deployment'
89
90
  require "ops_manager/cli"
90
91
  require "ops_manager/errors"
91
92
  require "net/https"
data/ops_manager.gemspec CHANGED
@@ -26,6 +26,7 @@ Gem::Specification.new do |spec|
26
26
  spec.add_dependency "rbvmomi"
27
27
  spec.add_dependency "multipart-post"
28
28
  spec.add_dependency "clamp"
29
+ spec.add_dependency "fog-aws"
29
30
  spec.add_dependency "net-ping"
30
31
  spec.add_dependency "cf-uaa-lib"
31
32
  spec.add_dependency "session_config"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ops_manager_cli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.4
4
+ version: 0.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - CompoZed
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-06-27 00:00:00.000000000 Z
11
+ date: 2017-10-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -136,6 +136,20 @@ dependencies:
136
136
  - - ">="
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: fog-aws
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
139
153
  - !ruby/object:Gem::Dependency
140
154
  name: net-ping
141
155
  requirement: !ruby/object:Gem::Requirement
@@ -218,12 +232,15 @@ files:
218
232
  - lib/ops_manager/api/base.rb
219
233
  - lib/ops_manager/api/opsman.rb
220
234
  - lib/ops_manager/api/pivnet.rb
235
+ - lib/ops_manager/appliance/aws.rb
236
+ - lib/ops_manager/appliance/base.rb
237
+ - lib/ops_manager/appliance/vsphere.rb
221
238
  - lib/ops_manager/appliance_deployment.rb
222
239
  - lib/ops_manager/cli.rb
240
+ - lib/ops_manager/config/base.rb
241
+ - lib/ops_manager/config/opsman_deployment.rb
242
+ - lib/ops_manager/config/product_deployment.rb
223
243
  - lib/ops_manager/configs/base.rb
224
- - lib/ops_manager/configs/opsman_deployment.rb
225
- - lib/ops_manager/configs/product_deployment.rb
226
- - lib/ops_manager/deployments/vsphere.rb
227
244
  - lib/ops_manager/director_template_generator.rb
228
245
  - lib/ops_manager/errors.rb
229
246
  - lib/ops_manager/installation.rb
@@ -1,16 +0,0 @@
1
- require 'ops_manager/configs/base'
2
-
3
- class OpsManager
4
- class Configs
5
- class ProductDeployment < Base
6
- def initialize(config)
7
- super(config)
8
- validate_presence_of!(:name, :desired_version)
9
- end
10
-
11
- def stemcell
12
- find_full_path(@config['stemcell'])
13
- end
14
- end
15
- end
16
- end
@@ -1,45 +0,0 @@
1
- require 'rbvmomi'
2
- require "uri"
3
- require 'shellwords'
4
- require "ops_manager/logging"
5
-
6
- class OpsManager
7
- module Deployments
8
- module Vsphere
9
- include OpsManager::Logging
10
-
11
- def deploy_vm(name, ip)
12
- print '====> Deploying ova ...'.green
13
- vcenter_target= "vi://#{vcenter_username}:#{vcenter_password}@#{config.opts['vcenter']['host']}/#{config.opts['vcenter']['datacenter']}/host/#{config.opts['vcenter']['cluster']}"
14
- cmd = "echo yes | ovftool --acceptAllEulas --noSSLVerify --powerOn --X:waitForIp --net:\"Network 1=#{config.opts['portgroup']}\" --name=#{name} -ds=#{config.opts['datastore']} --prop:ip0=#{ip} --prop:netmask0=#{config.opts['netmask']} --prop:gateway=#{config.opts['gateway']} --prop:DNS=#{config.opts['dns']} --prop:ntp_servers=#{config.opts['ntp_servers'].join(',')} --prop:admin_password=#{config.password} #{config.opts['ova_path']} #{vcenter_target}"
15
- logger.info "Running: #{cmd}"
16
- logger.info `#{cmd}`
17
- puts 'done'.green
18
- end
19
-
20
- def stop_current_vm(name)
21
- print "====> Stopping vm #{name} ...".green
22
- dc = vim.serviceInstance.find_datacenter(config.opts['vcenter']['datacenter'])
23
- logger.info "finding vm: #{name}"
24
- vm = dc.find_vm(name) or fail "VM not found"
25
- vm.PowerOffVM_Task.wait_for_completion
26
- puts 'done'.green
27
- end
28
-
29
- private
30
- def vim
31
- RbVmomi::VIM.connect host: config.opts['vcenter']['host'], user: URI.unescape(config.opts['vcenter']['username']), password: URI.unescape(config.opts['vcenter']['password']), insecure: true
32
- end
33
-
34
- def vcenter_username
35
- Shellwords.escape(URI.encode(config.opts['vcenter']['username']))
36
- end
37
-
38
- def vcenter_password
39
- Shellwords.escape(URI.encode(config.opts['vcenter']['password']))
40
- end
41
- end
42
- end
43
- end
44
-
45
-