helm 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: de942658d9f770530a4b5ef00b7481cc03dbf4e3
4
+ data.tar.gz: 7418c354fc2f5122d2e8f86d56d05f6123a26811
5
+ SHA512:
6
+ metadata.gz: d5611ba2985c413ea5b0964ff9b36243ee061b1627a076c54362770ea0b94874a1b81e86c1ef4eec40e51b7c7e98d262b8534efbcc65c0529b7f0a40f77dacbe
7
+ data.tar.gz: 73550c907b1a97555e299981057ba0eb4c21987bf0765ef8cffa210ca3c7ec9f416a3460c05e9868449300168edb196e3d0b7fc1fbffe899a8b5473089c963c6
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'helm/cli'
4
+
5
+ Helm.load_commands
6
+ Helm::CLI::Main.start(ARGV)
@@ -0,0 +1,60 @@
1
+ require 'valise'
2
+ require 'sequel'
3
+ require 'logger'
4
+ require 'helm/application'
5
+ require 'helm/cli'
6
+ require 'helm/server-command'
7
+
8
+ module Helm
9
+ class << self
10
+ def logger
11
+ @logger ||= Logger.new($stderr).tap do |logger|
12
+ logger.level = Logger::ERROR
13
+ end
14
+ end
15
+
16
+ def databases
17
+ @databases ||= Hash.new do |hash, conn_string|
18
+ hash[conn_string] = Sequel::connect(conn_string, :logger => logger).tap do |db|
19
+ db.extension(:pretty_table)
20
+ end
21
+ end
22
+ end
23
+
24
+ def log_at(level)
25
+ begin
26
+ old_level, logger.level = logger.level, level
27
+ yield
28
+ ensure
29
+ logger.level = old_level
30
+ end
31
+ end
32
+
33
+ def check_db(db_string, directory)
34
+ require 'sequel/extensions/migration'
35
+
36
+ unless Sequel::Migrator.is_current?(databases[db_string], directory)
37
+ warn "Your servers database is out of date. You should run #$0 db update."
38
+ end
39
+ end
40
+
41
+ def valise
42
+ @valise ||= Valise.define do
43
+ ro from_here(%w{.. default_configuration}, up_to("lib"))
44
+ end
45
+ end
46
+
47
+ def commands_valise
48
+ @commands_valise ||= valise.sub_set("commands")
49
+ end
50
+
51
+ def load_commands
52
+ commands_valise.glob("*.rb") do |file|
53
+ require file.full_path
54
+ end
55
+ ServerCommand.valid_commands.each do |command_class|
56
+ CLI::Main.define_from(command_class.new)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,163 @@
1
+ require 'helm/command-runner'
2
+ require 'helm/queries/server'
3
+
4
+ module Helm
5
+ module Commands
6
+ class Command
7
+ def initialize(app_config, options)
8
+ @app_config = app_config
9
+ @options = options
10
+ end
11
+ attr_accessor :app_config, :options
12
+
13
+ def if_option(name)
14
+ if options.has_key?(name.to_s)
15
+ yield(options[name])
16
+ end
17
+ end
18
+ end
19
+
20
+ module Main
21
+ class Defined < Command
22
+ def initialize(app_config, options, config)
23
+ @config = config
24
+ super(app_config, options)
25
+ end
26
+ attr_reader :config
27
+
28
+ def execute
29
+ config.query_options = options || {}
30
+
31
+ query = Helm::Queries::Server.new(app_config.connstring)
32
+ if_option(:client){|client| query.client = client }
33
+ if_option(:role){|role| query.role = role }
34
+ if_option(:name){|name| query.name = name }
35
+ if_option(:platform){|platform| query.platform = platform }
36
+
37
+ runner = Helm::CommandRunner.new(query, config)
38
+ runner.run
39
+ end
40
+ end
41
+ end
42
+
43
+ module Database
44
+ class Migrate < Command
45
+ def initialize(app_config, options)
46
+ @directory = "migrations"
47
+ super
48
+ end
49
+ attr_accessor :db_string, :directory
50
+
51
+ def execute
52
+ require 'sequel/extensions/migration'
53
+
54
+ Helm.log_at(Logger::DEBUG) do
55
+ Sequel::Migrator.run(Helm.databases[app_config.connstring], directory)
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ module Servers
62
+ class Add < Command
63
+ def initialize(app_config, options, source_io)
64
+ @source_io = source_io
65
+ super(app_config, options)
66
+ end
67
+
68
+ def execute
69
+ require 'yaml'
70
+ require 'helm/persisters/server'
71
+ serverlist = Array(YAML.load(source_io.read))
72
+
73
+ store = Helm::Persisters::Server.new(app_config.connstring)
74
+
75
+ defaults = {:client => options[:client]}
76
+
77
+ serverlist.each do |server|
78
+ store.insert_or_update(defaults.merge(server))
79
+ end
80
+ end
81
+ end
82
+
83
+ class List < Command
84
+ def execute
85
+ require 'helm/queries/server'
86
+ Helm::Queries::Server.new(app_config.connstring).print
87
+ end
88
+ end
89
+
90
+ class Edit < Command
91
+ def edit_tempfile(file)
92
+ require 'io/console'
93
+
94
+ edit_shell = Caliph::Shell.new
95
+ edit_shell.output_stream = File.new("/dev/null", "a")
96
+ edit_shell.run(ENV['EDITOR'] || app_config.editor, file.path) do |cmd|
97
+ cmd.redirect_stdin(IO.console.path)
98
+ cmd.redirect_stdout(IO.console.path)
99
+ end
100
+ ensure
101
+ edit_shell.output_stream.close
102
+ end
103
+
104
+ def server_query
105
+ query = Helm::Queries::Server.new(app_config.connstring)
106
+
107
+ if_option(:id){|server_id| query.server_id = server_id }
108
+ if_option(:client){|client| query.client = client }
109
+ if_option(:role){|role| query.role = role }
110
+ if_option(:name){|name| query.name = name }
111
+ if_option(:platform){|platform| query.platform = platform }
112
+
113
+ query
114
+ end
115
+
116
+ def put_server_record_in_file(query, file)
117
+ server = query.first
118
+ server_hash = server.to_hash
119
+
120
+ server_id = server_hash.delete(:server_id)
121
+
122
+ file.write("# Edit this file to update the server\n")
123
+ file.write(server_hash.to_yaml)
124
+ file.close
125
+
126
+ return server_id
127
+ end
128
+
129
+ def save_server_record_to_database(server_id, file)
130
+ file.open
131
+ new_hash = YAML.load(file.read).merge(:server_id => server_id)
132
+
133
+ store = Helm::Persisters::Server.new(app_config.connstring)
134
+ store.insert_or_update(new_hash)
135
+ end
136
+
137
+ def execute
138
+ require 'yaml'
139
+ require 'helm/persisters/server'
140
+
141
+ query = server_query
142
+
143
+ unless query.to_a.length == 1
144
+ puts "#{query.to_a.length} servers match #{query.constraint.inspect}"
145
+ exit 1
146
+ end
147
+
148
+ begin
149
+ file = Tempfile.new('server', app_config.tempdir)
150
+
151
+ server_id = put_server_record_in_file(query, file)
152
+
153
+ edit_tempfile(file)
154
+
155
+ save_server_record_to_database(server_id, file)
156
+ ensure
157
+ file.unlink if file
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,75 @@
1
+ require 'helm'
2
+ require 'thor'
3
+
4
+ module Helm
5
+ Config = Struct.new(:connstring, :editor, :tempdir)
6
+
7
+ def self.config
8
+ Config.new("sqlite://servers.sql", "vim", ".")
9
+ end
10
+
11
+ module CLI
12
+ class DB < Thor
13
+ include Commands::Database
14
+
15
+ desc "update", "Update the servers database schema"
16
+ def update
17
+ Migrate.new(Helm.config, options).execute
18
+ end
19
+ end
20
+
21
+ class Server < Thor
22
+ include Commands::Servers
23
+
24
+ desc "add", "Add a list of servers described in YAML from STDIN"
25
+ option :client, :banner => "Client name"
26
+ def add
27
+ Add.new(Helm.config, options, $stdin).execute
28
+ end
29
+
30
+ desc "list", "List servers that Helm knows about"
31
+ def list
32
+ puts List.new(Helm.config, options).execute
33
+ end
34
+
35
+ desc "edit", "Edit the details of particular servers"
36
+ method_option :id
37
+ def edit
38
+ Edit.new(Helm.config, options).execute
39
+ end
40
+ end
41
+
42
+ class Main < Thor
43
+ desc "db SUBCOMMAND", "server database maintenance tasks"
44
+ subcommand "db", DB
45
+
46
+ desc "server SUBCOMMAND", "server listing tasks"
47
+ subcommand "server", Server
48
+
49
+ class_option :client
50
+ class_option :name
51
+ class_option :role
52
+
53
+ class << self
54
+ def define_from(command_config)
55
+ desc command_config.name.to_s, command_config.description
56
+ command_config.scope_options.each do |name|
57
+ option name, :required => true
58
+ end
59
+
60
+ define_method command_config.name do |*args|
61
+ command = Commands::Main::Defined.new(Helm.config, options, command_config)
62
+ command.execute(*args)
63
+ end
64
+ end
65
+ end
66
+
67
+ def help(task = nil, subcommand=false)
68
+ super
69
+
70
+ shell.say "Commands are loaded from:"
71
+ shell.say Helm.commands_valise.to_s
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,56 @@
1
+ require 'caliph'
2
+
3
+ module Helm
4
+ class CommandRunner
5
+ CommandExecution = Struct.new(:server, :result)
6
+
7
+ def initialize(server_query, command_definition)
8
+ @server_query, @command_definition = server_query, command_definition
9
+ @completed = []
10
+ @ran_any = false
11
+ end
12
+
13
+ attr_accessor :server_query, :command_definition, :shell
14
+
15
+ def shell
16
+ @shell ||= Caliph::Shell.new
17
+ end
18
+
19
+ def run
20
+ start_run
21
+ catch :fail do
22
+ configured_query.each do |server|
23
+ result = run_one(command_definition.command(server))
24
+ execution = CommandExecution.new(server, result)
25
+ collect(execution)
26
+ end
27
+ end
28
+ finish_run
29
+ end
30
+
31
+ def configured_query
32
+ command_definition.configure_query(server_query)
33
+ server_query
34
+ end
35
+
36
+ def run_one(single)
37
+ @ran_any = true
38
+ shell.execute(single)
39
+ end
40
+
41
+ def start_run
42
+ @ran_any = false
43
+ end
44
+
45
+ def finish_run
46
+ warn "No servers found for #{server_query}!" unless @ran_any
47
+ command_definition.all_results(@completed)
48
+ return true
49
+ end
50
+
51
+ def collect(execution)
52
+ @completed << execution
53
+ command_definition.each_result(execution)
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,27 @@
1
+ require 'helm'
2
+
3
+ module Helm
4
+ class Persister
5
+ def initialize(db_string)
6
+ @db = Helm.databases[db_string]
7
+ end
8
+ attr_accessor :db
9
+
10
+ def slice(hash)
11
+ Hash[
12
+ columns.zip(
13
+ hash.values_at(*columns).zip(
14
+ hash.values_at(*(columns.map(&:to_s)))
15
+ ).map{|sym_val, str_val| sym_val || str_val })
16
+ ]
17
+ end
18
+
19
+ def dataset
20
+ @db[table_name]
21
+ end
22
+
23
+ def insert_or_update(row)
24
+ dataset.replace(slice(row))
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,16 @@
1
+ require 'helm/persister'
2
+ require 'helm/records/server'
3
+
4
+ module Helm
5
+ module Persisters
6
+ class Server < Persister
7
+ def columns
8
+ Records::Server.columns
9
+ end
10
+
11
+ def table_name
12
+ :servers
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,38 @@
1
+ require 'helm/query'
2
+ require 'helm/records/server'
3
+
4
+ module Helm
5
+ module Queries
6
+ class Server < Query
7
+ attr_accessor :server_id, :client, :name, :role, :platform, :id_from_platform
8
+
9
+ def to_s
10
+ nil_attrs = constraint_attrs.reject{|attr| constraint_hash.has_key?(attr) }
11
+ "Servers query: #{constraint_hash.inspect} (not set: #{nil_attrs.inspect})"
12
+ end
13
+
14
+ def inspect
15
+ "<#{self.class.name}:#{"%0x" % object_id} #{constraint.select_sql rescue "<?sql?>"}>"
16
+ end
17
+
18
+ def constraint_attrs
19
+ [:server_id, :client, :name, :role, :platform, :id_from_plaform]
20
+ end
21
+
22
+ def constraint_hash
23
+ @constraint_hash ||= constraint_attrs.each_with_object({}) do |attr, hash|
24
+ val = instance_variable_get("@#{attr}")
25
+ hash[attr] = val unless val.nil?
26
+ end
27
+ end
28
+
29
+ def constraint
30
+ @constraint ||= @db[:servers].where(constraint_hash)
31
+ end
32
+
33
+ def result_class
34
+ Records::Server
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,28 @@
1
+ require 'helm'
2
+
3
+ module Helm
4
+ class Query
5
+ include Enumerable
6
+
7
+ def initialize(conn_string)
8
+ @db = Helm.databases[conn_string]
9
+ end
10
+
11
+ attr_reader :db
12
+ attr_accessor :result_class
13
+
14
+ def constraint
15
+ @constraint ||= @db
16
+ end
17
+
18
+ def print
19
+ constraint.print
20
+ end
21
+
22
+ def each
23
+ constraint.select(*result_class.columns).each do |row|
24
+ yield result_class.new(row)
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,72 @@
1
+ module Helm
2
+ class Record
3
+ class << self
4
+ attr_accessor :columns
5
+
6
+ def types
7
+ @types ||= {}
8
+ end
9
+
10
+ def with_columns(*columns)
11
+ types[columns.sort] || subclass(*columns)
12
+ end
13
+
14
+ def subclass(*columns, &block)
15
+ klass = Class.new(self, &block)
16
+ columns = columns.sort
17
+ klass.columns = columns
18
+
19
+ columns.each do |column|
20
+ klass.column_accessor(column)
21
+ end
22
+ types[columns] ||= klass
23
+ end
24
+
25
+ def column_accessor(name)
26
+ unless instance_methods(false).include?(name)
27
+ define_method name do
28
+ @values[name]
29
+ end
30
+ end
31
+
32
+ write_method = "#{name}="
33
+ unless instance_methods(false).include?(write_method)
34
+ define_method write_method do |value|
35
+ @values[name] = value
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ def [](key)
42
+ @values[key]
43
+ end
44
+
45
+ def []=(key, value)
46
+ @values[key] = value
47
+ end
48
+
49
+ def keys
50
+ @row.keys | @values.keys
51
+ end
52
+
53
+ def initialize(row)
54
+ @row = row
55
+ @values = Hash.new do |h, k|
56
+ @row[k]
57
+ end
58
+ end
59
+
60
+ def changed
61
+ @values.keys
62
+ end
63
+
64
+ def to_hash
65
+ Hash[ keys.map{|key| [key, self[key]]}]
66
+ end
67
+
68
+ def to_yaml
69
+ to_hash.to_yaml
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,24 @@
1
+ require 'helm/record'
2
+
3
+ module Helm
4
+ module Records
5
+ Server = Record.subclass(
6
+ :server_id,
7
+ :platform,
8
+ :id_from_platform,
9
+ :name,
10
+ :client,
11
+ :private_dns_name,
12
+ :public_dns_name,
13
+ :private_ip_address,
14
+ :public_ip_address,
15
+ :ssh_key_name,
16
+ :architecture,
17
+ :launch_time
18
+ ) do
19
+ def name
20
+ self[:name] || [self[:platform], self[:id_from_platform]].join(":")
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,116 @@
1
+ require 'caliph/command-line-dsl'
2
+
3
+ module Helm
4
+ class ServerCommand
5
+
6
+ class << self
7
+ def subclasses
8
+ @subclasses ||= []
9
+ end
10
+
11
+ def inherited(sub)
12
+ ServerCommand.subclasses << sub
13
+ end
14
+
15
+ def abstract
16
+ @abstract = true
17
+ end
18
+
19
+ def abstract?
20
+ !!@abstract
21
+ end
22
+
23
+ def valid_commands(quietly = false)
24
+ valid = []
25
+ ServerCommand.subclasses.each do |sub|
26
+ next if sub.abstract?
27
+
28
+ methods = sub.instance_methods(false)
29
+
30
+ unless methods.include?(:name) and methods.include?(:command)
31
+ unless quietly
32
+ warn "ServerCommand subclass #{sub.name} isn't abstract and doesn't define :name and :command"
33
+ a_method = sub.instance_method(methods.first)
34
+ warn " (appears to be defined in #{a_method.source_location.first})"
35
+ end
36
+ next
37
+ end
38
+
39
+ valid << sub
40
+ end
41
+ valid
42
+ end
43
+ end
44
+
45
+ def valid?
46
+ true
47
+ end
48
+
49
+ def desc
50
+ ""
51
+ end
52
+ alias description desc
53
+
54
+ def required_options
55
+ []
56
+ end
57
+ alias scope_options required_options
58
+
59
+ attr_accessor :query_options
60
+
61
+ def configure_query(query)
62
+ end
63
+
64
+ def each_result(execution)
65
+ format_result(execution)
66
+ if execution.result.exit_code != 0
67
+ throw :fail
68
+ end
69
+ end
70
+
71
+ def all_results(results)
72
+ end
73
+
74
+ def format_result(execution)
75
+ result = execution.result
76
+ server = execution.server
77
+
78
+ puts "#{server.name} (#{server.public_ip_address})"
79
+ puts "#{result.command.string_format} => #{result.exit_code}"
80
+ puts result.format_streams
81
+ puts
82
+ end
83
+
84
+ include Caliph::CommandLineDSL
85
+
86
+ def ssh(server, *command, &block)
87
+ cmd("ssh") do |command|
88
+ command.options << "-o BatchMode=yes"
89
+ command.options << "-i " + server.ssh_key_name unless server.ssh_key_name.nil?
90
+ #command.options << "-l " + server.connect_as unless
91
+ #server.connect_as.nil?
92
+ # XXX need to add 'connect_as'
93
+ #command.options << "-p " + server.port unless server.ssh_port.nil? ##ok
94
+ # XXX need to add "ssh_port"
95
+ command.options << server.public_dns_name || server.public_ip_address
96
+ end - escaped_command(*command, &block)
97
+ end
98
+ end
99
+
100
+ module Persistent
101
+ def each_result(result)
102
+ format_results(result)
103
+ end
104
+ end
105
+
106
+ module Picky
107
+ def all_results(results)
108
+ if results.any?{|execution| execution.result.exit_code != 0}
109
+ raise "Command failed!\n #{
110
+ results.select{|execution| execution.result.exit_code != 0
111
+ }.map{|exec| exec.result.inspect}.join(" \n")
112
+ }"
113
+ end
114
+ end
115
+ end
116
+ end
File without changes
metadata ADDED
@@ -0,0 +1,148 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: helm
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Judson Lester
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '0.18'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '0.18'
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.1.1
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: 10.1.1
41
+ - !ruby/object:Gem::Dependency
42
+ name: sqlite3
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 1.3.5
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 1.3.5
55
+ - !ruby/object:Gem::Dependency
56
+ name: sequel
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 4.6.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 4.6.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: caliph
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: 0.3.1
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: 0.3.1
83
+ - !ruby/object:Gem::Dependency
84
+ name: valise
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: 1.1.1
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: 1.1.1
97
+ description: ''
98
+ email:
99
+ - nyarly@gmail.com
100
+ executables:
101
+ - helm
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - lib/helm/records/server.rb
106
+ - lib/helm/persister.rb
107
+ - lib/helm/queries/server.rb
108
+ - lib/helm/record.rb
109
+ - lib/helm/cli.rb
110
+ - lib/helm/persisters/server.rb
111
+ - lib/helm/command-runner.rb
112
+ - lib/helm/server-command.rb
113
+ - lib/helm/query.rb
114
+ - lib/helm/application.rb
115
+ - lib/helm.rb
116
+ - bin/helm
117
+ - spec_help/gem_test_suite.rb
118
+ homepage: http://nyarly.github.com/helm
119
+ licenses:
120
+ - MIT
121
+ metadata: {}
122
+ post_install_message:
123
+ rdoc_options:
124
+ - --inline-source
125
+ - --main
126
+ - doc/README
127
+ - --title
128
+ - helm-0.0.1 Documentation
129
+ require_paths:
130
+ - lib/
131
+ required_ruby_version: !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - - '>='
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ required_rubygems_version: !ruby/object:Gem::Requirement
137
+ requirements:
138
+ - - '>='
139
+ - !ruby/object:Gem::Version
140
+ version: '0'
141
+ requirements: []
142
+ rubyforge_project: helm
143
+ rubygems_version: 2.0.14
144
+ signing_key:
145
+ specification_version: 4
146
+ summary: ''
147
+ test_files:
148
+ - spec_help/gem_test_suite.rb