clc_machine 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b3a9cf7685e5942e8f5260b7a15ae6e0b71eb765
4
+ data.tar.gz: 600b9d4e20da9c498b72291550969c202939d21e
5
+ SHA512:
6
+ metadata.gz: a7959abe9f65cf4f527cd5ea3edef1466322c7456c8ab05097f08bae30086b49de42645b79159386136e1e39dcefb12e996af5adad41059e457545b239795212
7
+ data.tar.gz: 2b504629673ad5e507222770ef74d417398c255d379707d26bded1b5971e22dc7a6aaa7c1f670ccefcfc43d3bd3b4366e75ed618c9ced530ac20d4b05580b61a
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ *.bundle
10
+ *.so
11
+ *.o
12
+ *.a
13
+ mkmf.log
14
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in clc_machine.gemspec
4
+ gemspec
@@ -0,0 +1,99 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ clc_machine (0.1.0)
5
+ chef-vault (~> 2.4.0)
6
+ clc-chef-metal-vsphere
7
+
8
+ GEM
9
+ remote: https://rubygems.org/
10
+ specs:
11
+ akami (1.2.2)
12
+ gyoku (>= 0.4.0)
13
+ nokogiri
14
+ builder (3.2.2)
15
+ chef-vault (2.4.0)
16
+ chef-zero (3.2.1)
17
+ ffi-yajl (~> 1.1)
18
+ hashie (~> 2.0)
19
+ mixlib-log (~> 1.3)
20
+ rack
21
+ uuidtools (~> 2.1)
22
+ clc-chef-metal-vsphere (0.3.67)
23
+ clc-fork-chef-metal (= 0.14.alpha.8)
24
+ rbvmomi (~> 1.8.0, >= 1.8.2)
25
+ rubyzip (= 1.1.6)
26
+ clc-cheffish (0.8.3.clc.3)
27
+ chef-zero
28
+ clc-fork-chef-metal (0.14.alpha.8)
29
+ clc-cheffish (~> 0.8.3.clc.3)
30
+ inifile (~> 2.0)
31
+ net-scp (~> 1.0)
32
+ net-ssh (~> 2.0)
33
+ net-ssh-gateway (~> 1.2.0)
34
+ winrm (~> 1.2.0)
35
+ ffi (1.9.6)
36
+ ffi-yajl (1.3.1)
37
+ ffi (~> 1.5)
38
+ libyajl2 (~> 1.2)
39
+ gssapi (1.0.3)
40
+ ffi (>= 1.0.1)
41
+ gyoku (1.2.2)
42
+ builder (>= 2.1.2)
43
+ hashie (2.1.2)
44
+ httpclient (2.5.3.3)
45
+ httpi (0.9.7)
46
+ rack
47
+ inifile (2.0.2)
48
+ libyajl2 (1.2.0)
49
+ little-plugger (1.1.3)
50
+ logging (1.8.2)
51
+ little-plugger (>= 1.1.3)
52
+ multi_json (>= 1.8.4)
53
+ mini_portile (0.6.1)
54
+ mixlib-log (1.6.0)
55
+ multi_json (1.10.1)
56
+ net-scp (1.2.1)
57
+ net-ssh (>= 2.6.5)
58
+ net-ssh (2.9.1)
59
+ net-ssh-gateway (1.2.0)
60
+ net-ssh (>= 2.6.5)
61
+ nokogiri (1.6.5)
62
+ mini_portile (~> 0.6.0)
63
+ nori (1.1.5)
64
+ rack (1.5.2)
65
+ rake (10.4.2)
66
+ rbvmomi (1.8.2)
67
+ builder
68
+ nokogiri (>= 1.4.1)
69
+ trollop
70
+ rubyntlm (0.1.1)
71
+ rubyzip (1.1.6)
72
+ savon (0.9.5)
73
+ akami (~> 1.0)
74
+ builder (>= 2.1.2)
75
+ gyoku (>= 0.4.0)
76
+ httpi (~> 0.9)
77
+ nokogiri (>= 1.4.0)
78
+ nori (~> 1.0)
79
+ wasabi (~> 1.0)
80
+ trollop (2.0)
81
+ uuidtools (2.1.5)
82
+ wasabi (1.0.0)
83
+ nokogiri (>= 1.4.0)
84
+ winrm (1.2.0)
85
+ gssapi (~> 1.0.0)
86
+ httpclient (~> 2.2, >= 2.2.0.2)
87
+ logging (~> 1.6, >= 1.6.1)
88
+ nokogiri (~> 1.5)
89
+ rubyntlm (~> 0.1.1)
90
+ savon (= 0.9.5)
91
+ uuidtools (~> 2.1.2)
92
+
93
+ PLATFORMS
94
+ ruby
95
+
96
+ DEPENDENCIES
97
+ bundler (~> 1.7)
98
+ clc_machine!
99
+ rake (~> 10.0)
@@ -0,0 +1,43 @@
1
+ # clc_machine
2
+ clc_machine provides commands for inspecting, deleting and adding machines in the QA1 DLAB folder. This is really intended to be a quick and dirty tool for a rather narrow use case.
3
+
4
+ ## Installation
5
+
6
+ Add this line to your application's Gemfile:
7
+
8
+ ```ruby
9
+ gem 'clc_machine'
10
+ ```
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install clc_machine
19
+
20
+ ## Usage
21
+
22
+ ```
23
+ clc_machine COMMAND [MACHINE NAME] [OPTIONS]
24
+ ```
25
+
26
+ ### Commands
27
+
28
+ - delete
29
+
30
+ Deletes machines specified by name or regex (see options). An attempt will be made to delete the machine from the chef server as well.
31
+
32
+ - get
33
+
34
+ Returns details about a machine.
35
+
36
+ - list
37
+
38
+ Lists all machines in the QA1 DLAB folder.
39
+
40
+ ### Options
41
+
42
+ - -n, --name: The name of the vm
43
+ - -r, --regex: A regular expression to match one or more VMs.
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,122 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'clc_machine'
4
+ require 'optparse'
5
+ require 'highline/import'
6
+
7
+ def parse_options()
8
+ options = {}
9
+
10
+ opt_parser = OptionParser.new do |opt|
11
+ opt.banner = "Usage: clc_machine COMMAND [MACHINE NAME] [OPTIONS]"
12
+ opt.separator ""
13
+ opt.separator "Commands"
14
+ opt.separator " delete: delete server"
15
+ opt.separator " get: gets a server"
16
+ opt.separator " list: lists servers"
17
+ opt.separator ""
18
+ opt.separator "Options"
19
+
20
+ opt.on("-n","--name NAME","name of vm to create") do |name|
21
+ options[:name] = name
22
+ end
23
+
24
+ opt.on("-r","--regex REGEX","regular expresion to match for deleting VMs") do |regex|
25
+ options[:regex] = Regexp.new regex
26
+ end
27
+
28
+ options[:stamp] = "QA1"
29
+ opt.on("-s","--stamp STAMP","name of stamp to target") do |stamp|
30
+ options[:stamp] = stamp
31
+ end
32
+
33
+ options[:folder] = "DLAB"
34
+ opt.on("-f","--folder FOLDER","vsphere folder to target") do |folder|
35
+ options[:folder] = folder
36
+ end
37
+
38
+ options[:hypervisor_type] = :standard
39
+ opt.on("-t","--hypervisor_type TYPE","standard(default) or hyperscale") do |hypervisor_type|
40
+ options[:hypervisor_type] = hypervisor_type.to_sym
41
+ end
42
+
43
+ opt.on("-c","--knife_config PATH","path to knife config") do |knife_config|
44
+ options[:knife_config] = knife_config
45
+ end
46
+
47
+ opt.on("-k","--key KEY","chef api client key") do |key|
48
+ options[:key] = key
49
+ end
50
+
51
+ opt.on("-u","--user USER","chef api client username") do |user|
52
+ options[:user] = user
53
+ end
54
+
55
+ opt.on("-h","--help","help") do
56
+ puts opt_parser
57
+ exit
58
+ end
59
+ end
60
+
61
+ command = ARGV[0]
62
+
63
+ # first token after command name defaults machine name if none was set
64
+ if command != 'list' && !options.has_key?(:name) && !options.has_key?(:regex) && ARGV.length > 1
65
+ options[:name] = ARGV[1]
66
+ end
67
+ options[:command] = command
68
+
69
+ if validate_input(options, opt_parser) == false
70
+ puts opt_parser
71
+ exit 1
72
+ end
73
+
74
+ options
75
+ end
76
+
77
+ def validate_input(options, opt_parser)
78
+ begin
79
+ opt_parser.parse!
80
+ mandatory = []
81
+ if options[:command] != "list"
82
+ if !options.has_key?(:name) && !options.has_key?(:regex)
83
+ puts "Either --name or --regex option is required"
84
+ return false
85
+ end
86
+ end
87
+ return false unless %w{list delete get}.include?(options[:command])
88
+ rescue OptionParser::InvalidOption, OptionParser::MissingArgument
89
+ puts $!.to_s
90
+ return false
91
+ end
92
+ return true
93
+ end
94
+
95
+ def run(options)
96
+ clc_machine = ClcMachine::Machine.new(options)
97
+ case options[:command]
98
+ when "get"
99
+ puts clc_machine.get(options[:name]).summary.pretty_inspect
100
+ when "list"
101
+ puts "listing vms in #{options[:folder]}..."
102
+ clc_machine.get.each do | vm |
103
+ puts vm['name']
104
+ end
105
+ when "delete"
106
+ if options[:regex]
107
+ clc_machine.delete(options[:regex])
108
+ else
109
+ confirm = ask("Delete machine #{options[:name]}? (Y/N) ") { |q| q.validate = /\A[yYnN]\Z/ }
110
+ if confirm.downcase == 'y'
111
+ clc_machine.delete(options[:name])
112
+ else
113
+ puts "Exiting."
114
+ exit 0
115
+ end
116
+ end
117
+ end
118
+
119
+ exit 0
120
+ end
121
+
122
+ run(parse_options)
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'clc_machine/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "clc_machine"
8
+ spec.version = ClcMachine::VERSION
9
+ spec.authors = ['CenturyLink Cloud']
10
+ spec.email = ["matt.wrock@ctl.io"]
11
+ spec.summary = 'Minimal cli for managing clc dlab machines'
12
+ spec.description = spec.summary
13
+ spec.homepage = ""
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ["lib"]
19
+
20
+ spec.add_development_dependency "bundler", "~> 1.7"
21
+ spec.add_development_dependency "rake", "~> 10.0"
22
+ spec.add_runtime_dependency 'clc-chef-metal-vsphere'
23
+ spec.add_runtime_dependency 'chef-vault'
24
+ spec.add_runtime_dependency 'chef'
25
+ end
@@ -0,0 +1,141 @@
1
+ require 'chef_metal_vsphere/vsphere_driver'
2
+ require 'chef_metal/chef_machine_spec'
3
+ require 'clc_machine/data_bag'
4
+ require 'clc_machine/secret_data_bag'
5
+ require 'clc_machine/utils'
6
+ require 'rbvmomi'
7
+ require 'highline/import' # user interaction
8
+
9
+ module ClcMachine
10
+ class Machine
11
+ def initialize(options)
12
+ @options = options
13
+ set_chef(options)
14
+ @data_bag = DataBag.new(options[:stamp])
15
+ @secrets = SecretDataBag.new(options[:stamp])
16
+ end
17
+
18
+ attr_reader :options
19
+ attr_reader :data_bag
20
+ attr_reader :secrets
21
+
22
+ def connection
23
+ RbVmomi::VIM.connect vsphere_options
24
+ end
25
+
26
+ def get(name = nil)
27
+ stamp = data_bag.vsphere_datacenter(options[:hypervisor_type])
28
+ if name
29
+ find_vm(stamp, options[:folder], name)
30
+ else
31
+ folder = find_folder(stamp, options[:folder])
32
+ folder.childEntity.each
33
+ end
34
+ end
35
+
36
+ def delete(name)
37
+ if name.is_a?(String)
38
+ vm = get(name)
39
+ if vm
40
+ config = Chef::Config.merge!({ :driver_options => vsphere_options })
41
+ machine_spec = ChefMetal::ChefMachineSpec.new({'name' => name}, Cheffish.default_chef_server(config))
42
+ driver = ChefMetal.driver_for_url("vsphere://#{vsphere_options[:host]}", config)
43
+ action_handler = ChefMetal::ActionHandler.new
44
+ machine_spec.location = { 'driver_url' => driver.driver_url,
45
+ 'server_id' => vm.config.instanceUuid}
46
+
47
+ chef_server = Cheffish.default_chef_server(config)
48
+ begin
49
+ driver.destroy_machine(action_handler, machine_spec, :convergence_options => { :chef_server => chef_server })
50
+ rescue Chef::Exceptions::PrivateKeyMissing, Net::HTTPServerException, Errno::ETIMEDOUT
51
+ puts "Unable to delete node on the chef server. See previous message."
52
+ end
53
+
54
+ puts "succesfully deleted #{name}"
55
+ else
56
+ puts "VM #{name} does not exist. I shall destroy nothing."
57
+ end
58
+ else
59
+ to_be_deleted = []
60
+ print 'Looking for matching machines '
61
+ get.each do |v|
62
+ check = v['name']
63
+ print '.'
64
+ if name.match(check)
65
+ to_be_deleted.push(check)
66
+ end
67
+ end
68
+ if to_be_deleted.count > 0
69
+ puts "\nReady to delete #{to_be_deleted.inspect}"
70
+ confirm = ask("Continue? (Y/N) ") { |q| q.validate = /\A[yYnN]\Z/ }
71
+ if confirm.downcase == 'y'
72
+ to_be_deleted.each do |m|
73
+ delete m
74
+ end
75
+ else
76
+ puts 'No action taken. Exiting.'
77
+ exit 0
78
+ end
79
+ else
80
+ puts "\nNo matching machines found. Exiting."
81
+ exit 0
82
+ end
83
+ end
84
+ end
85
+
86
+ private
87
+
88
+ def set_chef(options)
89
+ Chef::Config.reset
90
+ if @options.has_key?(:knife_config)
91
+ Chef::Config.from_file(@options[:knife_config])
92
+ else
93
+ repo = Chef::Config.find_chef_repo_path(Dir.pwd)
94
+ Chef::Config.from_file(File.join(repo, '.chef', 'knife.rb'))
95
+ end
96
+
97
+ if @options.has_key?(:key)
98
+ Chef::Config[:client_key] = @options[:key]
99
+ end
100
+
101
+ if @options.has_key?(:user)
102
+ Chef::Config[:node_name] = @options[:user]
103
+ end
104
+
105
+ if !File::exist?(Chef::Config[:client_key])
106
+ raise "Cant locate #{Chef::Config[:client_key]}."
107
+ end
108
+ end
109
+
110
+ def vsphere_options
111
+ {
112
+ :host => data_bag.vsphere_server(options[:hypervisor_type]),
113
+ :user => secrets.vsphere_username(options[:hypervisor_type]),
114
+ :password => secrets.vsphere_password(options[:hypervisor_type]),
115
+ :insecure => true
116
+ }
117
+ end
118
+
119
+ def find_vm(dc_name, vm_folder, vm_name)
120
+ folder = find_folder(dc_name, vm_folder) or raise("vSphere Folder not found [#{vm_folder}] for vm #{vm_name}")
121
+ folder.find(vm_name, RbVmomi::VIM::VirtualMachine)
122
+ end
123
+
124
+ def find_folder(dc_name, folder_name)
125
+ baseEntity = dc(dc_name).vmFolder
126
+ if folder_name && folder_name.length > 0
127
+ entityArray = folder_name.split('/')
128
+ entityArray.each do |entityArrItem|
129
+ if entityArrItem != ''
130
+ baseEntity = baseEntity.childEntity.grep(RbVmomi::VIM::Folder).find { |f| f.name == entityArrItem }
131
+ end
132
+ end
133
+ end
134
+ baseEntity
135
+ end
136
+
137
+ def dc(dc_name)
138
+ connection.serviceInstance.find_datacenter(dc_name) or raise("vSphere Datacenter not found [#{dc_name}]")
139
+ end
140
+ end
141
+ end
@@ -0,0 +1,42 @@
1
+ require 'json'
2
+
3
+ module ClcMachine
4
+ class DataBag
5
+ TMP_DIR = '/tmp/ClcMachine/data_bags'
6
+ def initialize(stamp)
7
+ @stamp = stamp
8
+ end
9
+
10
+ def vsphere_datacenter(hypervisor_type = :standard)
11
+ raw[:hypervisors][hypervisor_type][0]['datacenter']
12
+ end
13
+
14
+ def vsphere_server(hypervisor_type = :standard)
15
+ raw[:hypervisors][hypervisor_type][0]['vsphere_server']
16
+ end
17
+
18
+ def raw
19
+ @raw ||= load_databag
20
+ end
21
+
22
+ private
23
+
24
+ def load_databag
25
+ download_data_bag
26
+ Utils.symbolize_keys(JSON.parse(IO.read(File.join(TMP_DIR, 'stamps',"#{@stamp}.json"))))
27
+ end
28
+
29
+ def download_data_bag
30
+ FileUtils.mkdir_p(TMP_DIR) if !Dir.exist?(TMP_DIR)
31
+
32
+ fs_config = Chef::ChefFS::Config.new(Chef::Config, cwd = Dir.pwd)
33
+ pattern = Chef::ChefFS::FilePattern.new("/data_bags/*")
34
+ local = Chef::ChefFS::FileSystem::ChefRepositoryFileSystemRootDir.new(
35
+ {
36
+ 'data_bags' => [TMP_DIR],
37
+ }
38
+ )
39
+ Chef::ChefFS::FileSystem.copy_to(pattern, fs_config.chef_fs, local, 1, Chef::Config)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,32 @@
1
+ require 'chef-vault'
2
+
3
+ module ClcMachine
4
+ class SecretDataBag
5
+ def initialize(stamp)
6
+ @stamp = stamp
7
+ end
8
+
9
+ def vsphere_username(hypervisor_type = :standard)
10
+ raw['hypervisors'][hypervisor_type.to_s]['vsphere_username']
11
+ end
12
+
13
+ def vsphere_password(hypervisor_type = :standard)
14
+ raw['hypervisors'][hypervisor_type.to_s]['vsphere_password']
15
+ end
16
+
17
+ def raw
18
+ @raw ||= load_secrets
19
+ end
20
+
21
+ private
22
+
23
+ def load_secrets
24
+ %w{secrets_qa secrets_prod}.each do |bag|
25
+ begin
26
+ return ChefVault::Item.load(bag, "#{@stamp}_secrets")
27
+ rescue ChefVault::Exceptions::KeysNotFound
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,12 @@
1
+ module ClcMachine
2
+ class Utils
3
+ def self.symbolize_keys(h)
4
+ Hash === h ?
5
+ Hash[
6
+ h.map do |k, v|
7
+ [k.respond_to?(:to_sym) ? k.to_sym : k, symbolize_keys(v)]
8
+ end
9
+ ] : h
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,3 @@
1
+ module ClcMachine
2
+ VERSION = "0.1.11"
3
+ end
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: clc_machine
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.11
5
+ platform: ruby
6
+ authors:
7
+ - CenturyLink Cloud
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: clc-chef-metal-vsphere
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: chef-vault
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: chef
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: Minimal cli for managing clc dlab machines
84
+ email:
85
+ - matt.wrock@ctl.io
86
+ executables:
87
+ - clc_machine
88
+ extensions: []
89
+ extra_rdoc_files: []
90
+ files:
91
+ - ".gitignore"
92
+ - Gemfile
93
+ - Gemfile.lock
94
+ - README.md
95
+ - Rakefile
96
+ - bin/clc_machine
97
+ - clc_machine.gemspec
98
+ - lib/clc_machine.rb
99
+ - lib/clc_machine/data_bag.rb
100
+ - lib/clc_machine/secret_data_bag.rb
101
+ - lib/clc_machine/utils.rb
102
+ - lib/clc_machine/version.rb
103
+ homepage: ''
104
+ licenses: []
105
+ metadata: {}
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ requirements: []
121
+ rubyforge_project:
122
+ rubygems_version: 2.4.1
123
+ signing_key:
124
+ specification_version: 4
125
+ summary: Minimal cli for managing clc dlab machines
126
+ test_files: []
127
+ has_rdoc: