kitchen-lxd_sling 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 8f3243840ce11f59febe69a8d1c1f1714381ac91
4
+ data.tar.gz: 532cd4412fe82ddfd4a9f959015010a16890bbf2
5
+ SHA512:
6
+ metadata.gz: 66474f971690fe2db140e791c6f4aebc2352a3fe7f626a49620261eeb2adf9e7731178e561a694ef742e1a97f81ccc66f27261731f9fad3264a0b2b444f95dfd
7
+ data.tar.gz: b7ebd2456aad97a87b1d0aa4f881f88fe51f41f6c898613d1c08fc0cba7a60d269a3282e001dac87991efeb03c0933dc031b6544213302bf8bc7a1e10bbab60d
@@ -0,0 +1,17 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /.vscode/
11
+ Berksfile.lock
12
+ _*
13
+
14
+ # rspec failure tracking
15
+ .rspec_status
16
+ .kitchen/
17
+ .kitchen.local.yml
@@ -0,0 +1,7 @@
1
+ platforms:
2
+ - name: local
3
+ driver: exec
4
+
5
+ suites:
6
+ - name: travis
7
+ run_list: recipe[test::default]
@@ -0,0 +1,22 @@
1
+ <% require 'tmpdir' %>
2
+ ---
3
+ driver: lxd
4
+
5
+ provisioner:
6
+ name: chef_zero
7
+
8
+ platforms:
9
+ - name: ubuntu-16.04
10
+
11
+ transport: lxd
12
+
13
+ suites:
14
+ - name: kitchen-lxd-native
15
+ provisioner:
16
+ downloads:
17
+ '/tmp/kitchen': <%= Dir.tmpdir %>/kitchen-download-test
18
+ - name: kitchen-lxd-cloud
19
+ driver:
20
+ image_server: https://cloud-images.ubuntu.com/releases
21
+ username: ubuntu
22
+
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,24 @@
1
+ sudo: required
2
+ language: ruby
3
+ rvm:
4
+ - 2.4.3
5
+ - ruby-head
6
+ matrix:
7
+ allow_failures:
8
+ - rvm: ruby-head
9
+ script:
10
+ - rake --tasks
11
+ - bundle exec kitchen diagnose
12
+ - KITCHEN_LOCAL_YAML=.kitchen.travis.yml rake kitchen:travis-local
13
+ - ssh-keygen -f ~/.ssh/id_rsa -t rsa -N ''
14
+ - sudo cat /etc/passwd
15
+ - sudo su -l $USER -c "cd $(pwd) && rvm use ${RUBY_VERSION/ruby-/} && rake kitchen:all"
16
+ deploy:
17
+ provider: rubygems
18
+ api_key:
19
+ secure: A599p8PjugFfsTdWLLHW1Rl2yaMLWfFpUAV1Oq4qFG2RqMQXgM4zWGO4+Upff6zJ07qxOqon0kjysaU46Pwollp4pS+5sogtFPkcboSi8qhjeCJ3eYo6O1GWLD+5kBZ1PIS9iRPqTGKFPB677KmjXEdmdYvBY4x01tOK23KzjsjtdXO3/6C8BD7pg5EC2qGxjztkbzGm8OZXbGvTvQ5lxtQe5H4ldHr6zs6ZUu/OzszGofXwWMRxeOu0UHkcrHrDUJ/HIJxjm7ogOQI7C016KksCPcYCG3GeS/Od/tVMZiQ0Z2LVV0dQjLTFzD9fGqIcGTur1M+pE4lv4NMFHZc6ICVJgVEegQ8S0SVbkpXijrw4ahahfRTU8U//hmnR4wnRAEd2N5IYA4ChQqwUcARBnmVb/uxQASEvF4tLBzjvUdgUMggWr94705ATIOqIu2CsQZYxGU5nsD3WxYBRM1ByVFq+yT93OsBmhAMwwurhVwP0yjL5Fi8ax94Guq8JD7BnbhON3nEwevLI5/O14bNhdHmb9O7sjQ5qdmqStmxIB96wLADuLUYFhPCh+zLIYzGulcHRId7QyqavU9seSIg+XL8dbM0Iljfi//lrq9FDEyYlh35nSf+p0UnNLfC10qXnBp8ojb/GhEXOyqIEDWmKO/Ose1OJ5Cr4qtN7Ye0+B7s=
20
+ gem: kitchen-lxd_sling
21
+ on:
22
+ tags: true
23
+ rvm: 2.4.3
24
+
@@ -0,0 +1,7 @@
1
+ source 'https://supermarket.chef.io'
2
+
3
+ cookbook 'lxd_sling', git: 'https://github.com/nexussw/lxd_sling.git'
4
+
5
+ group :test do
6
+ cookbook 'test', path: 'test/cookbooks/test'
7
+ end
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in kitchen-lxd_sling.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,203 @@
1
+
2
+ Apache License
3
+ Version 2.0, January 2004
4
+ http://www.apache.org/licenses/
5
+
6
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
+
8
+ 1. Definitions.
9
+
10
+ "License" shall mean the terms and conditions for use, reproduction,
11
+ and distribution as defined by Sections 1 through 9 of this document.
12
+
13
+ "Licensor" shall mean the copyright owner or entity authorized by
14
+ the copyright owner that is granting the License.
15
+
16
+ "Legal Entity" shall mean the union of the acting entity and all
17
+ other entities that control, are controlled by, or are under common
18
+ control with that entity. For the purposes of this definition,
19
+ "control" means (i) the power, direct or indirect, to cause the
20
+ direction or management of such entity, whether by contract or
21
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
+ outstanding shares, or (iii) beneficial ownership of such entity.
23
+
24
+ "You" (or "Your") shall mean an individual or Legal Entity
25
+ exercising permissions granted by this License.
26
+
27
+ "Source" form shall mean the preferred form for making modifications,
28
+ including but not limited to software source code, documentation
29
+ source, and configuration files.
30
+
31
+ "Object" form shall mean any form resulting from mechanical
32
+ transformation or translation of a Source form, including but
33
+ not limited to compiled object code, generated documentation,
34
+ and conversions to other media types.
35
+
36
+ "Work" shall mean the work of authorship, whether in Source or
37
+ Object form, made available under the License, as indicated by a
38
+ copyright notice that is included in or attached to the work
39
+ (an example is provided in the Appendix below).
40
+
41
+ "Derivative Works" shall mean any work, whether in Source or Object
42
+ form, that is based on (or derived from) the Work and for which the
43
+ editorial revisions, annotations, elaborations, or other modifications
44
+ represent, as a whole, an original work of authorship. For the purposes
45
+ of this License, Derivative Works shall not include works that remain
46
+ separable from, or merely link (or bind by name) to the interfaces of,
47
+ the Work and Derivative Works thereof.
48
+
49
+ "Contribution" shall mean any work of authorship, including
50
+ the original version of the Work and any modifications or additions
51
+ to that Work or Derivative Works thereof, that is intentionally
52
+ submitted to Licensor for inclusion in the Work by the copyright owner
53
+ or by an individual or Legal Entity authorized to submit on behalf of
54
+ the copyright owner. For the purposes of this definition, "submitted"
55
+ means any form of electronic, verbal, or written communication sent
56
+ to the Licensor or its representatives, including but not limited to
57
+ communication on electronic mailing lists, source code control systems,
58
+ and issue tracking systems that are managed by, or on behalf of, the
59
+ Licensor for the purpose of discussing and improving the Work, but
60
+ excluding communication that is conspicuously marked or otherwise
61
+ designated in writing by the copyright owner as "Not a Contribution."
62
+
63
+ "Contributor" shall mean Licensor and any individual or Legal Entity
64
+ on behalf of whom a Contribution has been received by Licensor and
65
+ subsequently incorporated within the Work.
66
+
67
+ 2. Grant of Copyright License. Subject to the terms and conditions of
68
+ this License, each Contributor hereby grants to You a perpetual,
69
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
+ copyright license to reproduce, prepare Derivative Works of,
71
+ publicly display, publicly perform, sublicense, and distribute the
72
+ Work and such Derivative Works in Source or Object form.
73
+
74
+ 3. Grant of Patent License. Subject to the terms and conditions of
75
+ this License, each Contributor hereby grants to You a perpetual,
76
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
+ (except as stated in this section) patent license to make, have made,
78
+ use, offer to sell, sell, import, and otherwise transfer the Work,
79
+ where such license applies only to those patent claims licensable
80
+ by such Contributor that are necessarily infringed by their
81
+ Contribution(s) alone or by combination of their Contribution(s)
82
+ with the Work to which such Contribution(s) was submitted. If You
83
+ institute patent litigation against any entity (including a
84
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
85
+ or a Contribution incorporated within the Work constitutes direct
86
+ or contributory patent infringement, then any patent licenses
87
+ granted to You under this License for that Work shall terminate
88
+ as of the date such litigation is filed.
89
+
90
+ 4. Redistribution. You may reproduce and distribute copies of the
91
+ Work or Derivative Works thereof in any medium, with or without
92
+ modifications, and in Source or Object form, provided that You
93
+ meet the following conditions:
94
+
95
+ (a) You must give any other recipients of the Work or
96
+ Derivative Works a copy of this License; and
97
+
98
+ (b) You must cause any modified files to carry prominent notices
99
+ stating that You changed the files; and
100
+
101
+ (c) You must retain, in the Source form of any Derivative Works
102
+ that You distribute, all copyright, patent, trademark, and
103
+ attribution notices from the Source form of the Work,
104
+ excluding those notices that do not pertain to any part of
105
+ the Derivative Works; and
106
+
107
+ (d) If the Work includes a "NOTICE" text file as part of its
108
+ distribution, then any Derivative Works that You distribute must
109
+ include a readable copy of the attribution notices contained
110
+ within such NOTICE file, excluding those notices that do not
111
+ pertain to any part of the Derivative Works, in at least one
112
+ of the following places: within a NOTICE text file distributed
113
+ as part of the Derivative Works; within the Source form or
114
+ documentation, if provided along with the Derivative Works; or,
115
+ within a display generated by the Derivative Works, if and
116
+ wherever such third-party notices normally appear. The contents
117
+ of the NOTICE file are for informational purposes only and
118
+ do not modify the License. You may add Your own attribution
119
+ notices within Derivative Works that You distribute, alongside
120
+ or as an addendum to the NOTICE text from the Work, provided
121
+ that such additional attribution notices cannot be construed
122
+ as modifying the License.
123
+
124
+ You may add Your own copyright statement to Your modifications and
125
+ may provide additional or different license terms and conditions
126
+ for use, reproduction, or distribution of Your modifications, or
127
+ for any such Derivative Works as a whole, provided Your use,
128
+ reproduction, and distribution of the Work otherwise complies with
129
+ the conditions stated in this License.
130
+
131
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
132
+ any Contribution intentionally submitted for inclusion in the Work
133
+ by You to the Licensor shall be under the terms and conditions of
134
+ this License, without any additional terms or conditions.
135
+ Notwithstanding the above, nothing herein shall supersede or modify
136
+ the terms of any separate license agreement you may have executed
137
+ with Licensor regarding such Contributions.
138
+
139
+ 6. Trademarks. This License does not grant permission to use the trade
140
+ names, trademarks, service marks, or product names of the Licensor,
141
+ except as required for reasonable and customary use in describing the
142
+ origin of the Work and reproducing the content of the NOTICE file.
143
+
144
+ 7. Disclaimer of Warranty. Unless required by applicable law or
145
+ agreed to in writing, Licensor provides the Work (and each
146
+ Contributor provides its Contributions) on an "AS IS" BASIS,
147
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
+ implied, including, without limitation, any warranties or conditions
149
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
+ PARTICULAR PURPOSE. You are solely responsible for determining the
151
+ appropriateness of using or redistributing the Work and assume any
152
+ risks associated with Your exercise of permissions under this License.
153
+
154
+ 8. Limitation of Liability. In no event and under no legal theory,
155
+ whether in tort (including negligence), contract, or otherwise,
156
+ unless required by applicable law (such as deliberate and grossly
157
+ negligent acts) or agreed to in writing, shall any Contributor be
158
+ liable to You for damages, including any direct, indirect, special,
159
+ incidental, or consequential damages of any character arising as a
160
+ result of this License or out of the use or inability to use the
161
+ Work (including but not limited to damages for loss of goodwill,
162
+ work stoppage, computer failure or malfunction, or any and all
163
+ other commercial damages or losses), even if such Contributor
164
+ has been advised of the possibility of such damages.
165
+
166
+ 9. Accepting Warranty or Additional Liability. While redistributing
167
+ the Work or Derivative Works thereof, You may choose to offer,
168
+ and charge a fee for, acceptance of support, warranty, indemnity,
169
+ or other liability obligations and/or rights consistent with this
170
+ License. However, in accepting such obligations, You may act only
171
+ on Your own behalf and on Your sole responsibility, not on behalf
172
+ of any other Contributor, and only if You agree to indemnify,
173
+ defend, and hold each Contributor harmless for any liability
174
+ incurred by, or claims asserted against, such Contributor by reason
175
+ of your accepting any such warranty or additional liability.
176
+
177
+ END OF TERMS AND CONDITIONS
178
+
179
+ APPENDIX: How to apply the Apache License to your work.
180
+
181
+ To apply the Apache License to your work, attach the following
182
+ boilerplate notice, with the fields enclosed by brackets "[]"
183
+ replaced with your own identifying information. (Don't include
184
+ the brackets!) The text should be enclosed in the appropriate
185
+ comment syntax for the file format. We also recommend that a
186
+ file or class name and description of purpose be included on the
187
+ same "printed page" as the copyright notice for easier
188
+ identification within third-party archives.
189
+
190
+ Copyright [yyyy] [name of copyright owner]
191
+
192
+ Licensed under the Apache License, Version 2.0 (the "License");
193
+ you may not use this file except in compliance with the License.
194
+ You may obtain a copy of the License at
195
+
196
+ http://www.apache.org/licenses/LICENSE-2.0
197
+
198
+ Unless required by applicable law or agreed to in writing, software
199
+ distributed under the License is distributed on an "AS IS" BASIS,
200
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
+ See the License for the specific language governing permissions and
202
+ limitations under the License.
203
+
@@ -0,0 +1,39 @@
1
+ # Kitchen::LxdNexus
2
+
3
+ Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/kitchen/lxd_sling`. To experiment with that code, run `bin/console` for an interactive prompt.
4
+
5
+ TODO: Delete this and the text above, and describe your gem
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'kitchen-lxd_sling'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install kitchen-lxd_sling
22
+
23
+ ## Usage
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ## Development
28
+
29
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
+
31
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
32
+
33
+ ## Contributing
34
+
35
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/kitchen-lxd_sling.
36
+
37
+ ## License
38
+
39
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
@@ -0,0 +1,13 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
7
+
8
+ begin
9
+ require 'kitchen/rake_tasks'
10
+ Kitchen::RakeTasks.new
11
+ rescue LoadError
12
+ puts '>>>>> Kitchen gem not loaded, omitting tasks' unless ENV['CI']
13
+ end
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'kitchen/lxd_sling'
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require 'pry'
11
+ # Pry.start
12
+
13
+ require 'irb'
14
+ IRB.start(__FILE__)
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'yaml'
4
+
5
+ def symbolize_keys(hash)
6
+ {}.tap do |retval|
7
+ hash.each do |k, v|
8
+ retval[k.to_sym] = v.is_a?(Hash) ? symbolize_keys(v) : v
9
+ end
10
+ end
11
+ end
12
+
13
+ state = symbolize_keys(YAML.load(File.read(ARGV[0])))
14
+
15
+ require 'kitchen'
16
+ require 'kitchen/driver/lxd/host_locator'
17
+ require 'tty/reader'
18
+ require 'tty/screen'
19
+
20
+ class NxHost
21
+ include Kitchen::Driver::Lxd::HostLocator
22
+ def initialize(config = {})
23
+ @config = config
24
+ end
25
+ attr_reader :config
26
+ end
27
+
28
+ driver = NxHost.new state[:config]
29
+ transport = driver.nx_transport state
30
+ tty = TTY::Reader.new
31
+ win_keymap = {}
32
+ if Gem.win_platform?
33
+ win_keymap = TTY::Reader::Keys.keys.invert
34
+ win_keymap[:clear] = win_keymap[:delete]
35
+ end
36
+
37
+ # ruby bin/lxc-shell .kitchen/kitchen-lxd-cloud-ubuntu-1604.yml
38
+
39
+ # TODO: (someday - if found useful) the TTY subsystem doesn't capture stdin, so you can't pipe commands to this script
40
+ # we'd have to interleave the code for both input types (ignoring tty if stdin is not a tty)
41
+ # TTY gems must stay due to them handling windows input for us
42
+ term = ENV['TERM'] || 'dumb'
43
+ user = transport.username
44
+ if user
45
+ user = " - #{user}"
46
+ transport.reset_user
47
+ end
48
+ transport.execute "env TERM=#{term} su#{user}", capture: :interactive do |active|
49
+ active.capture_output do |stdout|
50
+ print stdout
51
+ end
52
+ tty.on :keypress do |event|
53
+ active.stdin.write win_keymap[event.key.name] || event.value
54
+ end
55
+ if active.thread.respond_to? :window_resize
56
+ lines, columns = TTY::Screen.size
57
+ active.thread.window_resize columns, lines
58
+ end
59
+ # tty-reader doesn't have its own thread - it's pumped by a 'read_xxxx' call
60
+ # and its inner wait loop blocks VERY HARD unless you nonblock (even a main Thread.kill won't unblock it - windows issue?)
61
+ # yes windows issue... test code can kill read_keypress when running on linux
62
+ begin
63
+ loop do
64
+ break unless active.thread.alive?
65
+ sleep 0.01 unless tty.read_keypress nonblock: true
66
+ end
67
+ rescue Interrupt
68
+ # active.thread.signal 2
69
+ active.stdin.write "\x3"
70
+ retry
71
+ end
72
+ end.error!
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'kitchen/driver/lxd_version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'kitchen-lxd_sling'
8
+ spec.version = Kitchen::Driver::LXD_VERSION
9
+ spec.authors = ['Sean Zachariasen']
10
+ spec.email = ['thewyzard@hotmail.com']
11
+
12
+ spec.summary = 'Test Kitchen Driver for LXD'
13
+ spec.homepage = 'https://github.com/NexusSW/kitchen-lxd_sling'
14
+ spec.license = 'Apache-2.0'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
17
+ f.match(%r{^(test|spec|features)/})
18
+ end
19
+ spec.bindir = 'exe'
20
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
21
+ spec.require_paths = ['lib']
22
+
23
+ spec.add_dependency 'lxd-common', '~> 0.9'
24
+ spec.add_dependency 'test-kitchen', '~> 1.0'
25
+ spec.add_dependency 'tty-reader', '~> 0.2'
26
+ spec.add_dependency 'tty-screen', '~> 0.6'
27
+
28
+ spec.add_development_dependency 'bundler'
29
+ spec.add_development_dependency 'rake'
30
+ spec.add_development_dependency 'rspec'
31
+ spec.add_development_dependency 'berkshelf'
32
+ end
@@ -0,0 +1,440 @@
1
+ require 'kitchen'
2
+ require 'kitchen/driver/base'
3
+ require 'kitchen/transport/lxd'
4
+ require 'kitchen/driver/lxd_version'
5
+ require 'kitchen/driver/lxd/host_locator'
6
+
7
+ require 'nexussw/lxd/driver/cli'
8
+ require 'nexussw/lxd/driver/rest'
9
+ require 'nexussw/lxd/transport/cli'
10
+ require 'nexussw/lxd/transport/rest'
11
+ require 'nexussw/lxd/transport/local'
12
+
13
+ require 'securerandom'
14
+
15
+ require 'pp'
16
+
17
+ module Kitchen
18
+ module Driver
19
+ class Lxd < Kitchen::Driver::Base
20
+ include HostLocator
21
+
22
+ def initialize(config = {})
23
+ # pp 'Config:', config
24
+ super
25
+ end
26
+
27
+ kitchen_driver_api_version 2
28
+ plugin_version Kitchen::Driver::LXD_VERSION
29
+
30
+ default_config :server, nil
31
+ default_config :port, 8443
32
+ default_config :image_server, 'https://images.linuxcontainers.org'
33
+ default_config :rest_options, {}
34
+
35
+ def create(state)
36
+ state[:config] = config.slice :server, :port, :rest_options, :image_server
37
+ info 'Utilizing REST interface at ' + host_address if respond_to?(:info) && can_rest?
38
+
39
+ state[:username] = config[:username] if config.key? :username
40
+ state[:container_name] = new_container_name unless state[:container_name]
41
+
42
+ # TODO: convergent behavior on container_options change? (:profiles :config)
43
+ state[:container_options] = container_options
44
+
45
+ info "Container name: #{state[:container_name]}"
46
+ driver.create_container(state[:container_name], state[:container_options])
47
+
48
+ # Allow SSH transport on known images with sshd enabled
49
+ # This will only work if the container is routable. LXD does not do port forwarding (yet)
50
+ # Which also means that you might need to do 'ssh_login: false' in the config if you're using a cloud-image and aren't routable
51
+ # think ahead for default behaviour once LXD can port forward
52
+ # FUTURE: If I get time I'll look into faking a port forward with something under /dev/ until then
53
+ if use_ssh?
54
+ # Normalize [:ssh_login]
55
+ config[:ssh_login] = { username: config[:ssh_login] } if config[:ssh_login].is_a? String
56
+ config[:ssh_login] = {} if config[:ssh_login] && !config.to_hash[:ssh_login].is_a?(Hash)
57
+
58
+ state[:username] = config[:ssh_login][:username] if config[:ssh_login]
59
+ state[:username] ||= 'root'
60
+ # TODO: make public key configurable
61
+ info 'Waiting for an IP address...'
62
+ state[:ip_address] = state[:hostname] = container_ip(state)
63
+ setup_ssh(state[:username], "#{ENV['HOME']}/.ssh/id_rsa.pub", state)
64
+ info "SSH access enabled on #{state[:ip_address]}"
65
+ else
66
+ # TODO: this section is only for the base images on linuxcontainers.org... (and I still need to account for yum)
67
+ # they need patched because they don't have wget, or anything else with which to download the chef client
68
+ # Custom images should account for this, so I won't run this patch for them (in the name of testing speed)
69
+ info 'Waiting for network access...'
70
+ state[:ip_address] = container_ip(state) # This is only here to wait until the net is up so we can download packages
71
+ unless cloud_image?
72
+ info 'Installing additional dependencies...'
73
+ transport = nx_transport(state)
74
+ transport.reset_user
75
+ transport.execute('apt-get install openssl wget ca-certificates -y').error!
76
+ end
77
+ end
78
+ end
79
+
80
+ def finalize_config!(instance)
81
+ super.tap do
82
+ instance.transport = Kitchen::Transport::Lxd.new config unless lxd_transport_selected? || use_ssh?
83
+ end
84
+ end
85
+
86
+ def destroy(state)
87
+ info "Destroying container #{state[:container_name]}"
88
+ driver.delete_container state[:container_name]
89
+ end
90
+
91
+ private
92
+
93
+ # ssh is kitchen's default unless lxd is selected by the user
94
+ # otherwise, only use ssh when the user supplies info
95
+ # and automatically, only on capable cloud images (requires kitchen 1.19 to perform the automatic override)
96
+ def use_ssh?
97
+ return false if lxd_transport_selected?
98
+ return true if config[:ssh_login]
99
+ return false if config[:ssh_login] == false # allow forced disable for cloud-images... or (TODO: should I not default enable for them?)
100
+ cloud_image?
101
+ end
102
+
103
+ # if selected by user during startup (finalize_config!)
104
+ # later, if selected by the user, or if deemed necessary by the driver
105
+ def lxd_transport_selected?
106
+ instance.transport.is_a? Kitchen::Transport::Lxd
107
+ end
108
+
109
+ def cloud_image?
110
+ server = image_server
111
+ return false unless server && server[:server]
112
+ server[:server].downcase.start_with? 'https://cloud-images.ubuntu.com'
113
+ end
114
+
115
+ def new_container_name
116
+ instance.name + '-' + SecureRandom.hex(8)
117
+ end
118
+
119
+ # Normalize into a hash with the correct protocol
120
+ # We'll take a given hash verbatim
121
+ # But we'll allow a simple string to default to the simplestreams protocol if no port is specified
122
+ # (otherwise 'lxd' is default, but counterintuitive given that if we specify neither a port nor a protocol, 8443 will be appended for lxd's default)
123
+ # Side effect: differing behavior (protocol) depending on whether a port is specified on a simple string
124
+ # which is (ok?) If you want to specify an odd port, you should probably also specify which protocol
125
+ def image_server
126
+ server = config[:image_server]
127
+ if server.is_a? String
128
+ server = { server: server }
129
+ server[:protocol] = 'simplestreams' if server[:server].split(':', 3)[2].nil?
130
+ end
131
+ server
132
+ end
133
+
134
+ # Special cases: using example `ubuntu-16.04`
135
+ # 0: if alias, fingerprint, or properties are specified, use instead of the below: (handled by caller)
136
+ # 1: if server.start_with? 'https://cloud-images.ubuntu.com'
137
+ # - trim the leading `ubuntu-` (optionally specified)
138
+ # 2: if server.start_with? 'https://images.linuxcontainers.org'
139
+ # - replace `-` with `/` (in all cases?)
140
+ # - replace version with codename, if dist == 'ubuntu'
141
+ def image_name(server)
142
+ name = instance.platform.name
143
+ return name unless server
144
+
145
+ # 1:
146
+ if server.downcase.start_with? 'https://cloud-images.ubuntu.com'
147
+ info "Using cloud-image '#{name}'"
148
+ return name.downcase.sub(/^ubuntu-/, '')
149
+ end
150
+ # 2:
151
+ if server.downcase.start_with? 'https://images.linuxcontainers.org'
152
+ name = name.downcase.split('-')
153
+ # 'core' parses out in this method as the 'version' so just use 'ubuntu-core' in the kitchen.yml
154
+ if UBUNTU_RELEASES.key?(name[1]) && name[0] == 'ubuntu'
155
+ name[1] = UBUNTU_RELEASES[name[1]]
156
+ name[0] = 'ubuntu-core' if name[1] == '16' # Logic patch for the edge case. We'll do something different if this gets complicated
157
+ end
158
+ name = name.join('/')
159
+ info "Using standard image #{name}"
160
+ end
161
+ name
162
+ end
163
+
164
+ # only bothering with the releases on linuxcontainers.org
165
+ # leaving this mutable so that end-users can append new releases to it
166
+ # Usage Note: If a future release is not in the below table, just specify the full image name in the kitchen yml instead of using ubuntu-<version>
167
+ UBUNTU_RELEASES = { # rubocop:disable Style/MutableConstant
168
+ '12.04' => 'precise',
169
+ '14.04' => 'trusty',
170
+ '16.04' => 'xenial',
171
+ '17.04' => 'zesty',
172
+ '17.10' => 'artful',
173
+ '18.04' => 'bionic',
174
+ 'core' => '16',
175
+ }
176
+
177
+ def container_options
178
+ options = image_server
179
+ # 0:
180
+ found = false
181
+ %w(:alias :fingerprint :properties).each do |k|
182
+ if config.key? k
183
+ options[k] = config[k]
184
+ found = true
185
+ end
186
+ end
187
+ options[:alias] = image_name(options[:server]) unless found
188
+ options.merge config.slice(:profiles, :config)
189
+ end
190
+
191
+ def setup_ssh(username, pubkey, state)
192
+ # DEFERRED: should I create the ssh user if it doesn't exist? (I've seen that in other drivers)
193
+ # not for now... that is an edge case within an edge case, and the default case just shells in as 'root' without concept of 'users'
194
+ # submit a feature request if you need me to create a user
195
+ # and that is if it is unfeasible for you to create a custom image with that user included
196
+ return if state[:ssh_enabled]
197
+ raise ActionFailed, "Public Key File does not exist (#{pubkey})" unless File.exist? pubkey
198
+
199
+ transport = nx_transport(state)
200
+ transport.reset_user
201
+ remote_file = "/tmp/#{state[:container_name]}-publickey"
202
+ transport.upload_file pubkey, remote_file
203
+ begin
204
+ sshdir = transport.execute("bash -c \"grep '^#{username}:' /etc/passwd | cut -d':' -f 6\"").error!.stdout.strip
205
+ rescue => e
206
+ fatal "Transport Error querying SSH User: #{sshdir}\n#{e.message}"
207
+ raise
208
+ ensure
209
+ raise ActionFailed, "User (#{username}), or their home directory, were not found within container (#{state[:container_name]})" unless sshdir && !sshdir.empty?
210
+ sshdir += '/.ssh'
211
+ end
212
+ ak_file = sshdir + '/authorized_keys'
213
+
214
+ info "Inserting public key for container user '#{username}'"
215
+ transport.execute("bash -c 'mkdir -p #{sshdir} 2> /dev/null; cat #{remote_file} >> #{ak_file} \
216
+ && rm -rf #{remote_file} && chown -R #{username}:#{username} #{sshdir}'").error! # , capture: false
217
+ state[:ssh_enabled] = true
218
+ end
219
+
220
+ def container_ip(state)
221
+ # TODO: make timeout configurable
222
+ driver.wait_for state[:container_name], :ip # , 60 # default timeout=60
223
+ end
224
+ end
225
+ end
226
+ end
227
+
228
+ =begin # rubocop:disable Style/BlockComments
229
+ "Instance:"
230
+ #<Kitchen::Instance:0x48b5350
231
+ @driver=
232
+ #<Kitchen::Driver::LXD:0x490e9f0
233
+ @config=
234
+ {:name=>"LXD",
235
+ :hostname=>"wyzsrv",
236
+ :rest_options=>{:verify_ssl=>false},
237
+ :"image-server"=>
238
+ {:addr=>"https://cloud-images.ubuntu.com/releases",
239
+ :protocol=>"simplestreams"},
240
+ :kitchen_root=>"C:/Users/Sean/Documents/projects/kitchen-lxd_sling",
241
+ :test_base_path=>
242
+ "C:/Users/Sean/Documents/projects/kitchen-lxd_sling/test/integration",
243
+ :log_level=>:info,
244
+ :port=>8443},
245
+ @driver=
246
+ #<NexusSW::LXD::Driver::Rest:0x490c200
247
+ @driver_options={:verify_ssl=>false},
248
+ @hk=
249
+ #<Hyperkit::Client:0x490c170
250
+ @api_endpoint="https://wyzsrv:8443",
251
+ @auto_sync=true,
252
+ @client_cert="C:/Users/Sean/.config/lxc/client.crt",
253
+ @client_key="C:/Users/Sean/.config/lxc/client.key",
254
+ @default_media_type="application/json",
255
+ @middleware=
256
+ #<Faraday::RackBuilder:0x49fadf0
257
+ @handlers=
258
+ [Hyperkit::Middleware::FollowRedirects,
259
+ Hyperkit::Response::RaiseError,
260
+ Faraday::Adapter::NetHttp]>,
261
+ @proxy=nil,
262
+ @user_agent="Hyperkit Ruby Gem 1.1.0",
263
+ @verify_ssl=false>,
264
+ @rest_endpoint="https://wyzsrv:8443">,
265
+ @instance=#<Kitchen::Instance:0x48b5350 ...>>,
266
+ @logger=
267
+ #<Kitchen::Logger:0x4907d48
268
+ @log_overwrite=true,
269
+ @logdev=
270
+ #<Kitchen::Logger::LogdevLogger:0x4907a90
271
+ @default_formatter=#<Logger::Formatter:0x4907a60 @datetime_format=nil>,
272
+ @formatter=nil,
273
+ @level=1,
274
+ @logdev=
275
+ #<Logger::LogDevice:0x4907a30
276
+ @dev=
277
+ #<File:C:/Users/Sean/Documents/projects/kitchen-lxd_sling/.kitchen/logs/default-ubuntu-1604.log>,
278
+ @filename=nil,
279
+ @mon_count=0,
280
+ @mon_mutex=#<Thread::Mutex:0x4907a00>,
281
+ @mon_owner=nil,
282
+ @shift_age=nil,
283
+ @shift_period_suffix=nil,
284
+ @shift_size=nil>,
285
+ @progname="default-ubuntu-1604">,
286
+ @loggers=
287
+ [#<Kitchen::Logger::LogdevLogger:0x4907a90
288
+ @default_formatter=#<Logger::Formatter:0x4907a60 @datetime_format=nil>,
289
+ @formatter=nil,
290
+ @level=1,
291
+ @logdev=
292
+ #<Logger::LogDevice:0x4907a30
293
+ @dev=
294
+ #<File:C:/Users/Sean/Documents/projects/kitchen-lxd_sling/.kitchen/logs/default-ubuntu-1604.log>,
295
+ @filename=nil,
296
+ @mon_count=0,
297
+ @mon_mutex=#<Thread::Mutex:0x4907a00>,
298
+ @mon_owner=nil,
299
+ @shift_age=nil,
300
+ @shift_period_suffix=nil,
301
+ @shift_size=nil>,
302
+ @progname="default-ubuntu-1604">,
303
+ #<Kitchen::Logger::StdoutLogger:0x49079d0
304
+ @default_formatter=#<Logger::Formatter:0x49079a0 @datetime_format=nil>,
305
+ @formatter=
306
+ #<Proc:0x49078e0@C:/opscode/chefdk/embedded/lib/ruby/gems/2.4.0/gems/test-kitchen-1.17.0/lib/kitchen/logger.rb:296>,
307
+ @level=1,
308
+ @logdev=
309
+ #<Logger::LogDevice:0x4907970
310
+ @dev=#<IO:<STDOUT>>,
311
+ @filename=nil,
312
+ @mon_count=0,
313
+ @mon_mutex=#<Thread::Mutex:0x4907940>,
314
+ @mon_owner=nil,
315
+ @shift_age=nil,
316
+ @shift_period_suffix=nil,
317
+ @shift_size=nil>,
318
+ @progname="default-ubuntu-1604">]>,
319
+ @name="default-ubuntu-1604",
320
+ @platform=
321
+ #<Kitchen::Platform:0x3c840d8
322
+ @name="ubuntu-16.04",
323
+ @os_type="unix",
324
+ @shell_type="bourne">,
325
+ @provisioner=
326
+ #<Kitchen::Provisioner::ChefSolo:0x4964b20
327
+ @config=
328
+ {:name=>"chef_solo",
329
+ :kitchen_root=>"C:/Users/Sean/Documents/projects/kitchen-lxd_sling",
330
+ :test_base_path=>
331
+ "C:/Users/Sean/Documents/projects/kitchen-lxd_sling/test/integration",
332
+ :http_proxy=>nil,
333
+ :https_proxy=>nil,
334
+ :ftp_proxy=>nil,
335
+ :retry_on_exit_code=>[],
336
+ :max_retries=>1,
337
+ :wait_for_retry=>30,
338
+ :root_path=>
339
+ #<Proc:0x395f1d8@C:/opscode/chefdk/embedded/lib/ruby/gems/2.4.0/gems/test-kitchen-1.17.0/lib/kitchen/provisioner/base.rb:36>,
340
+ :sudo=>
341
+ #<Proc:0x395f1c0@C:/opscode/chefdk/embedded/lib/ruby/gems/2.4.0/gems/test-kitchen-1.17.0/lib/kitchen/provisioner/base.rb:40>,
342
+ :sudo_command=>
343
+ #<Proc:0x395f1a8@C:/opscode/chefdk/embedded/lib/ruby/gems/2.4.0/gems/test-kitchen-1.17.0/lib/kitchen/provisioner/base.rb:44>,
344
+ :command_prefix=>nil,
345
+ :require_chef_omnibus=>true,
346
+ :chef_omnibus_url=>"https://omnitruck.chef.io/install.sh",
347
+ :chef_omnibus_install_options=>nil,
348
+ :run_list=>[],
349
+ :attributes=>{},
350
+ :config_path=>nil,
351
+ :log_file=>nil,
352
+ :log_level=>"auto",
353
+ :profile_ruby=>false,
354
+ :policyfile=>nil,
355
+ :policyfile_path=>nil,
356
+ :always_update_cookbooks=>false,
357
+ :cookbook_files_glob=>
358
+ "README.*,metadata.{json,rb},attributes/**/*,definitions/**/*,files/**/*,libraries/**/*,providers/**/*,recipes/**/*,resources/**/*,templates/**/*",
359
+ :deprecations_as_errors=>false,
360
+ :multiple_converge=>1,
361
+ :enforce_idempotency=>false,
362
+ :data_path=>
363
+ #<Proc:0x4965780@C:/opscode/chefdk/embedded/lib/ruby/gems/2.4.0/gems/test-kitchen-1.17.0/lib/kitchen/provisioner/chef_base.rb:74>,
364
+ :data_bags_path=>
365
+ #<Proc:0x49656f0@C:/opscode/chefdk/embedded/lib/ruby/gems/2.4.0/gems/test-kitchen-1.17.0/lib/kitchen/provisioner/chef_base.rb:79>,
366
+ :environments_path=>
367
+ #<Proc:0x49656d8@C:/opscode/chefdk/embedded/lib/ruby/gems/2.4.0/gems/test-kitchen-1.17.0/lib/kitchen/provisioner/chef_base.rb:84>,
368
+ :nodes_path=>
369
+ #<Proc:0x49656c0@C:/opscode/chefdk/embedded/lib/ruby/gems/2.4.0/gems/test-kitchen-1.17.0/lib/kitchen/provisioner/chef_base.rb:89>,
370
+ :roles_path=>
371
+ #<Proc:0x49656a8@C:/opscode/chefdk/embedded/lib/ruby/gems/2.4.0/gems/test-kitchen-1.17.0/lib/kitchen/provisioner/chef_base.rb:94>,
372
+ :clients_path=>
373
+ #<Proc:0x4965690@C:/opscode/chefdk/embedded/lib/ruby/gems/2.4.0/gems/test-kitchen-1.17.0/lib/kitchen/provisioner/chef_base.rb:99>,
374
+ :encrypted_data_bag_secret_key_path=>
375
+ #<Proc:0x4965678@C:/opscode/chefdk/embedded/lib/ruby/gems/2.4.0/gems/test-kitchen-1.17.0/lib/kitchen/provisioner/chef_base.rb:104>,
376
+ :solo_rb=>{},
377
+ :chef_solo_path=>
378
+ #<Proc:0x4964fd0@C:/opscode/chefdk/embedded/lib/ruby/gems/2.4.0/gems/test-kitchen-1.17.0/lib/kitchen/provisioner/chef_solo.rb:33>},
379
+ @instance=#<Kitchen::Instance:0x48b5350 ...>>,
380
+ @state_file=
381
+ #<Kitchen::StateFile:0x48b5440
382
+ @file_name=
383
+ "C:/Users/Sean/Documents/projects/kitchen-lxd_sling/.kitchen/default-ubuntu-1604.yml">,
384
+ @suite=
385
+ #<Kitchen::Suite:0x3c84198 @excludes=[], @includes=[], @name="default">,
386
+ @transport=
387
+ #<Kitchen::Transport::Ssh:0x48fc090
388
+ @config=
389
+ {:name=>"ssh",
390
+ :kitchen_root=>"C:/Users/Sean/Documents/projects/kitchen-lxd_sling",
391
+ :test_base_path=>
392
+ "C:/Users/Sean/Documents/projects/kitchen-lxd_sling/test/integration",
393
+ :log_level=>:info,
394
+ :port=>22,
395
+ :username=>"root",
396
+ :keepalive=>true,
397
+ :keepalive_interval=>60,
398
+ :max_ssh_sessions=>9,
399
+ :connection_timeout=>15,
400
+ :connection_retries=>5,
401
+ :connection_retry_sleep=>1,
402
+ :max_wait_until_ready=>600,
403
+ :ssh_gateway=>nil,
404
+ :ssh_gateway_username=>nil,
405
+ :ssh_key=>nil,
406
+ :compression=>false,
407
+ :compression_level=>
408
+ #<Proc:0x48fc8e8@C:/opscode/chefdk/embedded/lib/ruby/gems/2.4.0/gems/test-kitchen-1.17.0/lib/kitchen/transport/ssh.rb:64>},
409
+ @connection=nil,
410
+ @instance=#<Kitchen::Instance:0x48b5350 ...>>,
411
+ @verifier=
412
+ #<Kitchen::Verifier::Busser:0x48b5a40
413
+ @config=
414
+ {:name=>"busser",
415
+ :kitchen_root=>"C:/Users/Sean/Documents/projects/kitchen-lxd_sling",
416
+ :test_base_path=>
417
+ "C:/Users/Sean/Documents/projects/kitchen-lxd_sling/test/integration",
418
+ :log_level=>:info,
419
+ :http_proxy=>nil,
420
+ :https_proxy=>nil,
421
+ :ftp_proxy=>nil,
422
+ :root_path=>
423
+ #<Proc:0x3cd7be0@C:/opscode/chefdk/embedded/lib/ruby/gems/2.4.0/gems/test-kitchen-1.17.0/lib/kitchen/verifier/base.rb:36>,
424
+ :sudo=>
425
+ #<Proc:0x3cd7b80@C:/opscode/chefdk/embedded/lib/ruby/gems/2.4.0/gems/test-kitchen-1.17.0/lib/kitchen/verifier/base.rb:40>,
426
+ :chef_omnibus_root=>"/opt/chef",
427
+ :sudo_command=>
428
+ #<Proc:0x3cd7b50@C:/opscode/chefdk/embedded/lib/ruby/gems/2.4.0/gems/test-kitchen-1.17.0/lib/kitchen/verifier/base.rb:46>,
429
+ :command_prefix=>nil,
430
+ :suite_name=>
431
+ #<Proc:0x3cd7af0@C:/opscode/chefdk/embedded/lib/ruby/gems/2.4.0/gems/test-kitchen-1.17.0/lib/kitchen/verifier/base.rb:52>,
432
+ :busser_bin=>
433
+ #<Proc:0x48b6190@C:/opscode/chefdk/embedded/lib/ruby/gems/2.4.0/gems/test-kitchen-1.17.0/lib/kitchen/verifier/busser.rb:36>,
434
+ :ruby_bindir=>
435
+ #<Proc:0x48b6118@C:/opscode/chefdk/embedded/lib/ruby/gems/2.4.0/gems/test-kitchen-1.17.0/lib/kitchen/verifier/busser.rb:42>,
436
+ :version=>"busser"},
437
+ @instance=#<Kitchen::Instance:0x48b5350 ...>>>
438
+ "State (create):"
439
+ {}
440
+ =end
@@ -0,0 +1,31 @@
1
+ require 'kitchen/driver/base'
2
+ require 'nexussw/lxd/transport/local'
3
+ require 'nexussw/lxd/driver/cli'
4
+ require 'nexussw/lxd/driver/rest'
5
+
6
+ class Kitchen::Driver::Lxd < Kitchen::Driver::Base
7
+ module HostLocator
8
+ def driver
9
+ @driver ||= nx_driver
10
+ end
11
+
12
+ def nx_driver
13
+ return ::NexusSW::LXD::Driver::CLI.new(::NexusSW::LXD::Transport::Local.new) unless can_rest?
14
+ ::NexusSW::LXD::Driver::Rest.new(host_address, config[:rest_options])
15
+ end
16
+
17
+ def nx_transport(state)
18
+ driver.transport_for(state[:container_name]).tap do |transport|
19
+ transport.user state[:username] if state.key? :username
20
+ end
21
+ end
22
+
23
+ def can_rest?
24
+ !config[:server].nil?
25
+ end
26
+
27
+ def host_address
28
+ "https://#{config[:server]}:#{config[:port]}"
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,7 @@
1
+
2
+
3
+ module Kitchen
4
+ module Driver
5
+ LXD_VERSION = '0.4.0'.freeze
6
+ end
7
+ end
@@ -0,0 +1,81 @@
1
+ require 'kitchen/transport/base'
2
+ require 'kitchen/driver/lxd_version'
3
+ require 'shellwords'
4
+ require 'fileutils'
5
+
6
+ module Kitchen
7
+ module Transport
8
+ class Lxd < Kitchen::Transport::Base
9
+ kitchen_transport_api_version 2
10
+
11
+ plugin_version Kitchen::Driver::LXD_VERSION
12
+
13
+ def initialize(config = {})
14
+ super
15
+ @cache = {}
16
+ end
17
+
18
+ def connection(state)
19
+ begin
20
+ @cache[state[:container_name]] ||= Connection.new nx_transport(state), config.to_hash.merge(state), state_filename
21
+ end.tap { |conn| yield conn if block_given? }
22
+ end
23
+
24
+ def nx_transport(state)
25
+ instance.driver.nx_transport state
26
+ end
27
+
28
+ def state_filename
29
+ instance.instance_variable_get('@state_file').instance_variable_get('@file_name')
30
+ end
31
+
32
+ class Connection < Transport::Base::Connection
33
+ def initialize(transport, options, state_filename)
34
+ super options
35
+ @nx_transport = transport
36
+ @state_filename = state_filename
37
+ end
38
+
39
+ attr_reader :nx_transport, :state_filename
40
+
41
+ def execute(command)
42
+ return unless command && !command.empty?
43
+
44
+ # There are some bash-isms coming from chef_zero (in particular, multiple_converge)
45
+ # so let's wrap it
46
+ command = command.shelljoin if command.is_a? Array
47
+ command = ['bash', '-c', command]
48
+
49
+ res = nx_transport.execute(command, capture: true) do |stdout_chunk, stderr_chunk|
50
+ logger << stdout_chunk if stdout_chunk
51
+ logger << stderr_chunk if stderr_chunk
52
+ end
53
+ res.error!
54
+ end
55
+
56
+ def upload(locals, remote)
57
+ nx_transport.execute("mkdir -p #{remote}").error!
58
+ [locals].flatten.each do |local|
59
+ nx_transport.upload_file local, File.join(remote, File.basename(local)) if File.file? local
60
+ if File.directory? local
61
+ debug "Transferring folder (#{local}) to remote: #{remote}"
62
+ nx_transport.upload_folder local, remote
63
+ end
64
+ end
65
+ end
66
+
67
+ def download(remotes, local)
68
+ FileUtils.mkdir_p local unless Dir.exist? local
69
+ [remotes].flatten.each do |remote|
70
+ nx_transport.download_folder remote.to_s, local, auto_detect: true
71
+ end
72
+ end
73
+
74
+ def login_command
75
+ args = [File.expand_path('../../../../bin/lxc-shell', __FILE__), state_filename]
76
+ LoginCommand.new 'ruby', args
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
metadata ADDED
@@ -0,0 +1,174 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kitchen-lxd_sling
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ platform: ruby
6
+ authors:
7
+ - Sean Zachariasen
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-02-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: lxd-common
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.9'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.9'
27
+ - !ruby/object:Gem::Dependency
28
+ name: test-kitchen
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '1.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: tty-reader
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.2'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: tty-screen
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '0.6'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '0.6'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: berkshelf
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description:
126
+ email:
127
+ - thewyzard@hotmail.com
128
+ executables: []
129
+ extensions: []
130
+ extra_rdoc_files: []
131
+ files:
132
+ - ".gitignore"
133
+ - ".kitchen.travis.yml"
134
+ - ".kitchen.yml"
135
+ - ".rspec"
136
+ - ".travis.yml"
137
+ - Berksfile
138
+ - Gemfile
139
+ - LICENSE
140
+ - README.md
141
+ - Rakefile
142
+ - bin/console
143
+ - bin/lxc-shell
144
+ - bin/setup
145
+ - kitchen-lxd_nexus.gemspec
146
+ - lib/kitchen/driver/lxd.rb
147
+ - lib/kitchen/driver/lxd/host_locator.rb
148
+ - lib/kitchen/driver/lxd_version.rb
149
+ - lib/kitchen/transport/lxd.rb
150
+ homepage: https://github.com/NexusSW/kitchen-lxd_sling
151
+ licenses:
152
+ - Apache-2.0
153
+ metadata: {}
154
+ post_install_message:
155
+ rdoc_options: []
156
+ require_paths:
157
+ - lib
158
+ required_ruby_version: !ruby/object:Gem::Requirement
159
+ requirements:
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ version: '0'
163
+ required_rubygems_version: !ruby/object:Gem::Requirement
164
+ requirements:
165
+ - - ">="
166
+ - !ruby/object:Gem::Version
167
+ version: '0'
168
+ requirements: []
169
+ rubyforge_project:
170
+ rubygems_version: 2.6.14
171
+ signing_key:
172
+ specification_version: 4
173
+ summary: Test Kitchen Driver for LXD
174
+ test_files: []