awspec 0.0.1

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: c7cdec523d2ed0c3f17c1fe819f9ec63907135d7
4
+ data.tar.gz: 8a56f108f5fd80304b1c7f2d12cd14992cf0ebd7
5
+ SHA512:
6
+ metadata.gz: 5f22da57b3c932b9e98ab55e6a07db11346c45ba90e126e72a411a81d0d315eb424b49502e453b8a77b2d19cf639bac380b7eef610a91b7c095ff2beca1d2cc5
7
+ data.tar.gz: 74de2a12f8a98ab7fc1f4409d86972e36611e781be22db161caddc0cf99becd3f3c195b1f7cc594b22167dc5302bd5e8e129521440f134c40fb6a63c87e92500
@@ -0,0 +1,13 @@
1
+ root = ture
2
+
3
+ [*]
4
+ end_of_line = lf
5
+ insert_final_newline = true
6
+ charset = utf-8
7
+
8
+ [*.rb]
9
+ indent_style = space
10
+ indent_size = 2
11
+ trim_trailing_whitespace = true
12
+ insert_final_newline = false
13
+ trim_traling_whitespace = true
@@ -0,0 +1,10 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ /spec/secrets.yml
@@ -0,0 +1,50 @@
1
+ Lint/Eval:
2
+ Enabled: false
3
+
4
+ Lint/HandleExceptions:
5
+ Enabled: false
6
+
7
+ Lint/UselessAssignment:
8
+ Enabled: false
9
+
10
+ Metrics/AbcSize:
11
+ Max: 50
12
+
13
+ Metrics/ClassLength:
14
+ Max: 120
15
+
16
+ Metrics/CyclomaticComplexity:
17
+ Max: 15
18
+
19
+ Metrics/LineLength:
20
+ Max: 120
21
+
22
+ Metrics/MethodLength:
23
+ Max: 30
24
+
25
+ Metrics/PerceivedComplexity:
26
+ Max: 15
27
+
28
+ Style/BarePercentLiterals:
29
+ Enabled: false
30
+
31
+ Style/ClassAndModuleChildren:
32
+ Enabled: false
33
+
34
+ Style/Documentation:
35
+ Enabled: false
36
+
37
+ Style/PercentLiteralDelimiters:
38
+ Enabled: false
39
+
40
+ Style/PredicateName:
41
+ Enabled: false
42
+
43
+ Style/RedundantSelf:
44
+ Enabled: false
45
+
46
+ Style/SymbolProc:
47
+ Enabled: false
48
+
49
+ Style/BracesAroundHashParameters:
50
+ Enabled: false
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.6
4
+ - 2.2.1
5
+
6
+ before_install:
7
+ - gem update bundler
8
+
9
+ script:
10
+ - bundle exec rake spec
11
+ - bundle exec rubocop
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in awspec.gemspec
4
+ gemspec
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 Ken'ichiro Oyama
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,68 @@
1
+ # awspec [![Build Status](https://travis-ci.org/k1LoW/awspec.svg?branch=master)](https://travis-ci.org/k1LoW/awspec)
2
+
3
+ RSpec tests for your AWS resources.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'awspec'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install awspec
20
+
21
+ ## Usage
22
+
23
+ ### 1. Generate awspec template
24
+
25
+ $ awspec init
26
+
27
+ ### 2. Write *_spec.rb
28
+
29
+ ```ruby
30
+ describe ec2('i-ec12345a') do
31
+ it { should be_running }
32
+ its(:instance_id) { should eq 'i-ec12345a' }
33
+ its(:image_id) { should eq 'ami-abc12def' }
34
+ its(:public_ip_address) { should eq '123.0.456.789' }
35
+ it { should have_security_group('my-security-group-name') }
36
+ it { should belong_to_vpc('my-vpc') }
37
+ it { should belong_to_subnet('subnet-1234a567') }
38
+ it { should have_eip('123.0.456.789') }
39
+ end
40
+ ```
41
+
42
+ ## Support AWS Resources
43
+
44
+ - [X] EC2
45
+ - [X] RDS
46
+ - [ ] RDS DB Parameter
47
+ - [X] Security Group
48
+ - [X] VPC
49
+
50
+ ### Next..
51
+
52
+ - [ ] S3
53
+ - [ ] Route53
54
+ - ...
55
+
56
+ ## Contributing
57
+
58
+ 1. Fork it ( https://github.com/k1LoW/awspec/fork )
59
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
60
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
61
+ 4. Push to the branch (`git push origin my-new-feature`)
62
+ 5. Create a new Pull Request
63
+
64
+ ## References
65
+
66
+ - Original idea (code / architecture) -> [Serverspec](https://github.com/serverspec/serverspec)
67
+ - awspec original concept -> https://github.com/marcy-terui/awspec
68
+ - [Serverspec book](http://www.oreilly.co.jp/books/9784873117096/)
@@ -0,0 +1,16 @@
1
+ require 'bundler/gem_tasks'
2
+ begin
3
+ require 'rspec/core/rake_task'
4
+ rescue LoadError
5
+ end
6
+
7
+ if defined?(RSpec)
8
+ task spec: 'spec:all'
9
+ namespace :spec do
10
+ task all: ['spec:type']
11
+
12
+ RSpec::Core::RakeTask.new(:type) do |t|
13
+ t.pattern = 'spec/type/*_spec.rb'
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'awspec/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'awspec'
8
+ spec.version = Awspec::VERSION
9
+ spec.authors = ['k1LoW']
10
+ spec.email = ['k1lowxb@gmail.com']
11
+
12
+ spec.summary = 'RSpec tests for your AWS resources.'
13
+ spec.description = 'RSpec tests for your AWS resources.'
14
+ spec.homepage = 'https://github.com/k1LoW/awspec'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = 'exe'
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ['lib']
21
+
22
+ spec.add_runtime_dependency 'rspec', '~> 3.0'
23
+ spec.add_runtime_dependency 'rspec-its'
24
+ spec.add_runtime_dependency 'aws-sdk', '~> 2'
25
+ spec.add_runtime_dependency 'thor'
26
+ spec.add_development_dependency 'bundler', '~> 1.9'
27
+ spec.add_development_dependency 'rake', '~> 10.0'
28
+ spec.add_development_dependency 'rubocop'
29
+ end
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'awspec'
4
+
5
+ Awspec::CLI.start
@@ -0,0 +1,11 @@
1
+ require 'rubygems'
2
+ require 'rspec'
3
+ require 'rspec/its'
4
+ require 'awspec/version'
5
+ require 'awspec/cli'
6
+ require 'awspec/matcher'
7
+ require 'awspec/helper'
8
+ require 'awspec/ext/string'
9
+
10
+ module Awspec
11
+ end
@@ -0,0 +1,11 @@
1
+ require 'thor'
2
+ require 'awspec/setup'
3
+
4
+ module Awspec
5
+ class CLI < Thor
6
+ desc 'awspec init', 'Generate awspec spec_helper.rb'
7
+ def init
8
+ Awspec::Setup.run
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,14 @@
1
+ class String
2
+ def to_snake_case
3
+ self.gsub(/::/, '/')
4
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
5
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
6
+ .tr('-', '_')
7
+ .downcase
8
+ end
9
+
10
+ def to_camel_case
11
+ return self if self !~ /_/ && self =~ /[A-Z]+.*/
12
+ split('_').map { |e| e.capitalize }.join
13
+ end
14
+ end
@@ -0,0 +1,6 @@
1
+ require 'awspec/helper/type'
2
+ extend Awspec::Helper::Type
3
+ class RSpec::Core::ExampleGroup
4
+ extend Awspec::Helper::Type
5
+ include Awspec::Helper::Type
6
+ end
@@ -0,0 +1,18 @@
1
+ module Awspec
2
+ module Helper
3
+ module Type
4
+ types = %w(
5
+ base ec2 rds security_group vpc
6
+ )
7
+
8
+ types.each { |type| require "awspec/type/#{type}" }
9
+
10
+ types.each do |type|
11
+ define_method type do |*args|
12
+ name = args.first
13
+ eval "Awspec::Type::#{type.to_camel_case}.new(name)"
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,9 @@
1
+ # EC2
2
+ require 'awspec/matcher/belong_to_vpc'
3
+ require 'awspec/matcher/belong_to_subnet'
4
+
5
+ # RDS
6
+ require 'awspec/matcher/belong_to_db_subnet_group'
7
+
8
+ # SecurityGroup
9
+ require 'awspec/matcher/be_opened'
@@ -0,0 +1,17 @@
1
+ RSpec::Matchers.define :be_opened do |port|
2
+ match do |sg|
3
+ sg.opened?(port, @protocol, @cidr)
4
+ end
5
+
6
+ chain :protocol do |protocol|
7
+ @protocol = protocol
8
+ end
9
+
10
+ chain :for do |cidr|
11
+ @cidr = cidr
12
+ end
13
+
14
+ chain :target do |cidr|
15
+ @cidr = cidr
16
+ end
17
+ end
@@ -0,0 +1,5 @@
1
+ RSpec::Matchers.define :belong_to_db_subnet_group do |db_subnet_group_name|
2
+ match do |resource|
3
+ return true if resource.instance[:db_subnet_group][:db_subnet_group_name] == db_subnet_group_name
4
+ end
5
+ end
@@ -0,0 +1,33 @@
1
+ RSpec::Matchers.define :belong_to_subnet do |subnet_id|
2
+ match do |resource|
3
+ # EC2
4
+ if resource.instance_of?(Awspec::Type::Ec2)
5
+ return true if resource.subnet_id == subnet_id
6
+ ret = resource.client.describe_subnets({
7
+ filters: [{ name: 'tag:Name', values: [subnet_id] }]
8
+ })
9
+ return false unless ret
10
+ return ret[:subnets][0][:subnet_id] == resource.subnet_id
11
+ end
12
+
13
+ # RDS
14
+ if resource.instance_of?(Awspec::Type::Rds)
15
+ subnets = resource.instance[:db_subnet_group][:subnets]
16
+ ret = subnets.find do |subnet|
17
+ subnet[:subnet_identifier] == subnet_id
18
+ end
19
+
20
+ return ret[:subnet_availability_zone][:name] == resource.availability_zone if ret
21
+
22
+ res = resource.ec2_client.describe_subnets({
23
+ filters: [{ name: 'tag:Name', values: [subnet_id] }]
24
+ })
25
+ return false unless res
26
+ ret = subnets.find do |subnet|
27
+ subnet[:subnet_identifier] == res[:subnets][0][:subnet_id]
28
+ end
29
+
30
+ return ret[:subnet_availability_zone][:name] == resource.availability_zone if ret
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,8 @@
1
+ RSpec::Matchers.define :belong_to_vpc do |vpc_id|
2
+ match do |resource|
3
+ return true if resource.vpc_id == vpc_id
4
+ ret = resource.find_vpc(vpc_id)
5
+ return false unless ret
6
+ ret[:vpc_id] == resource.vpc_id
7
+ end
8
+ end
@@ -0,0 +1,75 @@
1
+ require 'fileutils'
2
+
3
+ module Awspec
4
+ class Setup
5
+ def self.run
6
+ generate_spec_helper
7
+ generate_rakefile
8
+ generate_dotgitignore
9
+ end
10
+
11
+ def self.generate_spec_helper
12
+ content = <<-'EOF'
13
+ require 'awspec'
14
+ if File.exist?('secrets.yml')
15
+ creds = YAML.load_file('secrets.yml')
16
+ Aws.config.update({
17
+ region: creds['region'],
18
+ credentials: Aws::Credentials.new(
19
+ creds['aws_access_key_id'],
20
+ creds['aws_secret_access_key'])
21
+ })
22
+ end
23
+ EOF
24
+ dir = 'spec'
25
+ if File.exist? dir
26
+ unless File.directory? dir
27
+ $stderr.puts '!! #{dir} already exists and is not a directory'
28
+ end
29
+ else
30
+ FileUtils.mkdir dir
31
+ puts ' + #{dir}/'
32
+ end
33
+
34
+ if File.exist? 'spec/spec_helper.rb'
35
+ $stderr.puts '!! spec/spec_helper.rb already exists'
36
+ else
37
+ File.open('spec/spec_helper.rb', 'w') do |f|
38
+ f.puts content
39
+ end
40
+ puts ' + spec/spec_helper.rb'
41
+ end
42
+ end
43
+
44
+ def self.generate_rakefile
45
+ content = <<-'EOF'
46
+ require 'rspec/core/rake_task'
47
+ RSpec::Core::RakeTask.new('spec')
48
+ task :default => :spec
49
+ EOF
50
+
51
+ if File.exist? 'Rakefile'
52
+ $stderr.puts '!! Rakefile already exists'
53
+ else
54
+ File.open('Rakefile', 'w') do |f|
55
+ f.puts content
56
+ end
57
+ puts ' + Rakefile'
58
+ end
59
+ end
60
+
61
+ def self.generate_dotgitignore
62
+ content = <<-'EOF'
63
+ secrets.yml
64
+ EOF
65
+ if File.exist? 'spec/.gitignore'
66
+ $stderr.puts '!! spec/.gitignore already exists'
67
+ else
68
+ File.open('spec/.gitignore', 'w') do |f|
69
+ f.puts content
70
+ end
71
+ puts ' + spec/.gitignore'
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,63 @@
1
+ require 'aws-sdk'
2
+
3
+ module Awspec::Type
4
+ class Base
5
+ attr_reader :id, :ec2_client
6
+
7
+ def initialize(id = nil)
8
+ @tmp = id
9
+ @ec2_client = Aws::EC2::Client.new
10
+ end
11
+
12
+ def find_vpc(id)
13
+ res = @ec2_client.describe_vpcs({
14
+ filters: [{ name: 'vpc-id', values: [id] }]
15
+ })
16
+ return res[:vpcs][0] if res[:vpcs].count == 1
17
+ res = @ec2_client.describe_vpcs({
18
+ filters: [{ name: 'tag:Name', values: [id] }]
19
+ })
20
+ return res[:vpcs][0] if res[:vpcs].count == 1
21
+ end
22
+
23
+ def find_route_table(id)
24
+ res = @ec2_client.describe_route_tables({
25
+ filters: [{ name: 'route-table-id', values: [id] }]
26
+ })
27
+ return res[:route_tables][0] if res[:route_tables].count == 1
28
+ res = @ec2_client.describe_route_tables({
29
+ filters: [{ name: 'tag:Name', values: [id] }]
30
+ })
31
+ return res[:route_tables][0] if res[:route_tables].count == 1
32
+ end
33
+
34
+ def find_network_acl(id)
35
+ res = @ec2_client.describe_network_acls({
36
+ filters: [{ name: 'network-acl-id', values: [id] }]
37
+ })
38
+ return res[:network_acls][0] if res[:network_acls].count == 1
39
+ res = @ec2_client.describe_network_acls({
40
+ filters: [{ name: 'tag:Name', values: [id] }]
41
+ })
42
+ return res[:network_acls][0] if res[:network_acls].count == 1
43
+ end
44
+
45
+ def find_security_group(id)
46
+ res = @ec2_client.describe_security_groups({
47
+ filters: [{ name: 'group-id', values: [id] }]
48
+ })
49
+
50
+ return res[:security_groups][0] if res[:security_groups].count == 1
51
+ res = @ec2_client.describe_security_groups({
52
+ filters: [{ name: 'group-name', values: [id] }]
53
+ })
54
+
55
+ return res[:security_groups][0] if res[:security_groups].count == 1
56
+ res = @ec2_client.describe_security_groups({
57
+ filters: [{ name: 'tag:Name', values: [id] }]
58
+ })
59
+
60
+ return res[:security_groups][0] if res[:security_groups].count == 1
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,90 @@
1
+ module Awspec::Type
2
+ class Ec2 < Base
3
+ attr_reader :client, :instance
4
+
5
+ def initialize(id)
6
+ super
7
+ @client = @ec2_client
8
+ if id.is_a?(Array)
9
+ # Aws::EC2::Client.describe_instances native filters format
10
+ res = @client.describe_instances({
11
+ filters: id
12
+ })
13
+ elsif id.is_a?(Hash)
14
+ # syntax sugar
15
+ filters = []
16
+ id.each do |k, v|
17
+ filters.push({ name: k, values: Array(v) })
18
+ end
19
+ res = @client.describe_instances({
20
+ filters: filters
21
+ })
22
+ else
23
+ # instance_id or tag:Name
24
+ begin
25
+ res = @client.describe_instances({
26
+ instance_ids: [id]
27
+ })
28
+ rescue
29
+ # Aws::EC2::Errors::InvalidInstanceIDMalformed
30
+ # Aws::EC2::Errors::InvalidInstanceIDNotFound
31
+ res = @client.describe_instances({
32
+ filters: [{ name: 'tag:Name', values: [id] }]
33
+ })
34
+ end
35
+ end
36
+ @id = res[:reservations][0][:instances][0][:instance_id]
37
+ @instance = res[:reservations][0][:instances][0]
38
+ end
39
+
40
+ states = %w(
41
+ pending running shutting-down
42
+ terminated stopping stopped
43
+ )
44
+
45
+ states.each do |state|
46
+ define_method state + '?' do
47
+ @instance[:state][:name] == state
48
+ end
49
+ end
50
+
51
+ describes = %w(
52
+ instance_id image_id state private_dns_name public_dns_name
53
+ state_transition_reason key_name ami_launch_index product_codes
54
+ instance_type launch_time placement kernel_id ramdisk_id platform
55
+ monitoring subnet_id vpc_id private_ip_address public_ip_address
56
+ state_reason architecture root_device_type root_device_name
57
+ block_device_mappings virtualization_type instance_lifecycle
58
+ spot_instance_request_id client_token tags security_groups
59
+ source_dest_check hypervisor network_interfaces
60
+ iam_instance_profile ebs_optimized sriov_net_support
61
+ )
62
+
63
+ describes.each do |describe|
64
+ define_method describe do
65
+ @instance[describe]
66
+ end
67
+ end
68
+
69
+ def has_eip?(ip_address = nil)
70
+ option = {
71
+ filters: [{ name: 'instance-id', values: [@id] }]
72
+ }
73
+ option[:public_ips] = [ip_address] if ip_address
74
+ ret = @client.describe_addresses(option)
75
+ ret[:addresses].count == 1
76
+ end
77
+
78
+ def has_security_group?(sg_id)
79
+ sgs = @instance[:security_groups]
80
+ ret = sgs.find do |sg|
81
+ sg[:group_id] == sg_id || sg[:group_name] == sg_id
82
+ end
83
+ return true if ret
84
+ sg2 = find_security_group(sg_id)
85
+ sg2[:tags].find do |tag|
86
+ tag[:key] == 'Name' && tag[:value] == sg_id
87
+ end
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,115 @@
1
+ module Awspec::Type
2
+ class Rds < Base
3
+ attr_reader :client, :instance
4
+
5
+ def initialize(id)
6
+ super
7
+ @client = Aws::RDS::Client.new
8
+ # db_instance_identifier
9
+ res = @client.describe_db_instances({
10
+ db_instance_identifier: id
11
+ })
12
+ @id = res[:db_instances][0][:db_instance_identifier]
13
+ @instance = res[:db_instances][0]
14
+ end
15
+
16
+ states = %w(
17
+ available backing-up creating deleting
18
+ failed inaccessible-encryption-credentials
19
+ incompatible-credentials incompatible-network
20
+ incompatible-option-group incompatible-parameters
21
+ incompatible-restore maintenance
22
+ modifying rebooting renaming resetting-master-credentials
23
+ restore-error storage-full upgrading
24
+ )
25
+
26
+ states.each do |state|
27
+ define_method state + '?' do
28
+ @instance[:db_instance_status] == state
29
+ end
30
+ end
31
+
32
+ describes = %w(
33
+ db_instance_identifier db_instance_class engine db_instance_status
34
+ master_username db_name endpoint allocated_storage instance_create_time
35
+ preferred_backup_window backup_retention_period db_security_groups
36
+ vpc_security_groups db_parameter_groups availability_zone
37
+ db_subnet_group preferred_maintenance_window pending_modified_values
38
+ latest_restorable_time multi_az engine_version auto_minor_version_upgrade
39
+ read_replica_source_db_instance_identifier
40
+ read_replica_db_instance_identifiers license_model iops
41
+ option_group_memberships character_set_name secondary_availability_zone
42
+ publicly_accessible status_infos storage_type tde_credential_arn
43
+ storage_encrypted kms_key_id dbi_resource_id ca_certificate_identifier
44
+ )
45
+
46
+ describes.each do |describe|
47
+ define_method describe do
48
+ @instance[describe]
49
+ end
50
+ end
51
+
52
+ def vpc_id
53
+ @instance[:db_subnet_group][:vpc_id]
54
+ end
55
+
56
+ def has_security_group?(sg_id)
57
+ return true if has_vpc_security_group_id?(sg_id)
58
+ return true if has_vpc_security_group_name?(sg_id)
59
+ return true if has_vpc_security_group_tag_name?(sg_id)
60
+ return true if has_db_security_group_name?(sg_id)
61
+ end
62
+
63
+ def has_db_parameter_group?(name)
64
+ pgs = @instance[:db_parameter_groups]
65
+ pgs.find do |pg|
66
+ pg[:db_parameter_group_name] == name
67
+ end
68
+ end
69
+
70
+ def has_option_group?(name)
71
+ ogs = @instance[:option_group_memberships]
72
+ ogs.find do |og|
73
+ og[:option_group_name] == name
74
+ end
75
+ end
76
+
77
+ private
78
+
79
+ def has_vpc_security_group_id?(sg_id)
80
+ sgs = @instance[:vpc_security_groups]
81
+ sgs.find do |sg|
82
+ sg[:vpc_security_group_id] == sg_id
83
+ end
84
+ end
85
+
86
+ def has_vpc_security_group_name?(sg_id)
87
+ sgs = @instance[:vpc_security_groups]
88
+ res = @ec2_client.describe_security_groups({
89
+ filters: [{ name: 'group-name', values: [sg_id] }]
90
+ })
91
+ return false unless res[:security_groups].count == 1
92
+ sgs.find do |sg|
93
+ sg[:vpc_security_group_id] == res[:security_groups][0][:group_id]
94
+ end
95
+ end
96
+
97
+ def has_vpc_security_group_tag_name?(sg_id)
98
+ sgs = @instance[:vpc_security_groups]
99
+ res = @ec2_client.describe_security_groups({
100
+ filters: [{ name: 'tag:Name', values: [sg_id] }]
101
+ })
102
+ return false unless res[:security_groups].count == 1
103
+ sgs.find do |sg|
104
+ sg[:vpc_security_group_id] == res[:security_groups][0][:group_id]
105
+ end
106
+ end
107
+
108
+ def has_db_security_group_name?(sg_id)
109
+ sgs = @instance[:db_security_groups]
110
+ sgs.find do |sg|
111
+ sg[:db_security_group_name] == sg_id
112
+ end
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,90 @@
1
+ module Awspec::Type
2
+ class SecurityGroup < Base
3
+ attr_reader :client, :sg, :inbound
4
+
5
+ def initialize(id)
6
+ super
7
+ @client = @ec2_client
8
+ @inbound = true
9
+ @sg = find_security_group(id)
10
+ @id = @sg[:group_id]
11
+ end
12
+
13
+ describes = %w(
14
+ owner_id group_name group_id description
15
+ ip_permissions ip_permissions_egress vpc_id tags
16
+ )
17
+
18
+ describes.each do |describe|
19
+ define_method describe do
20
+ @sg[describe]
21
+ end
22
+ end
23
+
24
+ def opened?(port = nil, protocol = nil, cidr = nil)
25
+ if @inbound
26
+ return inbound_opened?(port, protocol, cidr)
27
+ else
28
+ return outbound_opened?(port, protocol, cidr)
29
+ end
30
+ end
31
+
32
+ def inbound_opened?(port = nil, protocol = nil, cidr = nil)
33
+ @sg[:ip_permissions].find do |permission|
34
+ next true unless port
35
+ next true unless permission[:from_port]
36
+ next true unless permission[:to_port]
37
+ next false unless port.between?(permission[:from_port], permission[:to_port])
38
+ next false if protocol && permission[:ip_protocol] != protocol
39
+ next true unless cidr
40
+ ret = permission[:ip_ranges].select do |ip_range|
41
+ ip_range[:cidr_ip] == cidr
42
+ end
43
+ next true if ret.count > 0
44
+ ret = permission[:user_id_group_pairs].select do |sg|
45
+ next true if sg[:group_id] == cidr
46
+ sg2 = find_security_group(sg[:group_id])
47
+ next true if sg2[:group_name] == cidr
48
+ sg2[:tags].find do |tag|
49
+ tag[:key] == 'Name' && tag[:value] == cidr
50
+ end
51
+ end
52
+ next true if ret.count > 0
53
+ end
54
+ end
55
+
56
+ def outbound_opened?(port = nil, protocol = nil, cidr = nil)
57
+ @sg[:ip_permissions_egress].find do |permission|
58
+ next true unless port
59
+ next true unless permission[:from_port]
60
+ next true unless permission[:to_port]
61
+ next false unless port.between?(permission[:from_port], permission[:to_port])
62
+ next false if protocol && permission[:ip_protocol] != protocol
63
+ next true unless cidr
64
+ ret = permission[:ip_ranges].select do |ip_range|
65
+ ip_range[:cidr_ip] == cidr
66
+ end
67
+ next true if ret.count > 0
68
+ ret = permission[:user_id_group_pairs].select do |sg|
69
+ next true if sg[:group_id] == cidr
70
+ sg2 = find_security_group(sg[:group_id])
71
+ next true if sg2[:group_name] == cidr
72
+ sg2[:tags].find do |tag|
73
+ tag[:key] == 'Name' && tag[:value] == cidr
74
+ end
75
+ end
76
+ next true if ret.count > 0
77
+ end
78
+ end
79
+
80
+ def inbound
81
+ @inbound = true
82
+ self
83
+ end
84
+
85
+ def outbound
86
+ @inbound = false
87
+ self
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,45 @@
1
+ module Awspec::Type
2
+ class Vpc < Base
3
+ attr_reader :client, :vpc
4
+
5
+ def initialize(id)
6
+ super
7
+ @client = @ec2_client
8
+ @vpc = find_vpc(id)
9
+ @id = @vpc[:vpc_id]
10
+ end
11
+
12
+ states = %w(
13
+ available pending
14
+ )
15
+
16
+ states.each do |state|
17
+ define_method state + '?' do
18
+ @vpc[:state] == state
19
+ end
20
+ end
21
+
22
+ describes = %w(
23
+ vpc_id state cidr_block dhcp_options_id
24
+ tags instance_tenancy is_default
25
+ )
26
+
27
+ describes.each do |describe|
28
+ define_method describe do
29
+ @vpc[describe]
30
+ end
31
+ end
32
+
33
+ def has_route_table?(id)
34
+ route_table = find_route_table(id)
35
+ return false unless route_table
36
+ route_table[:vpc_id] == @id
37
+ end
38
+
39
+ def has_network_acl?(id)
40
+ n = find_network_acl(id)
41
+ return false unless n
42
+ n[:vpc_id] == @id
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,3 @@
1
+ module Awspec
2
+ VERSION = '0.0.1'
3
+ end
metadata ADDED
@@ -0,0 +1,169 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: awspec
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - k1LoW
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2015-07-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rspec
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec-its
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: aws-sdk
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: thor
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: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.9'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.9'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '10.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '10.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop
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
+ description: RSpec tests for your AWS resources.
112
+ email:
113
+ - k1lowxb@gmail.com
114
+ executables: []
115
+ extensions: []
116
+ extra_rdoc_files: []
117
+ files:
118
+ - ".editorconfig"
119
+ - ".gitignore"
120
+ - ".rubocop.yml"
121
+ - ".travis.yml"
122
+ - Gemfile
123
+ - LICENSE.txt
124
+ - README.md
125
+ - Rakefile
126
+ - awspec.gemspec
127
+ - bin/awspec
128
+ - lib/awspec.rb
129
+ - lib/awspec/cli.rb
130
+ - lib/awspec/ext/string.rb
131
+ - lib/awspec/helper.rb
132
+ - lib/awspec/helper/type.rb
133
+ - lib/awspec/matcher.rb
134
+ - lib/awspec/matcher/be_opened.rb
135
+ - lib/awspec/matcher/belong_to_db_subnet_group.rb
136
+ - lib/awspec/matcher/belong_to_subnet.rb
137
+ - lib/awspec/matcher/belong_to_vpc.rb
138
+ - lib/awspec/setup.rb
139
+ - lib/awspec/type/base.rb
140
+ - lib/awspec/type/ec2.rb
141
+ - lib/awspec/type/rds.rb
142
+ - lib/awspec/type/security_group.rb
143
+ - lib/awspec/type/vpc.rb
144
+ - lib/awspec/version.rb
145
+ homepage: https://github.com/k1LoW/awspec
146
+ licenses:
147
+ - MIT
148
+ metadata: {}
149
+ post_install_message:
150
+ rdoc_options: []
151
+ require_paths:
152
+ - lib
153
+ required_ruby_version: !ruby/object:Gem::Requirement
154
+ requirements:
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ required_rubygems_version: !ruby/object:Gem::Requirement
159
+ requirements:
160
+ - - ">="
161
+ - !ruby/object:Gem::Version
162
+ version: '0'
163
+ requirements: []
164
+ rubyforge_project:
165
+ rubygems_version: 2.2.2
166
+ signing_key:
167
+ specification_version: 4
168
+ summary: RSpec tests for your AWS resources.
169
+ test_files: []