devops 0.0.8

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.
data/.gitignore ADDED
@@ -0,0 +1,3 @@
1
+ *.swo
2
+ *.swp
3
+ *.gem
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ # A sample Gemfile
2
+ source "https://rubygems.org"
3
+
4
+ gem "json"
5
+ gem "net-ssh"
6
+ gem "aws-sdk"
7
+ gem "i18n"
8
+ gem "rake"
9
+
10
+ group :development do
11
+ gem "rspec"
12
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,33 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ aws-sdk (1.8.3)
5
+ json (~> 1.4)
6
+ nokogiri (>= 1.4.4)
7
+ uuidtools (~> 2.1)
8
+ diff-lcs (1.1.3)
9
+ i18n (0.6.1)
10
+ json (1.7.7)
11
+ net-ssh (2.6.5)
12
+ nokogiri (1.5.6)
13
+ rake (10.0.3)
14
+ rspec (2.11.0)
15
+ rspec-core (~> 2.11.0)
16
+ rspec-expectations (~> 2.11.0)
17
+ rspec-mocks (~> 2.11.0)
18
+ rspec-core (2.11.1)
19
+ rspec-expectations (2.11.2)
20
+ diff-lcs (~> 1.1.3)
21
+ rspec-mocks (2.11.2)
22
+ uuidtools (2.1.3)
23
+
24
+ PLATFORMS
25
+ ruby
26
+
27
+ DEPENDENCIES
28
+ aws-sdk
29
+ i18n
30
+ json
31
+ net-ssh
32
+ rake
33
+ rspec
data/README.md ADDED
@@ -0,0 +1,54 @@
1
+ # Ops
2
+
3
+ This repo serves as a container for utilitys and apps related
4
+ to Operations tasks.
5
+
6
+ ## Using Ops tools:
7
+
8
+ ### Requirements
9
+
10
+ ruby 1.8.7
11
+ openssh
12
+
13
+ ### Getting Started
14
+
15
+ Add the following to your .bashrc or .bash_profile_
16
+
17
+ export $OPS_HOME="/path to your ops repo"
18
+ source $OPS_HOME/autocomplete
19
+
20
+ Add the following symbolic link so you can use this from any directory
21
+
22
+ # ln -s this somewhere else if you're using a shared computer
23
+ # maybe create a local bin folder in ~/ and add it to your path
24
+
25
+ ln -s $OPS_HOME /usr/local/bin/ops
26
+
27
+ run the following command
28
+
29
+ bundle install
30
+
31
+ create a config.json file with the following contents:
32
+
33
+ {
34
+ "IdentityLocations" : [ "~/.ssh", ... ],
35
+ "AWS" : {
36
+ "AccessKeyId" : "Your Access Key",
37
+ "SecretAccessKey" : "Your Secret Access Key"
38
+ }
39
+ }
40
+
41
+ ### Connecting to a host:
42
+
43
+ usage: ops [ host ]:ssh
44
+
45
+ ### Other commands:
46
+
47
+ ops -T - List all tasks available
48
+
49
+ ops hosts:list - List all the hosts
50
+
51
+ ops hosts:sync - Sync hosts.json with EC2 instance list
52
+
53
+ ops hosts:add host=[ alias name ] hostname=[ ip address or hostname ] \
54
+ identity=[ private key name ] user=[ user ]
data/autocomplete ADDED
@@ -0,0 +1,5 @@
1
+ function _build_ops_completion() {
2
+ ops -T | awk '{ print $2 }'
3
+ }
4
+
5
+ complete -W "$(_build_ops_completion)" ops
data/bin/ops ADDED
@@ -0,0 +1,41 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'devops'
4
+
5
+ def exit_failure( reason="", code=1 )
6
+ puts reason; exit
7
+ end
8
+
9
+ bootstrap_files = [
10
+ File.join( 'tasks', 'init.rb' ) ]
11
+
12
+ Dir.chdir Ops::pwd_dir do
13
+
14
+ unless Ops::pwd_dir == Dir.pwd
15
+ puts "Executing from ( #{ Ops::pwd_dir } )".warning
16
+ end
17
+
18
+ Rake.application.init( File.basename( $0 ) )
19
+
20
+ begin
21
+ bootstrap_files.each do | f |
22
+ File.join Ops::root_dir, f
23
+ require f
24
+ end
25
+ rescue => e
26
+ puts e
27
+ end
28
+
29
+ bootstrap_files.each do | f |
30
+ f = File.join Ops::pwd_dir, f
31
+ require f if File.exists? f
32
+ end
33
+
34
+ begin
35
+ Rake.application.top_level
36
+ rescue => e
37
+ puts "Failed to call task: #{ e.message }"
38
+ end
39
+ end
40
+
41
+ exit
data/devops.gemspec ADDED
@@ -0,0 +1,24 @@
1
+ require './lib/version.rb'
2
+
3
+ files = `git ls-files`.split("\n")
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'devops'
7
+
8
+ s.version = Ops::version
9
+
10
+ s.date = Time.new
11
+
12
+ s.summary = "Ops tool for remote servers"
13
+ s.description = "Ops tool for remote servers"
14
+
15
+ s.authors = [ "Hardeep Shoker", "Ryan Willoughby" ]
16
+ s.email = 'hardeepshoker@gmail.com'
17
+ s.homepage = 'https://github.com/hardeep/ops'
18
+
19
+ s.files = files
20
+
21
+ s.bindir = 'bin'
22
+ s.require_paths = ["lib"]
23
+ s.executables = [ 'ops' ]
24
+ end
data/lib/devops.rb ADDED
@@ -0,0 +1,31 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ require 'rubygems'
5
+ require 'bundler'
6
+ end
7
+
8
+ # standard gems
9
+ require 'json'
10
+ require 'etc'
11
+ require 'pathname'
12
+ require 'pp'
13
+
14
+ # external gems
15
+ require 'net/ssh'
16
+ require 'i18n'
17
+ require 'rake'
18
+ require 'aws-sdk'
19
+
20
+ # local includes
21
+ require 'version'
22
+ require 'host/list'
23
+ require 'host/default'
24
+ require 'host/e_c_2'
25
+ require 'ops/common'
26
+ require 'ops/console'
27
+
28
+ # load all i18n strings
29
+ string_search = File.join( Ops::root_dir, "res", "strings/**/*.yml" )
30
+ string_files = Dir[ string_search ]
31
+ I18n.load_path << string_files
@@ -0,0 +1,136 @@
1
+ module Host
2
+ class Default
3
+
4
+ attr_reader :alias, :host_name, :ssh_pem, :user, :tags
5
+
6
+ def initialize( host = 'unspecified', info = {}, opts = {} )
7
+ @alias = host
8
+
9
+ @host_name = info[ "HostName" ] || nil
10
+ @user = info[ "User" ] || Etc.getlogin
11
+ @ssh_pem = info[ "IdentityFile" ] || nil
12
+ @ssh_port = info[ "Port" ] || nil
13
+ @type = info[ "Type" ] || :default
14
+ @tags = info[ "Tags" ] || {}
15
+ @pem_dirs = opts[ "IdentityLocations" ] || nil
16
+ end
17
+
18
+ def type
19
+ @type.to_sym
20
+ end
21
+
22
+ def tags=( tags )
23
+ raise IOError, "tags must be a hash" unless tags.kind_of?( Hash )
24
+ @tags = tags
25
+ end
26
+
27
+ def matches?( tags )
28
+ tags.each do | tag, value |
29
+ is_regex = value.match( /^\/(.*)\/$/ )
30
+
31
+ if is_regex
32
+ regex = Regexp.new( is_regex[ 1 ] )
33
+
34
+ unless @tags.has_key?( tag ) && @tags[ tag ].match( regex )
35
+ return false
36
+ end
37
+ else
38
+ unless @tags.has_key?( tag ) && @tags[ tag ] == value
39
+ return false
40
+ end
41
+ end
42
+ end
43
+
44
+ true
45
+ end
46
+
47
+ def ssh_pem
48
+ ssh_pem = nil
49
+
50
+ unless @ssh_pem.nil?
51
+ unless @pem_dirs.nil?
52
+ @pem_dirs.each do | dir |
53
+ f = File.expand_path File.join( dir, "#{ @ssh_pem }*" )
54
+ glob = Dir.glob( f )
55
+ ssh_pem = glob.first unless glob.empty?
56
+ end
57
+ end
58
+
59
+ raise( IOError,
60
+ "Error: pem - #{ ssh_pem } not found or not accessable." ) unless
61
+ File.stat( ssh_pem )
62
+ end
63
+
64
+ ssh_pem
65
+ end
66
+
67
+ def shell!( opts = nil )
68
+ ssh_cmd = [ "ssh" ]
69
+
70
+ raise( IOError, "Error: HostName invalid." ) if @host_name.nil?
71
+
72
+ ssh_cmd << [ "-l", @user ]
73
+ ssh_cmd << @host_name
74
+
75
+ pem = ssh_pem
76
+ ssh_cmd << [ "-i", pem ] unless pem.nil?
77
+
78
+ begin
79
+ exec( ssh_cmd.join(" ") )
80
+ rescue => e
81
+ raise( IOError, "Could not call ssh." )
82
+ end
83
+ end
84
+
85
+ def shell_exec!( command, opts = {} )
86
+ ssh_pem
87
+
88
+ options = { :keys => ssh_pem }
89
+
90
+ color = Color.random_color
91
+
92
+ begin
93
+ Net::SSH.start( host_name, user, options ) do | s |
94
+
95
+ channel = s.open_channel do |ch|
96
+ channel.request_pty do |ch, success|
97
+ if success
98
+ puts "pty successfully obtained"
99
+ else
100
+ puts "could not obtain pty"
101
+ end
102
+ end if opts.has_key? :pty
103
+
104
+ ch.exec( command ) do | ch, success |
105
+ raise( IOError,
106
+ "#{ host_name } > could not execute command" ) unless
107
+ success
108
+
109
+ ch.on_data do | c, data |
110
+ data.split("\n").each do | line |
111
+ puts "#{ Color.print(
112
+ self.alias, [ :bold, color ] ) } > #{ line }"
113
+ end
114
+ end
115
+
116
+ ch.on_extended_data do |c, type, data|
117
+ data.split("\n").each do | line |
118
+ puts "#{ Color.print(
119
+ self.alias, [ :bold, color ] ) } > #{ line }"
120
+ end
121
+ end
122
+
123
+ ch.on_close do
124
+ puts "#{ Color.print(
125
+ self.alias, [ :bold, color ] ) } > COMMAND finished"
126
+ end
127
+
128
+ end
129
+ end
130
+ end
131
+ rescue => e
132
+ puts "Error: #{ self.alias } > #{ e.message }".error
133
+ end
134
+ end
135
+ end
136
+ end
data/lib/host/e_c_2.rb ADDED
@@ -0,0 +1,11 @@
1
+ module Host
2
+ class EC2 < Host::Default
3
+
4
+ attr_reader :alias
5
+
6
+ def initialize( host = 'unspecified', info = {}, opts = {} )
7
+ super
8
+ @type = info[ "Type" ] || :ec2
9
+ end
10
+ end
11
+ end
data/lib/host/list.rb ADDED
@@ -0,0 +1,11 @@
1
+ module Host
2
+
3
+ class List < Array
4
+
5
+ def filter( tags )
6
+ self.select do | i |
7
+ i.matches? tags
8
+ end
9
+ end
10
+ end
11
+ end
data/lib/ops/common.rb ADDED
@@ -0,0 +1,55 @@
1
+ module Ops
2
+
3
+ def self.root_dir
4
+ File.expand_path(
5
+ File.join( File.dirname( __FILE__ ), "..", ".." ) )
6
+ end
7
+
8
+ def self.pwd_dir
9
+ Pathname.new( Dir.pwd ).ascend do | p |
10
+ return p if File.exists? File.join( p, 'config.json' )
11
+ end
12
+ nil
13
+ end
14
+
15
+ def self.has_bash?
16
+ `which bash`
17
+ ( $? == 0 ) ? true : false
18
+ end
19
+
20
+ def self.read_config
21
+ config_file = File.join( self.pwd_dir, "config.json" )
22
+
23
+ begin
24
+ config = JSON.parse File.read( config_file )
25
+ rescue JSON::ParserError
26
+ raise IOError, "Error parsing config file: #{ config_file }."
27
+ end
28
+ end
29
+
30
+ def self.read_hosts
31
+ config = read_config
32
+
33
+ hosts = {}
34
+
35
+ hosts_files = [
36
+ File.join( self.pwd_dir, "hosts.json" ),
37
+ File.join( self.pwd_dir, 'tmp' ,"hosts.json" ), ]
38
+
39
+ hosts_files.each do | file |
40
+ if File.exists? file
41
+ begin
42
+ json = JSON.parse File.read( file )
43
+ json.each do | n, i |
44
+ hosts[ n ] = Host::Default.new( n, i, config )
45
+ end
46
+ rescue JSON::ParserError => e
47
+ raise( IOError,
48
+ "Error parsing hosts file: #{ file }. #{ e.message }" )
49
+ end
50
+ end
51
+ end
52
+
53
+ hosts
54
+ end
55
+ end
@@ -0,0 +1,57 @@
1
+ module Ops
2
+ module Console
3
+ OPTIONS = { :bold => 1, :underline => 4 }
4
+
5
+ COLORS = { :black => 30,
6
+ :red => 31, :green => 32, :yellow => 33, :blue => 34,
7
+ :magenta => 35, :cyan => 36, :white => 37 }
8
+
9
+ BG_COLORS = { :black => 40, :red => 41, :green => 42,
10
+ :yellow => 43, :blue => 44, :magenta => 45, :cyan => 46,
11
+ :white => 47 }
12
+
13
+ def self.reload!
14
+
15
+ end
16
+
17
+ def self.is_bash?
18
+ `which bash`
19
+ ( $? == 0 ) ? true : false
20
+ end
21
+
22
+ def self.bash_exec!( cmd )
23
+ bash = `which bash`.strip
24
+ `#{ bash } -c #{ cmd }"`
25
+ end
26
+
27
+ def print( string, opts = [] )
28
+ c = []
29
+ opts.each { | o | c << COLORS[ o ] if COLORS.has_key?( o ) }
30
+ opts.each { | o | c << OPTIONS[ o ] if OPTIONS.has_key?( o ) }
31
+
32
+ "\033[#{ c.join( ";" ) }m#{ string }\033[0m"
33
+ end
34
+
35
+ def random_color
36
+ colors = COLORS.keys + BG_COLORS.keys
37
+ colors.reject!{ | c | [ :white, :black ].include? c }
38
+ colors.sample
39
+ end
40
+ end
41
+ end
42
+
43
+ class Color
44
+ extend Ops::Console
45
+ end
46
+
47
+ class String
48
+ extend Ops::Console
49
+
50
+ def error
51
+ replace Color.print( self , [ :bold, :red ] )
52
+ end
53
+
54
+ def warning
55
+ replace Color.print( self , [ :bold, :yellow ] )
56
+ end
57
+ end
data/lib/tasks/ec2.rb ADDED
@@ -0,0 +1,50 @@
1
+ namespace "hosts" do
2
+
3
+ namespace "ec2" do
4
+
5
+ ## Sync EC2 Hosts
6
+ desc "hosts.sync"
7
+ task "sync" do
8
+ ec2 = AWS::EC2.new(
9
+ :access_key_id => $config[ "AWS" ][ "AccessKeyId" ],
10
+ :secret_access_key => $config[ "AWS" ][ "SecretAccessKey" ] )
11
+
12
+ hosts = {}
13
+
14
+ # used if no name is given
15
+ count = 0
16
+
17
+ ec2.instances.each do | h |
18
+ name = h.tags[ "Name" ]
19
+
20
+ if name.nil? || name.empty?
21
+ name = "noname-#{ count }"
22
+ count += 1
23
+ end
24
+
25
+ ip = h.dns_name || "stopped"
26
+
27
+ puts "Discovered: #{ name } -> #{ ip }"
28
+
29
+ hosts[ name ] = {
30
+ "HostName" => ip,
31
+ "User" => h.tags[ "User" ],
32
+ "IdentityFile" => h.key_name,
33
+ "Tags" => h.tags.to_h.to_hash,
34
+ "Type" => "EC2" }
35
+ end
36
+
37
+ tmp_dir = File.join( Ops::pwd_dir, 'tmp' )
38
+ Dir.mkdir( tmp_dir ) unless File.directory? tmp_dir
39
+
40
+ host_file = File.join( tmp_dir, 'hosts.json' )
41
+ File.open( host_file, 'w' ) { | f | f.write( hosts.to_json ) }
42
+
43
+ if Ops::has_bash?
44
+ bash = `which bash`.strip
45
+ `#{ bash } -c "source #{
46
+ File.join( Ops::root_dir, 'autocomplete' ) }"`
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,61 @@
1
+ namespace "hosts" do
2
+
3
+ desc I18n.t( "hosts.list.desc" )
4
+ task "list" do
5
+ hosts = Ops::read_hosts
6
+ hosts.each do | i, h |
7
+ puts "#{ h.alias }"
8
+ end
9
+ end
10
+
11
+ desc I18n.t( "hosts.add.desc" )
12
+ task "add" do
13
+ required = [ 'hostname', 'host', 'user' ]
14
+
15
+ required.each do | p |
16
+ fail I18n.t( "hosts.add.no_#{ p }" ) if ENV[ p ].nil? ||
17
+ ENV[ p ].empty?
18
+ end
19
+
20
+ hostname = ENV[ 'hostname' ]
21
+ host = ENV[ 'host' ]
22
+ user = ENV[ 'user' ]
23
+ type = ENV[ 'type' ] || "default"
24
+ identity = nil
25
+ tags = {}
26
+
27
+ unless ENV[ 'identity' ].nil?
28
+ identity = File.basename( ENV[ 'identity' ] )
29
+ end
30
+
31
+ unless ENV[ 'tags' ].nil?
32
+ tags = File.basename( ENV[ 'tags' ] )
33
+ tags = JSON.parse( tags )
34
+ end
35
+
36
+
37
+ puts "Adding host: #{ host }"
38
+ puts " => #{ hostname }"
39
+ puts " => using #{ identity }" unless identity.nil?
40
+
41
+ hosts = {}
42
+ hosts_file = File.join( pwd, "hosts.json" )
43
+
44
+ if File.exists? hosts_file
45
+ hosts = JSON.parse( File.read( hosts_file ) )
46
+ end
47
+
48
+ exit_failure( "Error: #{ host } is already defined" ) if
49
+ hosts.has_key? host
50
+
51
+ hosts[ host ] = {
52
+ 'HostName' => hostname,
53
+ 'User' => user,
54
+ 'IdentityFile' => identity,
55
+ "Type" => "type",
56
+ "Tags" => tags
57
+ }
58
+
59
+ File.open( hosts_file, 'w' ) { | f | f.write( hosts.to_json ) }
60
+ end
61
+ end
data/lib/tasks/init.rb ADDED
@@ -0,0 +1,4 @@
1
+ require 'tasks/ops.rb'
2
+ require 'tasks/hosts.rb'
3
+ require 'tasks/ec2.rb'
4
+ require 'tasks/ssh.rb'
data/lib/tasks/ops.rb ADDED
@@ -0,0 +1,32 @@
1
+ task "default" do
2
+ puts "run ops -T for a full list of commands"
3
+ end
4
+
5
+ desc I18n.t( "ops.version.desc" )
6
+ task "version" do
7
+ puts "Version: #{ Ops.version }"
8
+ end
9
+
10
+ ## Project Initialization
11
+
12
+ desc I18n.t( "ops.init.desc" )
13
+ task "init" do
14
+
15
+ name = ENV[ 'name' ]
16
+ fail I18n.t( "ops.init.no_name" ) if name.nil? || name.empty?
17
+
18
+ FileUtils.cp_r( File.join( Ops::root_dir, "res", "samples", "default" ),
19
+ File.join( Ops::pwd_dir, name ) )
20
+ end
21
+
22
+ begin
23
+ $hosts = Ops::read_hosts
24
+ rescue
25
+ $hosts = {}
26
+ end
27
+
28
+ begin
29
+ $config = Ops::read_config
30
+ rescue
31
+ $config = {}
32
+ end
data/lib/tasks/ssh.rb ADDED
@@ -0,0 +1,22 @@
1
+ namespace "hosts" do
2
+
3
+ $hosts.each do | i, host |
4
+
5
+ namespace host.alias do
6
+
7
+ desc I18n.t( "host.ssh", :host => host.alias )
8
+ task "ssh" do
9
+ host.shell!
10
+ end
11
+
12
+ desc "Execute a command over ssh"
13
+ task "ssh:exec" do
14
+ command = ENV[ "command" ]
15
+ raise IOError, "Command not specified" if command.nil? ||
16
+ command.empty?
17
+
18
+ host.shell_exec! command
19
+ end
20
+ end
21
+ end
22
+ end
data/lib/version.rb ADDED
@@ -0,0 +1,6 @@
1
+ module Ops
2
+
3
+ def self.version
4
+ "0.0.8"
5
+ end
6
+ end
data/pkg/.gitfile ADDED
File without changes
@@ -0,0 +1,7 @@
1
+ {
2
+ "IdentityLocations" : [ "~/.ssh" ],
3
+ "AWS" : {
4
+ "AccessKeyId" : "",
5
+ "SecretAccessKey" : ""
6
+ }
7
+ }
@@ -0,0 +1,14 @@
1
+ en:
2
+ messages:
3
+ reload_bash: "To have autocompletion for new/modified hosts reload
4
+ your bash profile/configs. Use `$ source [ location to
5
+ .bashrc or .bash_profile ]` on most machines."
6
+ ops:
7
+ init:
8
+ desc: "Initialize a new project"
9
+ no_name: "project name not provided"
10
+ version:
11
+ desc: "Print version number"
12
+
13
+ host:
14
+ ssh: "SSH into %{host}"
@@ -0,0 +1,15 @@
1
+ en:
2
+ hosts:
3
+
4
+ list:
5
+ desc: "List all hosts form hosts config file."
6
+
7
+ sync:
8
+ desc: "Syncronize local hosts file with instances from EC2."
9
+ in_progress: "Syncing hosts.json with EC2..."
10
+
11
+ add:
12
+ desc: "Add a host to the hosts file"
13
+ no_hostname: "No hostname was provided."
14
+ no_host: "No host was provided."
15
+ no_user: "No use was provided."
@@ -0,0 +1,32 @@
1
+ require 'spec_helper'
2
+
3
+ describe Host::Default do
4
+
5
+ context "with tags" do
6
+
7
+ before :each do
8
+ @host = Host::Default.new
9
+ end
10
+
11
+ it "should allow you to add tags" do
12
+ @host.tags = { "Platform" => "Windows" }
13
+ end
14
+
15
+ describe ".matches?" do
16
+
17
+ before :each do
18
+ @host.tags = { "Platform" => "Windows" }
19
+ end
20
+
21
+ it "should return true if all tags match" do
22
+ @host.matches?( { "Platform" => "Windows" } ).should == true
23
+ end
24
+
25
+ it "should return true if all tags match" do
26
+ @host.matches?( {
27
+ "Platform" => "Windows",
28
+ "Role" => "Worker" } ).should == false
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe Host::List do
4
+
5
+ before :each do
6
+ @list = Host::List.new
7
+ end
8
+
9
+ it "should be an extenstion of the array class" do
10
+ @list.kind_of?( Array ).should == true
11
+ end
12
+
13
+ describe ".filter" do
14
+
15
+ before :each do
16
+ @host = Host::Default.new( "host1" )
17
+ @host.tags = { "Platform" => "Windows" }
18
+ @list << @host
19
+ end
20
+
21
+ it "should iterate through the items and call .matches?" do
22
+ @host.should_receive( :matches? )
23
+ @list.filter( { "Platform" => "Windows" } )
24
+ end
25
+
26
+ it "should return the matched host" do
27
+ hosts = @list.filter( { "Platform" => "Windows" } )
28
+ hosts.length.should == 1
29
+ end
30
+
31
+ it "should return a empty list" do
32
+ hosts = @list.filter( { "Platform" => "Linux" } )
33
+ hosts.length.should == 0
34
+ end
35
+ end
36
+ end
@@ -0,0 +1 @@
1
+ require 'ops.rb'
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: devops
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.8
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Hardeep Shoker
9
+ - Ryan Willoughby
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2013-05-06 00:00:00.000000000 Z
14
+ dependencies: []
15
+ description: Ops tool for remote servers
16
+ email: hardeepshoker@gmail.com
17
+ executables:
18
+ - ops
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - .gitignore
23
+ - .rspec
24
+ - Gemfile
25
+ - Gemfile.lock
26
+ - README.md
27
+ - autocomplete
28
+ - bin/ops
29
+ - devops.gemspec
30
+ - lib/devops.rb
31
+ - lib/host/default.rb
32
+ - lib/host/e_c_2.rb
33
+ - lib/host/list.rb
34
+ - lib/ops/common.rb
35
+ - lib/ops/console.rb
36
+ - lib/tasks/ec2.rb
37
+ - lib/tasks/hosts.rb
38
+ - lib/tasks/init.rb
39
+ - lib/tasks/ops.rb
40
+ - lib/tasks/ssh.rb
41
+ - lib/version.rb
42
+ - pkg/.gitfile
43
+ - res/samples/default/config.json
44
+ - res/strings/strings.yml
45
+ - res/strings/tasks/hosts.yml
46
+ - spec/lib/host/default_spec.rb
47
+ - spec/lib/host/list_spec.rb
48
+ - spec/spec_helper.rb
49
+ homepage: https://github.com/hardeep/ops
50
+ licenses: []
51
+ post_install_message:
52
+ rdoc_options: []
53
+ require_paths:
54
+ - lib
55
+ required_ruby_version: !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ! '>='
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ required_rubygems_version: !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ! '>='
65
+ - !ruby/object:Gem::Version
66
+ version: '0'
67
+ requirements: []
68
+ rubyforge_project:
69
+ rubygems_version: 1.8.23
70
+ signing_key:
71
+ specification_version: 3
72
+ summary: Ops tool for remote servers
73
+ test_files: []