kitchen-oci 1.9.0 → 1.10.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8ac8fb8a6a0caaf9b86de1a6178009101fa642e4c6912acb6774fde2f664ae26
4
- data.tar.gz: 4a635fbcff0cec7a548709f65e780fe24628733b61441f6feafdf9e988900166
3
+ metadata.gz: d798253a77bea857de7ca9f24c6ce5943b9521231cf737bd8a35328cce90e42a
4
+ data.tar.gz: 5aedb2971a35efe057733e24df84c0f59296cc934871d6b4d2cbb57bfa510d7c
5
5
  SHA512:
6
- metadata.gz: 96e29112bec4d1f0dad5fbbe46e9accf959b27c63b6ca86e81bb32f9e89e7f646aaf720b7185072f9d9c04f45681172d0e6f5bfd14b212fbeee4e87cd9f6cc3f
7
- data.tar.gz: cc7f3a9dce9e3b7470ba8480551baa908e0b3880e5a17bfbceec0b0cdea9f2c6c7d9191438b4dbd0248416954d2bd26021748b9148be1c055c477b60448a5dcc
6
+ metadata.gz: ee1e27d4ee19ff91240b2bb3c236b87bdf13081af36e3b1e06decad31b9f998642df41612f949542d70e3add8b6fcef2442e8bbdc81afd0b7a72f03651dab669
7
+ data.tar.gz: b70069f530ae95ffdacefb0113b00fb2eb6ee04da8f5814ce6c15af0556062e26bd0ffdba19dd7c4281f892a173ac118be237620c8d77749b0e7989693284380
@@ -0,0 +1,5 @@
1
+ Layout/LineLength:
2
+ Max : 150
3
+
4
+ Style/NumericLiterals:
5
+ Enabled : false
@@ -1,4 +1,11 @@
1
1
 
2
+ ## 1.10.0 DBaaS support
3
+ - Added support for DBaaS.
4
+ - instance_type is new optional parameter (compute or dbaas)
5
+
6
+ ## 1.9.0 Use instance principals
7
+ - Added support for `use_instance_principals`
8
+
2
9
  ## 1.8.0 Freeform tags
3
10
  - Added optional parameter `freeform_tags`
4
11
 
@@ -10,4 +17,3 @@
10
17
  - Added cloud-init support.
11
18
  - Added support for Windows targets.
12
19
  - Can inject powershell script to set a random password and enable WinRM
13
-
data/README.md CHANGED
@@ -51,79 +51,100 @@ gem install pkg/kitchen-oci-<VERSION>.gem
51
51
 
52
52
  ## Example .kitchen.yml
53
53
 
54
- Adjust below template as required. The following configuration is mandatory:
54
+ Adjust below template as required. The following configuration is mandatory for all instance types:
55
55
 
56
- - compartment\_id
57
- - availability\_domain
58
- - image\_id
59
- - shape
60
- - subnet\_id
56
+ - `compartment_id`
57
+ - `availability_domain`
58
+ - `shape`
59
+ - `subnet_id`
60
+
61
+ There is an additional configuration item that allows for toggling instance types. If this item is not included, it defaults to `compute`.
62
+
63
+ - Permitted values of `instance_type`:
64
+ - compute
65
+ - dbaas
61
66
 
62
67
  Note: The availability domain should be the full AD name including the tenancy specific prefix. For example: "AaBb:US-ASHBURN-AD-1". Look in the OCI console to get your tenancy specific string.
63
68
 
69
+ ### Compute Instance Type
70
+
71
+ The following configuration is mandatory:
72
+
73
+ - `image_id`
74
+
64
75
  These settings are optional:
65
76
 
66
- - use\_private\_ip, Whether to connect to the instance using a private IP, default is false (public ip)
67
- - oci\_config\_file, OCI configuration file, by default this is ~/.oci/config
68
- - oci\_profile\_name, OCI profile to use, default value is "DEFAULT"
69
- - ssh\_keypath, SSH public key, default is ~/.ssh/id\_rsa.pub
70
- - post\_create\_script, run a script on compute\_instance after deployment
71
- - proxy\_url, Connect via the specified proxy URL
72
- - user\_data, Add user data scripts
73
- - hostname\_prefix, Prefix for the generated hostnames (note that OCI doesn't like underscores)
74
- - freeform\_tags, Hash containing tag name(s) and values(s)
75
- - use\_instance\_principals, Boolean flag indicated whether Instance Principals should be used as credentials (see below)
77
+ - `use_private_ip`, Whether to connect to the instance using a private IP, default is false (public ip)
78
+ - `oci_config_file`, OCI configuration file, by default this is ~/.oci/config
79
+ - `oci_profile_name`, OCI profile to use, default value is "DEFAULT"
80
+ - `ssh_keypath`, SSH public key, default is ~/.ssh/id\_rsa.pub
81
+ - `post_create_script`, run a script on compute\_instance after deployment
82
+ - `proxy_url`, Connect via the specified proxy URL
83
+ - `user_data`, Add user data scripts
84
+ - `hostname_prefix`, Prefix for the generated hostnames (note that OCI doesn't like underscores)
85
+ - `freeform_tags`, Hash containing tag name(s) and values(s)
86
+ - `use_instance_principals`, Boolean flag indicated whether Instance Principals should be used as credentials (see below)
76
87
 
77
88
  Optional settings for WinRM support in Windows:
78
89
 
79
- - setup\_winrm, Inject Windows powershell to set password and enable WinRM, default false.
80
- - winrm\_username, Used to set the WinRM transport username, defaults to 'opc'.
81
- - winrm\_password, Set the winrm password. By default a randomly generated password will be used, so don't set this unless you have to. Beware that the password must meet the Windows password complexity requirements otherwise the bootstrapping procedure will fail silently and Kitchen will eventually time out.
90
+ - `setup_winrm`, Inject Windows powershell to set password and enable WinRM, default false.
91
+ - `winrm_username`, Used to set the WinRM transport username, defaults to 'opc'.
92
+ - `winrm_password`, Set the winrm password. By default a randomly generated password will be used, so don't set this unless you have to. Beware that the password must meet the Windows password complexity requirements otherwise the bootstrapping procedure will fail silently and Kitchen will eventually time out.
82
93
 
83
- The use\_private\_ip influences whether the public or private IP will be used by Kitchen to connect to the instance. If it is set to false (the default) then it will connect to the public IP, otherwise it'll use the private IP.
94
+ The `use_private_ip` influences whether the public or private IP will be used by Kitchen to connect to the instance. If it is set to false (the default) then it will connect to the public IP, otherwise it'll use the private IP.
84
95
 
85
- If the subnet\_id refers to a subnet configured to disallow public IPs on any attached VNICs, then the VNIC will be created without a public IP and the use\_private\_ip flag will assumed to be true irrespective of the config setting. On subnets that do allow a public IP a public IP will be allocated to the VNIC, but the use\_private\_ip flag can still be used to override whether the private or public IP will be used.
96
+ If the `subnet_id` refers to a subnet configured to disallow public IPs on any attached VNICs, then the VNIC will be created without a public IP and the `use_private_ip` flag will assumed to be true irrespective of the config setting. On subnets that do allow a public IP a public IP will be allocated to the VNIC, but the `use_private_ip` flag can still be used to override whether the private or public IP will be used.
86
97
 
87
98
  ```yml
88
99
  ---
89
- driver:
90
- name: oci
100
+ driver:
101
+ name: oci
102
+ # These are mandatory
103
+ compartment_id: "ocid1.compartment.oc1..xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
104
+ availability_domain: "XyAb:US-ASHBURN-AD-1"
105
+ image_id: "ocid1.image.oc1.phx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
106
+ shape: "VM.Standard1.2"
107
+ subnet_id: "ocid1.subnet.oc1.phx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
108
+
109
+ # These are optional
110
+ use_private_ip: false
111
+ oci_config_file: "~/.oci/config"
112
+ oci_profile_name: "DEFAULT"
113
+ ssh_keypath: "~/.ssh/id_rsa.pub"
114
+ post_create_script: >-
115
+ ```
91
116
 
92
- provisioner:
93
- name: chef_zero
94
- always_update_cookbooks: true
117
+ ### DBaaS Instance Type
95
118
 
96
- verifier:
97
- name: inspec
119
+ The DBaaS instance type configuration should be written in a hash beginning with `dbaas`.
98
120
 
99
- platforms:
100
- - name: ubuntu-18.04
101
- driver:
102
- # These are mandatory
103
- compartment_id: "ocid1.compartment.oc1..xxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
104
- availability_domain: "XyAb:US-ASHBURN-AD-1"
105
- image_id: "ocid1.image.oc1.phx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
106
- shape: "VM.Standard1.2"
107
- subnet_id: "ocid1.subnet.oc1.phx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
121
+ The following configuration item is mandatory for the DBaaS `instance_type`:
108
122
 
109
- # These are optional
110
- use_private_ip: false
111
- oci_config_file: "~/.oci/config"
112
- oci_profile_name: "DEFAULT"
113
- ssh_keypath: "~/.ssh/id_rsa.pub"
114
- post_create_script: >-
115
- touch /tmp/example.txt;
116
- transport:
117
- username: "ubuntu"
123
+ - `db_version`, The specific version of the Oracle database software to be installed. Values can be at either the major version level (eg. 12.1.0.2) or at a PSU level (eg. 12.1.0.2.191015). If no PSU is provided, the latest available will be installed.
118
124
 
119
- suites:
120
- - name: default
121
- run_list:
122
- - recipe[my_cookbook::default]
123
- verifier:
124
- inspec_tests:
125
- - test/smoke/default
126
- attributes:
125
+ The following is a list of optional items for the DBaaS `instance_type`:
126
+
127
+ - `cpu_core_count`, CPU core count for DBaaS nodes. Default value is 2
128
+ - `database_edition`, The edition of the Oracle database software to be installed. Default value is ENTERPRISE_EDITION
129
+ - `license_model`, The licensing model for the Oracle database software. Default value is BRING_YOUR_OWN_LICENSE
130
+ - `db_name`, The name of the database to be provisioned. Must be 8 characters or less, alphanumeric. Default value is `dbaas1`.
131
+ - `pdb_name`, The name of the pdb to be provisioned. Only valid if `db_version` is 12cR1 or higher. Default value is nil (OCI will create a single pdb with the name `db_name`\_PDB1)
132
+ - `admin_password`, The SYS password of the database to be provisioned. Password must be 9 to 30 characters and contain at least 2 uppercase, 2 lowercase, 2 special, and 2 numeric characters. The special characters must be `_`, `#`, or `-`. Default value will be a randomly generated password
133
+ - `initial_data_storage_size_in_gb`, The desired amount of database storage in GB. Default value is 256
134
+ - `character_set`, The characterset of the database. Default value is AL32UTF8
135
+ - `ncharacter_set`, The national characterset of the database. Default value is AL16UTF16
136
+ - `db_workload`, The desired workload configuration for the database. Acceptable values are 'OLTP' and 'DSS'. Default value is 'OLTP'
137
+
138
+ Note: At this time, `node_count` is forced to be 1. RAC provisioning is not supported.
139
+
140
+ ```yml
141
+ ---
142
+ driver:
143
+ name: oci
144
+ instance_type: dbaas
145
+ ...
146
+ dbaas:
147
+ db_version: "12.1.0.2.191015"
127
148
  ```
128
149
 
129
150
  ## Instance Principals
@@ -152,15 +173,15 @@ This will allow the OCI lib to retrieve the certificate, key and ca-chain from t
152
173
  The driver has support for adding user data that can be executed as scripts by cloud-init. These can either be specified inline or by referencing a file. Examples:
153
174
 
154
175
  ```yml
155
- user_data:
156
- - type: x-shellscript
157
- inline: |
158
- #!/bin/bash
159
- touch /tmp/foo.txt
160
- filename: init.sh
161
- - type: x-shellscript
162
- path: myscript.sh
163
- filename: myscript.sh
176
+ user_data:
177
+ - type: x-shellscript
178
+ inline: |
179
+ #!/bin/bash
180
+ touch /tmp/foo.txt
181
+ filename: init.sh
182
+ - type: x-shellscript
183
+ path: myscript.sh
184
+ filename: myscript.sh
164
185
  ```
165
186
 
166
187
  The `filename` parameter must be specified for each entry, and determines the destination filename for the script. If the user data is to be read from a file then the `path` parameter should be specified to indicate where the file is to be read from.
@@ -198,7 +219,7 @@ See also the section above on Instance Principals if you plan to use a proxy in
198
219
 
199
220
  ## Windows Support
200
221
 
201
- When launching Oracle provided Windows images, it may be helpful to allow Kitchen-oci to inject powershell to configure WinRM and to set a randomized password that does not need to be changed on first login. If the `setup_winrm` parameter is set to true then the following steps will happen:
222
+ When launching Oracle provided Windows images, it may be helpful to allow kitchen-oci to inject powershell to configure WinRM and to set a randomized password that does not need to be changed on first login. If the `setup_winrm` parameter is set to true then the following steps will happen:
202
223
 
203
224
  - A random password will be generated and stored into the Kitchen state
204
225
  - A powershell script will be generated which sets the password for whatever username is defined in the transport section.
@@ -21,7 +21,6 @@
21
21
 
22
22
  # This require fixes bug in ChefDK 4.0.60-1 on Linux.
23
23
  require 'forwardable'
24
-
25
24
  require 'base64'
26
25
  require 'erb'
27
26
  require 'kitchen'
@@ -35,15 +34,14 @@ module Kitchen
35
34
  #
36
35
  # @author Stephen Pearson <stephen.pearson@oracle.com>
37
36
  class Oci < Kitchen::Driver::Base # rubocop:disable Metrics/ClassLength
37
+ # required config items
38
38
  required_config :compartment_id
39
39
  required_config :availability_domain
40
- required_config :image_id
41
40
  required_config :shape
42
41
  required_config :subnet_id
43
42
 
44
- default_config :use_private_ip, false
45
- default_config :oci_config_file, nil
46
- default_config :oci_profile_name, nil
43
+ # common config items
44
+ default_config :instance_type, 'compute'
47
45
  default_config :hostname_prefix, nil
48
46
  default_keypath = File.expand_path(File.join(%w[~ .ssh id_rsa.pub]))
49
47
  default_config :ssh_keypath, default_keypath
@@ -51,32 +49,19 @@ module Kitchen
51
49
  default_config :proxy_url, nil
52
50
  default_config :user_data, []
53
51
  default_config :freeform_tags, {}
52
+
53
+ # compute config items
54
+ default_config :image_id
55
+ default_config :use_private_ip, false
56
+ default_config :oci_config_file, nil
57
+ default_config :oci_profile_name, nil
54
58
  default_config :setup_winrm, false
55
59
  default_config :winrm_user, 'opc'
56
60
  default_config :winrm_password, nil
57
61
  default_config :use_instance_principals, false
58
62
 
59
- def process_freeform_tags(freeform_tags)
60
- prov = instance.provisioner.instance_variable_get(:@config)
61
- tags = %w[run_list policyfile]
62
- tags.each do |tag|
63
- unless prov[tag.to_sym].nil? || prov[tag.to_sym].empty?
64
- freeform_tags[tag] = prov[tag.to_sym].join(',')
65
- end
66
- end
67
- freeform_tags[:kitchen] = true
68
- freeform_tags
69
- end
70
-
71
- def process_windows_options(state)
72
- state[:username] = config[:winrm_user] if config[:setup_winrm]
73
- if config[:setup_winrm] == true &&
74
- config[:password].nil? &&
75
- state[:password].nil?
76
- state[:password] = config[:winrm_password] || random_password
77
- end
78
- state
79
- end
63
+ # dbaas config items
64
+ default_config :dbaas, {}
80
65
 
81
66
  def create(state)
82
67
  return if state[:server_id]
@@ -84,6 +69,7 @@ module Kitchen
84
69
  state = process_windows_options(state)
85
70
 
86
71
  instance_id = launch_instance(state)
72
+
87
73
  state[:server_id] = instance_id
88
74
  state[:hostname] = instance_ip(instance_id)
89
75
 
@@ -100,23 +86,53 @@ module Kitchen
100
86
  return unless state[:server_id]
101
87
 
102
88
  instance.transport.connection(state).close
103
- comp_api.terminate_instance(state[:server_id])
89
+
90
+ if instance_type == 'compute'
91
+ comp_api.terminate_instance(state[:server_id])
92
+ elsif instance_type == 'dbaas'
93
+ dbaas_api.terminate_db_system(state[:server_id])
94
+ end
104
95
 
105
96
  state.delete(:server_id)
106
97
  state.delete(:hostname)
107
98
  end
108
99
 
100
+ def process_freeform_tags(freeform_tags)
101
+ prov = instance.provisioner.instance_variable_get(:@config)
102
+ tags = %w[run_list policyfile]
103
+ tags.each do |tag|
104
+ freeform_tags[tag] = prov[tag.to_sym].join(',') unless prov[tag.to_sym].nil? || prov[tag.to_sym].empty?
105
+ end
106
+ freeform_tags[:kitchen] = true
107
+ freeform_tags
108
+ end
109
+
110
+ def process_windows_options(state)
111
+ state[:username] = config[:winrm_user] if config[:setup_winrm]
112
+ if config[:setup_winrm] == true &&
113
+ config[:password].nil? &&
114
+ state[:password].nil?
115
+ state[:password] = config[:winrm_password] || random_password
116
+ end
117
+ state
118
+ end
119
+
109
120
  private
110
121
 
122
+ def instance_type
123
+ raise 'instance_type must be either compute or dbaas!' unless %w[compute dbaas].include?(config[:instance_type].downcase)
124
+
125
+ config[:instance_type].downcase
126
+ end
127
+
128
+ ####################
129
+ # OCI config setup #
130
+ ####################
111
131
  def oci_config
112
132
  params = [:load_config]
113
133
  opts = {}
114
- if config[:oci_config_file]
115
- opts[:config_file_location] = config[:oci_config_file]
116
- end
117
- if config[:oci_profile_name]
118
- opts[:profile_name] = config[:oci_profile_name]
119
- end
134
+ opts[:config_file_location] = config[:oci_config_file] if config[:oci_config_file]
135
+ opts[:profile_name] = config[:oci_profile_name] if config[:oci_profile_name]
120
136
  params << opts
121
137
  OCI::ConfigFileLoader.send(*params)
122
138
  end
@@ -141,6 +157,9 @@ module Kitchen
141
157
  end
142
158
  end
143
159
 
160
+ #############
161
+ # API setup #
162
+ #############
144
163
  def generic_api(klass)
145
164
  api_prx = api_proxy
146
165
  if config[:use_instance_principals]
@@ -161,11 +180,90 @@ module Kitchen
161
180
  generic_api(OCI::Core::VirtualNetworkClient)
162
181
  end
163
182
 
183
+ def dbaas_api
184
+ generic_api(OCI::Database::DatabaseClient)
185
+ end
186
+
187
+ ##################
188
+ # Common methods #
189
+ ##################
164
190
  def launch_instance(state)
165
- request = compute_instance_request(state)
191
+ if instance_type == 'compute'
192
+ launch_compute_instance(state)
193
+ elsif instance_type == 'dbaas'
194
+ launch_dbaas_instance
195
+ end
196
+ end
197
+
198
+ def public_ip_allowed?
199
+ subnet = net_api.get_subnet(config[:subnet_id]).data
200
+ !subnet.prohibit_public_ip_on_vnic
201
+ end
202
+
203
+ def instance_ip(instance_id)
204
+ if instance_type == 'compute'
205
+ compute_instance_ip(instance_id)
206
+ elsif instance_type == 'dbaas'
207
+ dbaas_instance_ip(instance_id)
208
+ end
209
+ end
210
+
211
+ def pubkey
212
+ if instance_type == 'compute'
213
+ File.readlines(config[:ssh_keypath]).first.chomp
214
+ elsif instance_type == 'dbaas'
215
+ result = []
216
+ result << File.readlines(config[:ssh_keypath]).first.chomp
217
+ end
218
+ end
219
+
220
+ def generate_hostname
221
+ prefix = config[:hostname_prefix]
222
+ if instance_type == 'compute'
223
+ [prefix, random_hostname(instance.name)].compact.join('-')
224
+ elsif instance_type == 'dbaas'
225
+ # 30 character limit for hostname in DBaaS
226
+ if prefix.length > 30
227
+ [prefix[0, 26], 'db1'].compact.join('-')
228
+ else
229
+ [prefix, random_string(25 - prefix.length), 'db1'].compact.join('-')
230
+ end
231
+ end
232
+ end
233
+
234
+ def random_hostname(prefix)
235
+ "#{prefix}-#{random_string(6)}"
236
+ end
237
+
238
+ def random_password
239
+ if instance_type == 'compute'
240
+ special_chars = %w[! " # & ( ) * + , - . /]
241
+ elsif instance_type == 'dbaas'
242
+ special_chars = %w[# _ -]
243
+ end
166
244
 
245
+ (Array.new(5) { special_chars.sample } +
246
+ Array.new(5) { ('a'..'z').to_a.sample } +
247
+ Array.new(5) { ('A'..'Z').to_a.sample } +
248
+ Array.new(5) { ('0'..'9').to_a.sample }).shuffle.join
249
+ end
250
+
251
+ def random_string(length)
252
+ Array.new(length) { ('a'..'z').to_a.sample }.join
253
+ end
254
+
255
+ def random_number(length)
256
+ Array.new(length) { ('0'..'9').to_a.sample }.join
257
+ end
258
+
259
+ ###################
260
+ # Compute methods #
261
+ ###################
262
+ def launch_compute_instance(state)
263
+ request = compute_instance_request(state)
167
264
  response = comp_api.launch_instance(request)
168
265
  instance_id = response.data.id
266
+
169
267
  comp_api.get_instance(instance_id).wait_until(
170
268
  :lifecycle_state,
171
269
  OCI::Core::Models::Instance::LIFECYCLE_STATE_RUNNING
@@ -173,36 +271,32 @@ module Kitchen
173
271
  instance_id
174
272
  end
175
273
 
176
- def vnic_attachments(instance_id)
177
- att = comp_api.list_vnic_attachments(
178
- config[:compartment_id],
179
- instance_id: instance_id
180
- ).data
181
-
182
- raise 'Could not find any VNIC attachments' unless att.any?
274
+ def compute_instance_request(state)
275
+ request = compute_launch_details
183
276
 
184
- att
185
- end
277
+ inject_powershell(state) if config[:setup_winrm] == true
186
278
 
187
- def vnics(instance_id)
188
- vnic_attachments(instance_id).map do |att|
189
- net_api.get_vnic(att.vnic_id).data
190
- end
279
+ metadata = {}
280
+ metadata.store('ssh_authorized_keys', pubkey)
281
+ data = user_data
282
+ metadata.store('user_data', data) if config[:user_data].any?
283
+ request.metadata = metadata
284
+ request
191
285
  end
192
286
 
193
- def instance_ip(instance_id)
194
- vnic = vnics(instance_id).select(&:is_primary).first
195
- if public_ip_allowed?
196
- config[:use_private_ip] ? vnic.private_ip : vnic.public_ip
197
- else
198
- vnic.private_ip
287
+ def compute_launch_details
288
+ OCI::Core::Models::LaunchInstanceDetails.new.tap do |l|
289
+ hostname = generate_hostname
290
+ l.availability_domain = config[:availability_domain]
291
+ l.compartment_id = config[:compartment_id]
292
+ l.display_name = hostname
293
+ l.source_details = instance_source_details
294
+ l.shape = config[:shape]
295
+ l.create_vnic_details = create_vnic_details(hostname)
296
+ l.freeform_tags = process_freeform_tags(config[:freeform_tags])
199
297
  end
200
298
  end
201
299
 
202
- def pubkey
203
- File.readlines(config[:ssh_keypath]).first.chomp
204
- end
205
-
206
300
  def instance_source_details
207
301
  OCI::Core::Models::InstanceSourceViaImageDetails.new(
208
302
  sourceType: 'image',
@@ -210,11 +304,6 @@ module Kitchen
210
304
  )
211
305
  end
212
306
 
213
- def public_ip_allowed?
214
- subnet = net_api.get_subnet(config[:subnet_id]).data
215
- !subnet.prohibit_public_ip_on_vnic
216
- end
217
-
218
307
  def create_vnic_details(name)
219
308
  OCI::Core::Models::CreateVnicDetails.new(
220
309
  assign_public_ip: public_ip_allowed?,
@@ -224,12 +313,48 @@ module Kitchen
224
313
  )
225
314
  end
226
315
 
316
+ def vnics(instance_id)
317
+ vnic_attachments(instance_id).map do |att|
318
+ net_api.get_vnic(att.vnic_id).data
319
+ end
320
+ end
321
+
322
+ def vnic_attachments(instance_id)
323
+ att = comp_api.list_vnic_attachments(
324
+ config[:compartment_id],
325
+ instance_id: instance_id
326
+ ).data
327
+
328
+ raise 'Could not find any VNIC attachments' unless att.any?
329
+
330
+ att
331
+ end
332
+
333
+ def compute_instance_ip(instance_id)
334
+ vnic = vnics(instance_id).select(&:is_primary).first
335
+ if public_ip_allowed?
336
+ config[:use_private_ip] ? vnic.private_ip : vnic.public_ip
337
+ else
338
+ vnic.private_ip
339
+ end
340
+ end
341
+
227
342
  def winrm_ps1(state)
228
343
  filename = File.join(__dir__, %w[.. .. .. tpl setup_winrm.ps1.erb])
229
344
  tpl = ERB.new(File.read(filename))
230
345
  tpl.result(binding)
231
346
  end
232
347
 
348
+ def inject_powershell(state)
349
+ data = winrm_ps1(state)
350
+ config[:user_data] ||= []
351
+ config[:user_data] << {
352
+ type: 'x-shellscript',
353
+ inline: data,
354
+ filename: 'setup_winrm.ps1'
355
+ }
356
+ end
357
+
233
358
  def read_part(part)
234
359
  if part[:path]
235
360
  content = File.read part[:path]
@@ -265,60 +390,100 @@ module Kitchen
265
390
  Base64.encode64(gzip.close.string).delete("\n")
266
391
  end
267
392
 
268
- def inject_powershell(state)
269
- data = winrm_ps1(state)
270
- config[:user_data] ||= []
271
- config[:user_data] << {
272
- type: 'x-shellscript',
273
- inline: data,
274
- filename: 'setup_winrm.ps1'
275
- }
276
- end
393
+ #################
394
+ # DBaaS methods #
395
+ #################
396
+ def launch_dbaas_instance
397
+ request = dbaas_launch_details
398
+ response = dbaas_api.launch_db_system(request)
399
+ instance_id = response.data.id
277
400
 
278
- def generate_hostname
279
- prefix = config[:hostname_prefix]
280
- [prefix, random_hostname(instance.name)].compact.join('-')
401
+ dbaas_api.get_db_system(instance_id).wait_until(
402
+ :lifecycle_state,
403
+ OCI::Database::Models::DbSystem::LIFECYCLE_STATE_AVAILABLE,
404
+ max_interval_seconds: 900,
405
+ max_wait_seconds: 21600
406
+ )
407
+ instance_id
281
408
  end
282
409
 
283
- def base_oci_launch_details
284
- OCI::Core::Models::LaunchInstanceDetails.new.tap do |l|
285
- hostname = generate_hostname
410
+ def dbaas_launch_details # rubocop:disable Metrics/MethodLength
411
+ cpu_core_count = config[:dbaas][:cpu_core_count] ||= 2
412
+ database_edition = config[:dbaas][:database_edition] ||= OCI::Database::Models::DbSystem::DATABASE_EDITION_ENTERPRISE_EDITION
413
+ initial_data_storage_size_in_gb = config[:dbaas][:initial_data_storage_size_in_gb] ||= 256
414
+ license_model = config[:dbaas][:license_model] ||= OCI::Database::Models::DbSystem::LICENSE_MODEL_BRING_YOUR_OWN_LICENSE
415
+
416
+ OCI::Database::Models::LaunchDbSystemDetails.new.tap do |l|
286
417
  l.availability_domain = config[:availability_domain]
287
418
  l.compartment_id = config[:compartment_id]
288
- l.display_name = hostname
289
- l.source_details = instance_source_details
419
+ l.cpu_core_count = cpu_core_count
420
+ l.database_edition = database_edition
421
+ l.db_home = create_db_home_details
422
+ l.display_name = [config[:hostname_prefix], random_string(4), random_number(2)].compact.join('-')
423
+ l.hostname = generate_hostname
290
424
  l.shape = config[:shape]
291
- l.create_vnic_details = create_vnic_details(hostname)
425
+ l.ssh_public_keys = pubkey
426
+ l.cluster_name = [config[:hostname_prefix].split('-')[0], random_string(3), random_number(2)].compact.join('-')
427
+ l.initial_data_storage_size_in_gb = initial_data_storage_size_in_gb
428
+ l.node_count = 1
429
+ l.license_model = license_model
430
+ l.subnet_id = config[:subnet_id]
292
431
  l.freeform_tags = process_freeform_tags(config[:freeform_tags])
293
432
  end
294
433
  end
295
434
 
296
- def compute_instance_request(state)
297
- request = base_oci_launch_details
435
+ def create_db_home_details
436
+ raise 'db_version cannot be nil!' if config[:dbaas][:db_version].nil?
298
437
 
299
- inject_powershell(state) if config[:setup_winrm] == true
438
+ OCI::Database::Models::CreateDbHomeDetails.new.tap do |l|
439
+ l.database = create_database_details
440
+ l.db_version = config[:dbaas][:db_version]
441
+ l.display_name = ['dbhome', random_number(10)].compact.join('')
442
+ end
443
+ end
300
444
 
301
- metadata = {}
302
- metadata.store('ssh_authorized_keys', pubkey)
303
- data = user_data
304
- metadata.store('user_data', data) if config[:user_data].any?
305
- request.metadata = metadata
306
- request
445
+ def create_database_details # rubocop:disable Metrics/MethodLength
446
+ character_set = config[:dbaas][:character_set] ||= 'AL32UTF8'
447
+ ncharacter_set = config[:dbaas][:ncharacter_set] ||= 'AL16UTF16'
448
+ db_workload = config[:dbaas][:db_workload] ||= OCI::Database::Models::CreateDatabaseDetails::DB_WORKLOAD_OLTP
449
+ admin_password = config[:dbaas][:admin_password] ||= random_password
450
+ db_name = config[:dbaas][:db_name] ||= 'dbaas1'
451
+
452
+ OCI::Database::Models::CreateDatabaseDetails.new.tap do |l|
453
+ l.admin_password = admin_password
454
+ l.character_set = character_set
455
+ l.db_name = db_name
456
+ l.db_workload = db_workload
457
+ l.ncharacter_set = ncharacter_set
458
+ l.pdb_name = config[:dbaas][:pdb_name]
459
+ l.db_backup_config = db_backup_config
460
+ end
307
461
  end
308
462
 
309
- def random_hostname(prefix)
310
- "#{prefix}-#{random_string(6)}"
463
+ def db_backup_config
464
+ OCI::Database::Models::DbBackupConfig.new.tap do |l|
465
+ l.auto_backup_enabled = false
466
+ end
311
467
  end
312
468
 
313
- def random_password
314
- (Array.new(5) { %w[! " # & ( ) * + , - . /].sample } +
315
- Array.new(5) { ('a'..'z').to_a.sample } +
316
- Array.new(5) { ('A'..'Z').to_a.sample } +
317
- Array.new(5) { ('0'..'9').to_a.sample }).shuffle.join
469
+ def dbaas_node(instance_id)
470
+ dbaas_api.list_db_nodes(
471
+ config[:compartment_id],
472
+ db_system_id: instance_id
473
+ ).data
318
474
  end
319
475
 
320
- def random_string(length)
321
- Array.new(length) { ('a'..'z').to_a.sample }.join
476
+ def dbaas_vnic(node_ocid)
477
+ dbaas_api.get_db_node(node_ocid).data
478
+ end
479
+
480
+ def dbaas_instance_ip(instance_id)
481
+ vnic = dbaas_node(instance_id).select(&:vnic_id).first.vnic_id
482
+ if public_ip_allowed?
483
+ net_api.get_vnic(vnic).data.public_ip
484
+ else
485
+ net_api.get_vnic(vnic).data.private_ip
486
+ end
322
487
  end
323
488
  end
324
489
  end
@@ -20,6 +20,6 @@
20
20
  module Kitchen
21
21
  module Driver
22
22
  # Version string for Oracle OCI Kitchen driver
23
- OCI_VERSION = '1.9.0'
23
+ OCI_VERSION = '1.10.0'
24
24
  end
25
25
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kitchen-oci
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.9.0
4
+ version: 1.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen Pearson
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-10 00:00:00.000000000 Z
11
+ date: 2020-01-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oci
@@ -117,6 +117,7 @@ extra_rdoc_files: []
117
117
  files:
118
118
  - ".cane"
119
119
  - ".gitignore"
120
+ - ".rubocop.yml"
120
121
  - ".travis.yml"
121
122
  - CHANGELOG.md
122
123
  - Gemfile
@@ -146,7 +147,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
146
147
  - !ruby/object:Gem::Version
147
148
  version: '0'
148
149
  requirements: []
149
- rubygems_version: 3.0.1
150
+ rubygems_version: 3.0.3
150
151
  signing_key:
151
152
  specification_version: 4
152
153
  summary: A Test Kitchen Driver for Oracle OCI