kitchen-oci 1.25.0 → 1.26.0

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
  SHA256:
3
- metadata.gz: db93079acea4739f9970e3a00627fe554719df5effc9e3b78d45287ea14fa730
4
- data.tar.gz: 7dcc0d262fe162aa8db4cd351ff588a965f7560e01d9eccb5b7a6d901098faeb
3
+ metadata.gz: 1d223f52ef9973e25f1185d4646a7d1728f5eb0b760bcbe85c8b5cbe150f47bd
4
+ data.tar.gz: fbe86e8e26c0cb4cae838bc58e277e7e3c4c06e2850ad73b6b5ff9be46f30f00
5
5
  SHA512:
6
- metadata.gz: 79774b7b41ea8e9ee93c70f708fd2ff4e2f64efda2037e6237445cabff246a42ea6250d548d3bea9d8e843aaded434eebc55bccae219675169e455d4f73ea314
7
- data.tar.gz: 65907206e93b70b092a6a4154e5f1a3ce8490412950e41759856eb032940eed1fcf4227089db4bc4682711634276864af78eff5016915db2593f8c63793a86bc
6
+ metadata.gz: 39140520616c5ee302c3ba7766437598bb93ba2199aa1ea9cfe3e5525e972daacb7aacd40e95b39a9a72be9dad333d5f22c8b8cbb812d14f800e360527ce72d1
7
+ data.tar.gz: 86bbbecc3e66a2ec67607d889570d5c55ce88c45579903741d8021679b1cba1e83f9c00a3da974e3e68fd86ecb9c9457d1b9fdc913198b37a911f364565fe77c
@@ -26,15 +26,16 @@ module Kitchen
26
26
  require_relative "models/iscsi"
27
27
  require_relative "models/paravirtual"
28
28
 
29
- def initialize(config, state, oci, api, action = :create)
29
+ def initialize(opts = {})
30
30
  super()
31
- @config = config
32
- @state = state
33
- @oci = oci
34
- @api = api
31
+ @config = opts[:config]
32
+ @state = opts[:state]
33
+ @oci = opts[:oci]
34
+ @api = opts[:api]
35
+ @logger = opts[:logger]
35
36
  @volume_state = {}
36
37
  @volume_attachment_state = {}
37
- oci.compartment if action == :create
38
+ oci.compartment if opts[:action] == :create
38
39
  end
39
40
 
40
41
  #
@@ -65,6 +66,13 @@ module Kitchen
65
66
  #
66
67
  attr_accessor :api
67
68
 
69
+ #
70
+ # The instance of Kitchen::Logger in use by the active Kitchen::Instance
71
+ #
72
+ # @return [Kitchen::Logger]
73
+ #
74
+ attr_accessor :logger
75
+
68
76
  # The definition of the state of a volume
69
77
  #
70
78
  # @return [Hash]
@@ -78,44 +86,44 @@ module Kitchen
78
86
  attr_accessor :volume_attachment_state
79
87
 
80
88
  def create_volume(volume)
81
- info("Creating <#{volume[:name]}>...")
89
+ logger.info("Creating <#{volume[:name]}>...")
82
90
  result = api.blockstorage.create_volume(volume_details(volume))
83
91
  response = volume_response(result.data.id)
84
- info("Finished creating <#{volume[:name]}>.")
92
+ logger.info("Finished creating <#{volume[:name]}>.")
85
93
  [response, final_state(response)]
86
94
  end
87
95
 
88
96
  def create_clone_volume(volume)
89
97
  clone_volume_name = clone_volume_display_name(volume[:volume_id])
90
- info("Creating <#{clone_volume_name}>...")
98
+ logger.info("Creating <#{clone_volume_name}>...")
91
99
  result = api.blockstorage.create_volume(volume_clone_details(volume, clone_volume_name))
92
100
  response = volume_response(result.data.id)
93
- info("Finished creating <#{clone_volume_name}>.")
101
+ logger.info("Finished creating <#{clone_volume_name}>.")
94
102
  [response, final_state(response)]
95
103
  end
96
104
 
97
105
  def attach_volume(volume_details, server_id, volume_config)
98
- info("Attaching <#{volume_details.display_name}>...")
106
+ logger.info("Attaching <#{volume_details.display_name}>...")
99
107
  attach_volume = api.compute.attach_volume(attachment_details(volume_details, server_id, volume_config))
100
108
  response = attachment_response(attach_volume.data.id)
101
- info("Finished attaching <#{volume_details.display_name}>.")
109
+ logger.info("Finished attaching <#{volume_details.display_name}>.")
102
110
  final_state(response)
103
111
  end
104
112
 
105
113
  def delete_volume(volume)
106
- info("Deleting <#{volume[:display_name]}>...")
114
+ logger.info("Deleting <#{volume[:display_name]}>...")
107
115
  api.blockstorage.delete_volume(volume[:id])
108
116
  api.blockstorage.get_volume(volume[:id])
109
117
  .wait_until(:lifecycle_state, OCI::Core::Models::Volume::LIFECYCLE_STATE_TERMINATED)
110
- info("Finished deleting <#{volume[:display_name]}>.")
118
+ logger.info("Finished deleting <#{volume[:display_name]}>.")
111
119
  end
112
120
 
113
121
  def detatch_volume(volume_attachment)
114
- info("Detaching <#{attachment_name(volume_attachment)}>...")
122
+ logger.info("Detaching <#{attachment_name(volume_attachment)}>...")
115
123
  api.compute.detach_volume(volume_attachment[:id])
116
124
  api.compute.get_volume_attachment(volume_attachment[:id])
117
125
  .wait_until(:lifecycle_state, OCI::Core::Models::VolumeAttachment::LIFECYCLE_STATE_DETACHED)
118
- info("Finished detaching <#{attachment_name(volume_attachment)}>.")
126
+ logger.info("Finished detaching <#{attachment_name(volume_attachment)}>.")
119
127
  end
120
128
 
121
129
  def final_state(response)
@@ -61,7 +61,7 @@ module Kitchen
61
61
 
62
62
  def pubkey
63
63
  result = []
64
- result << File.readlines(config[:ssh_keypath]).first.chomp
64
+ result << read_public_key
65
65
  launch_details.ssh_public_keys = result
66
66
  end
67
67
 
@@ -30,12 +30,13 @@ module Kitchen
30
30
 
31
31
  include CommonLaunchDetails
32
32
 
33
- def initialize(config, state, oci, api, action)
33
+ def initialize(opts = {})
34
34
  super()
35
- @config = config
36
- @state = state
37
- @oci = oci
38
- @api = api
35
+ @config = opts[:config]
36
+ @state = opts[:state]
37
+ @oci = opts[:oci]
38
+ @api = opts[:api]
39
+ @logger = opts[:logger]
39
40
  end
40
41
 
41
42
  #
@@ -66,6 +67,13 @@ module Kitchen
66
67
  #
67
68
  attr_accessor :api
68
69
 
70
+ #
71
+ # The instance of Kitchen::Logger in use by the active Kitchen::Instance
72
+ #
73
+ # @return [Kitchen::Logger]
74
+ #
75
+ attr_accessor :logger
76
+
69
77
  def final_state(state, instance_id)
70
78
  state.store(:server_id, instance_id)
71
79
  state.store(:hostname, instance_ip(instance_id))
@@ -88,6 +96,43 @@ module Kitchen
88
96
  !subnet.prohibit_public_ip_on_vnic
89
97
  end
90
98
 
99
+ def public_key_file
100
+ if config[:ssh_keygen]
101
+ "#{config[:kitchen_root]}/.kitchen/.ssh/#{config[:instance_name]}_rsa.pub"
102
+ else
103
+ config[:ssh_keypath]
104
+ end
105
+ end
106
+
107
+ def private_key_file
108
+ public_key_file.gsub(".pub", "")
109
+ end
110
+
111
+ def gen_key_pair
112
+ FileUtils.mkdir_p("#{config[:kitchen_root]}/.kitchen/.ssh")
113
+ rsa_key = OpenSSL::PKey::RSA.new(4096)
114
+ write_private_key(rsa_key)
115
+ write_public_key(rsa_key)
116
+ state.store(:ssh_key, private_key_file)
117
+ end
118
+
119
+ def write_private_key(rsa_key)
120
+ File.open(private_key_file, "wb") { |k| k.write(rsa_key.to_pem) }
121
+ File.chmod(0600, private_key_file)
122
+ end
123
+
124
+ def write_public_key(rsa_key)
125
+ File.open(public_key_file, "wb") { |k| k.write("ssh-rsa #{encode_private_key(rsa_key)} #{config[:instance_name]}") }
126
+ File.chmod(0600, public_key_file)
127
+ end
128
+
129
+ def encode_private_key(rsa_key)
130
+ prefix = "#{[7].pack("N")}ssh-rsa"
131
+ exponent = rsa_key.e.to_s(0)
132
+ modulus = rsa_key.n.to_s(0)
133
+ ["#{prefix}#{exponent}#{modulus}"].pack("m0")
134
+ end
135
+
91
136
  def random_password(special_chars)
92
137
  (Array.new(5) { special_chars.sample } +
93
138
  Array.new(5) { ("a".."z").to_a.sample } +
@@ -26,7 +26,7 @@ module Kitchen
26
26
  class Compute < Instance # rubocop:disable Metrics/ClassLength
27
27
  include ComputeLaunchDetails
28
28
 
29
- def initialize(config, state, oci, api, action)
29
+ def initialize(opts = {})
30
30
  super
31
31
  @launch_details = OCI::Core::Models::LaunchInstanceDetails.new
32
32
  end
@@ -102,10 +102,10 @@ module Kitchen
102
102
  end
103
103
 
104
104
  def clone_boot_volume
105
- info("Cloning boot volume...")
105
+ logger.info("Cloning boot volume...")
106
106
  cbv = api.blockstorage.create_boot_volume(clone_boot_volume_details)
107
107
  api.blockstorage.get_boot_volume(cbv.data.id).wait_until(:lifecycle_state, OCI::Core::Models::BootVolume::LIFECYCLE_STATE_AVAILABLE)
108
- info("Finished cloning boot volume.")
108
+ logger.info("Finished cloning boot volume.")
109
109
  cbv.data.id
110
110
  end
111
111
 
@@ -159,15 +159,19 @@ module Kitchen
159
159
  end
160
160
 
161
161
  def pubkey
162
- File.readlines(config[:ssh_keypath]).first.chomp
162
+ if config[:ssh_keygen]
163
+ logger.info("Generating public/private rsa key pair")
164
+ gen_key_pair
165
+ end
166
+ File.readlines(public_key_file).first.chomp
163
167
  end
164
168
 
165
169
  def metadata
166
170
  md = {}
167
171
  inject_powershell
168
172
  config[:custom_metadata]&.each { |k, v| md.store(k, v) }
169
- md.store("ssh_authorized_keys", pubkey)
170
- md.store("user_data", user_data) if config[:user_data] && !config[:user_data].empty?
173
+ md.store("ssh_authorized_keys", pubkey) unless config[:setup_winrm]
174
+ md.store("user_data", user_data) if user_data?
171
175
  md
172
176
  end
173
177
 
@@ -182,6 +186,10 @@ module Kitchen
182
186
  config[:setup_winrm] && config[:password].nil? && state[:password].nil?
183
187
  end
184
188
 
189
+ def user_data?
190
+ config[:user_data] && !config[:user_data].empty?
191
+ end
192
+
185
193
  def winrm_ps1
186
194
  filename = File.join(__dir__, %w{.. .. .. .. .. tpl setup_winrm.ps1.erb})
187
195
  tpl = ERB.new(File.read(filename))
@@ -26,7 +26,7 @@ module Kitchen
26
26
  class Dbaas < Instance # rubocop:disable Metrics/ClassLength
27
27
  include DbaasLaunchDetails
28
28
 
29
- def initialize(config, state, oci, api, action)
29
+ def initialize(opts = {})
30
30
  super
31
31
  @launch_details = OCI::Database::Models::LaunchDbSystemDetails.new
32
32
  @database_details = OCI::Database::Models::CreateDatabaseDetails.new
@@ -97,6 +97,14 @@ module Kitchen
97
97
  def long_hostname_suffix
98
98
  [random_string(25 - hostname_prefix.length), random_string(3)].compact.join("-")
99
99
  end
100
+
101
+ def read_public_key
102
+ if config[:ssh_keygen]
103
+ logger.info("Generating public/private rsa key pair")
104
+ gen_key_pair
105
+ end
106
+ File.readlines(public_key_file).first.chomp
107
+ end
100
108
  end
101
109
  end
102
110
  end
@@ -23,7 +23,7 @@ module Kitchen
23
23
  module Models
24
24
  # iscsi volume attachment model
25
25
  class Iscsi < Blockstorage
26
- def initialize(config, state, oci, api)
26
+ def initialize(opts = {})
27
27
  super
28
28
  @attachment_type = "iscsi"
29
29
  end
@@ -23,7 +23,7 @@ module Kitchen
23
23
  module Models
24
24
  # paravirtual attachment model
25
25
  class Paravirtual < Blockstorage
26
- def initialize(config, state, oci, api)
26
+ def initialize(opts = {})
27
27
  super
28
28
  @attachment_type = "paravirtual"
29
29
  end
@@ -26,11 +26,11 @@ module Kitchen
26
26
  require_relative "blockstorage"
27
27
 
28
28
  def instance_class(config, state, oci, api, action)
29
- Oci::Models.const_get(config[:instance_type].capitalize).new(config, state, oci, api, action)
29
+ Oci::Models.const_get(config[:instance_type].capitalize).new(config: config, state: state, oci: oci, api: api, action: action, logger: instance.logger)
30
30
  end
31
31
 
32
32
  def volume_class(type, config, state, oci, api)
33
- Oci::Models.const_get(volume_attachment_type(type)).new(config, state, oci, api)
33
+ Oci::Models.const_get(volume_attachment_type(type)).new(config: config, state: state, oci: oci, api: api, logger: instance.logger)
34
34
  end
35
35
 
36
36
  private
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ #
4
+ # Author:: Justin Steele (<justin.steele@oracle.com>)
5
+ #
6
+ # Copyright (C) 2024, Stephen Pearson
7
+ #
8
+ # Licensed under the Apache License, Version 2.0 (the "License");
9
+ # you may not use this file except in compliance with the License.
10
+ # You may obtain a copy of the License at
11
+ #
12
+ # http://www.apache.org/licenses/LICENSE-2.0
13
+ #
14
+ # Unless required by applicable law or agreed to in writing, software
15
+ # distributed under the License is distributed on an "AS IS" BASIS,
16
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ # See the License for the specific language governing permissions and
18
+ # limitations under the License.
19
+
20
+ module Kitchen
21
+ module Driver
22
+ class Oci
23
+ # mixin for working with volumes and attachments
24
+ module Volumes
25
+ def create_and_attach_volumes(config, state, oci, api)
26
+ return if config[:volumes].empty?
27
+
28
+ volume_state = process_volumes(config, state, oci, api)
29
+ state.merge!(volume_state)
30
+ end
31
+
32
+ def process_volumes(config, state, oci, api)
33
+ volume_state = { volumes: [], volume_attachments: [] }
34
+ config[:volumes].each do |volume|
35
+ vol = volume_class(volume[:type], config, state, oci, api)
36
+ volume_details, vol_state = create_volume(vol, volume)
37
+ attach_state = vol.attach_volume(volume_details, state[:server_id], volume)
38
+ volume_state[:volumes] << vol_state
39
+ volume_state[:volume_attachments] << attach_state
40
+ end
41
+ volume_state
42
+ end
43
+
44
+ def create_volume(vol, volume)
45
+ if volume.key?(:volume_id)
46
+ vol.create_clone_volume(volume)
47
+ else
48
+ vol.create_volume(volume)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -35,9 +35,10 @@ module Kitchen
35
35
  class Oci < Kitchen::Driver::Base # rubocop:disable Metrics/ClassLength
36
36
  require_relative "oci_version"
37
37
  require_relative "oci/models"
38
+ require_relative "oci/volumes"
38
39
 
39
40
  plugin_version Kitchen::Driver::OCI_VERSION
40
- kitchen_driver_api_version 1
41
+ kitchen_driver_api_version 2
41
42
 
42
43
  # required config items
43
44
  required_config :availability_domain
@@ -63,6 +64,7 @@ module Kitchen
63
64
  default_config :display_name, nil
64
65
  default_keypath = File.expand_path(File.join(%w{~ .ssh id_rsa.pub}))
65
66
  default_config :ssh_keypath, default_keypath
67
+ default_config :ssh_keygen, false
66
68
  default_config :post_create_script, nil
67
69
  default_config :proxy_url, nil
68
70
  default_config :user_data, nil
@@ -114,6 +116,7 @@ module Kitchen
114
116
  end
115
117
 
116
118
  include Kitchen::Driver::Oci::Models
119
+ include Kitchen::Driver::Oci::Volumes
117
120
 
118
121
  def create(state)
119
122
  return if state[:server_id]
@@ -151,33 +154,6 @@ module Kitchen
151
154
  instance.transport.connection(state).wait_until_ready
152
155
  end
153
156
 
154
- def create_and_attach_volumes(config, state, oci, api)
155
- return if config[:volumes].empty?
156
-
157
- volume_state = process_volumes(config, state, oci, api)
158
- state.merge!(volume_state)
159
- end
160
-
161
- def process_volumes(config, state, oci, api)
162
- volume_state = { volumes: [], volume_attachments: [] }
163
- config[:volumes].each do |volume|
164
- vol = volume_class(volume[:type], config, state, oci, api)
165
- volume_details, vol_state = create_volume(vol, volume)
166
- attach_state = vol.attach_volume(volume_details, state[:server_id], volume)
167
- volume_state[:volumes] << vol_state
168
- volume_state[:volume_attachments] << attach_state
169
- end
170
- volume_state
171
- end
172
-
173
- def create_volume(vol, volume)
174
- if volume.key?(:volume_id)
175
- vol.create_clone_volume(volume)
176
- else
177
- vol.create_volume(volume)
178
- end
179
- end
180
-
181
157
  def process_post_script(state)
182
158
  return if config[:post_create_script].nil?
183
159
 
@@ -197,7 +173,7 @@ module Kitchen
197
173
  def detatch_and_delete_volumes(state, oci, api)
198
174
  return unless state[:volumes]
199
175
 
200
- bls = Blockstorage.new(config, state, oci, api, :destroy)
176
+ bls = Blockstorage.new(config: config, state: state, oci: oci, api: api, action: :destroy, logger: instance.logger)
201
177
  state[:volume_attachments].each { |att| bls.detatch_volume(att) }
202
178
  state[:volumes].each { |vol| bls.delete_volume(vol) }
203
179
  end
@@ -205,6 +181,10 @@ module Kitchen
205
181
  def terminate(state, inst)
206
182
  instance.transport.connection(state).close
207
183
  inst.terminate
184
+ if state[:ssh_key]
185
+ FileUtils.rm_f(state[:ssh_key])
186
+ FileUtils.rm_f("#{state[:ssh_key]}.pub")
187
+ end
208
188
  end
209
189
  end
210
190
  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.25.0"
23
+ OCI_VERSION = "1.26.0"
24
24
  end
25
25
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kitchen-oci
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.25.0
4
+ version: 1.26.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Stephen Pearson
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2024-12-24 00:00:00.000000000 Z
12
+ date: 2025-01-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: oci
@@ -133,6 +133,7 @@ files:
133
133
  - lib/kitchen/driver/oci/models/dbaas.rb
134
134
  - lib/kitchen/driver/oci/models/iscsi.rb
135
135
  - lib/kitchen/driver/oci/models/paravirtual.rb
136
+ - lib/kitchen/driver/oci/volumes.rb
136
137
  - lib/kitchen/driver/oci_version.rb
137
138
  - tpl/setup_winrm.ps1.erb
138
139
  homepage: https://github.com/stephenpearson/kitchen-oci