chemtrail 0.3.1 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/examples/lib/templates/config/load_balancer.yml +23 -0
  3. data/examples/lib/templates/config/nat_device.yml +49 -0
  4. data/examples/lib/templates/config/opsworks.yml +5 -0
  5. data/examples/lib/templates/config/private_network.yml +34 -0
  6. data/examples/lib/templates/config/{resources.yml → public_network.yml} +4 -14
  7. data/examples/lib/templates/config/public_network_acl.yml +54 -0
  8. data/examples/lib/templates/config/{mappings.yml → stack.yml} +24 -17
  9. data/examples/lib/templates/opsworks_vpc/load_balancer.rb +36 -0
  10. data/examples/lib/templates/opsworks_vpc/nat_device.rb +58 -0
  11. data/examples/lib/templates/opsworks_vpc/opsworks.rb +27 -0
  12. data/examples/lib/templates/opsworks_vpc/private_network.rb +89 -0
  13. data/examples/lib/templates/opsworks_vpc/public_network.rb +79 -0
  14. data/examples/lib/templates/opsworks_vpc/public_network_acl.rb +72 -0
  15. data/examples/lib/templates/opsworks_vpc_template.rb +71 -67
  16. data/examples/spec/lib/templates/opsworks_vpc/load_balancer_spec.rb +22 -0
  17. data/examples/spec/lib/templates/opsworks_vpc/nat_device_spec.rb +45 -0
  18. data/examples/spec/lib/templates/opsworks_vpc/opsworks_spec.rb +21 -0
  19. data/examples/spec/lib/templates/opsworks_vpc/private_network_spec.rb +62 -0
  20. data/examples/spec/lib/templates/opsworks_vpc/public_network_acl_spec.rb +63 -0
  21. data/examples/spec/lib/templates/opsworks_vpc/public_network_spec.rb +40 -0
  22. data/examples/spec/lib/templates/opsworks_vpc_template_spec.rb +37 -39
  23. data/lib/chemtrail/matchers/be_reference_to.rb +11 -0
  24. data/lib/chemtrail/matchers/have_entry.rb +36 -0
  25. data/lib/chemtrail/matchers/have_field.rb +7 -20
  26. data/lib/chemtrail/matchers/have_mapping.rb +4 -2
  27. data/lib/chemtrail/matchers/have_output.rb +46 -0
  28. data/lib/chemtrail/matchers/have_parameter.rb +9 -8
  29. data/lib/chemtrail/matchers/have_property.rb +35 -20
  30. data/lib/chemtrail/matchers/have_resource.rb +9 -8
  31. data/lib/chemtrail/matchers/have_tag.rb +7 -20
  32. data/lib/chemtrail/reference_presenter.rb +8 -6
  33. data/lib/chemtrail/rspec.rb +3 -1
  34. data/lib/chemtrail/version.rb +1 -1
  35. metadata +24 -6
  36. data/examples/lib/templates/config/parameters.yml +0 -18
  37. data/lib/chemtrail/matchers/have_mapping_key.rb +0 -49
@@ -0,0 +1,63 @@
1
+ require "spec_helper"
2
+
3
+ describe OpsworksVpc::PublicNetworkAcl do
4
+ let(:vpc) { double(:vpc, id: "VPC") }
5
+ let(:subnet) { double(:subnet, id: "PublicSubnet") }
6
+
7
+ subject(:network) { OpsworksVpc::PublicNetworkAcl.new(vpc, subnet) }
8
+
9
+ describe "#resources" do
10
+ its(:resources) { should have_resource("PublicNetworkAcl").with_type("AWS::EC2::NetworkAcl") }
11
+ its(:resources) { should have_resource("PublicSubnetNetworkAclAssociation").with_type("AWS::EC2::SubnetNetworkAclAssociation") }
12
+ its(:resources) { should have_resource("InboundHTTPPublicNetworkAclEntry").with_type("AWS::EC2::NetworkAclEntry") }
13
+ its(:resources) { should have_resource("InboundHTTPSPublicNetworkAclEntry").with_type("AWS::EC2::NetworkAclEntry") }
14
+ its(:resources) { should have_resource("InboundSSHPublicNetworkAclEntry").with_type("AWS::EC2::NetworkAclEntry") }
15
+ its(:resources) { should have_resource("InboundEmphemeralPublicNetworkAclEntry").with_type("AWS::EC2::NetworkAclEntry") }
16
+ its(:resources) { should have_resource("OutboundPublicNetworkAclEntry").with_type("AWS::EC2::NetworkAclEntry") }
17
+
18
+ describe "PublicNetworkAcl" do
19
+ its(:network_acl) { should have_property("VpcId").with_reference("VPC") }
20
+ its(:network_acl) { should have_tag("Application").with_reference("AWS::StackName") }
21
+ end
22
+
23
+ describe "PublicSubnetNetworkAclAssociation" do
24
+ its(:network_acl_association) { should have_property("SubnetId").with_reference("PublicSubnet") }
25
+ its(:network_acl_association) { should have_property("NetworkAclId").with_reference("PublicNetworkAcl") }
26
+ end
27
+
28
+ describe "InboundHTTPPublicNetworkAclEntry" do
29
+ its(:http_entry) { should have_property("NetworkAclId").with_reference("PublicNetworkAcl") }
30
+ its(:http_entry) { should have_property("PortRange").with_value("From" => "80", "To" => "80") }
31
+ its(:http_entry) { should have_property("RuleNumber").with_value("100") }
32
+ its(:http_entry) { should have_property("Egress").with_value("false") }
33
+ end
34
+
35
+ describe "InboundHTTPSPublicNetworkAclEntry" do
36
+ its(:https_entry) { should have_property("NetworkAclId").with_reference("PublicNetworkAcl") }
37
+ its(:https_entry) { should have_property("PortRange").with_value("From" => "443", "To" => "443") }
38
+ its(:https_entry) { should have_property("RuleNumber").with_value("101") }
39
+ its(:https_entry) { should have_property("Egress").with_value("false") }
40
+ end
41
+
42
+ describe "InboundSSHPublicNetworkAclEntry" do
43
+ its(:ssh_entry) { should have_property("NetworkAclId").with_reference("PublicNetworkAcl") }
44
+ its(:ssh_entry) { should have_property("PortRange").with_value("From" => "22", "To" => "22") }
45
+ its(:ssh_entry) { should have_property("RuleNumber").with_value("102") }
46
+ its(:ssh_entry) { should have_property("Egress").with_value("false") }
47
+ end
48
+
49
+ describe "InboundEmphemeralPublicNetworkAclEntry" do
50
+ its(:ephemeral_entry) { should have_property("NetworkAclId").with_reference("PublicNetworkAcl") }
51
+ its(:ephemeral_entry) { should have_property("PortRange").with_value("From" => "1024", "To" => "65535") }
52
+ its(:ephemeral_entry) { should have_property("RuleNumber").with_value("103") }
53
+ its(:ephemeral_entry) { should have_property("Egress").with_value("false") }
54
+ end
55
+
56
+ describe "OutboundPublicNetworkAclEntry" do
57
+ its(:outbound_entry) { should have_property("NetworkAclId").with_reference("PublicNetworkAcl") }
58
+ its(:outbound_entry) { should have_property("PortRange").with_value("From" => "0", "To" => "65535") }
59
+ its(:outbound_entry) { should have_property("RuleNumber").with_value("100") }
60
+ its(:outbound_entry) { should have_property("Egress").with_value("true") }
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,40 @@
1
+ require "spec_helper"
2
+
3
+ describe OpsworksVpc::PublicNetwork do
4
+ let(:vpc) { double(:vpc, id: "VPC") }
5
+ let(:subnet) { double(:subnet, find: "found") }
6
+
7
+ subject(:network) { OpsworksVpc::PublicNetwork.new(vpc, subnet) }
8
+
9
+ describe "#resources" do
10
+ its(:resources) { should have_resource("PublicSubnet").with_type("AWS::EC2::Subnet") }
11
+ its(:resources) { should have_resource("InternetGateway").with_type("AWS::EC2::InternetGateway") }
12
+ its(:resources) { should have_resource("GatewayToInternet").with_type("AWS::EC2::VPCGatewayAttachment") }
13
+ its(:resources) { should have_resource("PublicRouteTable").with_type("AWS::EC2::RouteTable") }
14
+ its(:resources) { should have_resource("PublicSubnetRouteTableAssociation").with_type("AWS::EC2::SubnetRouteTableAssociation") }
15
+
16
+ describe "PublicSubnet" do
17
+ its(:subnet) { should have_property("CidrBlock") }
18
+ its(:subnet) { should have_tag("Application").with_reference("AWS::StackName") }
19
+ end
20
+
21
+ describe "InternetGateway" do
22
+ its(:internet_gateway) { should have_tag("Application").with_reference("AWS::StackName") }
23
+ end
24
+
25
+ describe "GatewayToInternet" do
26
+ its(:gateway_to_internet) { should have_property("VpcId").with_reference("VPC") }
27
+ its(:gateway_to_internet) { should have_property("InternetGatewayId").with_reference("InternetGateway") }
28
+ end
29
+
30
+ describe "PublicRouteTable" do
31
+ its(:route_table) { should have_property("VpcId").with_reference("VPC") }
32
+ its(:route_table) { should have_tag("Application").with_reference("AWS::StackName") }
33
+ end
34
+
35
+ describe "PublicSubnetRouteTableAssociation" do
36
+ its(:route_table_association) { should have_property("SubnetId").with_reference("PublicSubnet") }
37
+ its(:route_table_association) { should have_property("RouteTableId").with_reference("PublicRouteTable") }
38
+ end
39
+ end
40
+ end
@@ -1,59 +1,57 @@
1
1
  require "spec_helper"
2
2
 
3
- describe OpsworksVpc do
4
- subject(:template) { OpsworksVpc.new }
3
+ describe OpsworksVpc::Stack do
4
+ subject(:template) { OpsworksVpc::Stack.new }
5
5
 
6
6
  its(:description) { should include("VPC environment for AWS OpsWorks") }
7
7
 
8
8
  describe "#parameters" do
9
- it { should have_parameter("NATInstanceType").with_type("String") }
9
+ its(:parameters) { should have_parameter("NATInstanceType").with_type("String") }
10
10
 
11
- it { should have_field("Default").with_value("m1.small").on("NATInstanceType") }
12
- it { should have_field("AllowedValues").including("t1.micro").on("NATInstanceType") }
13
- it { should have_field("ConstraintDescription").including("valid EC2 instance").on("NATInstanceType") }
11
+ describe "NATInstanceType" do
12
+ its(:nat_instance_type) { should have_field("Default").with_value("m1.small") }
13
+ its(:nat_instance_type) { should have_field("AllowedValues").including("t1.micro") }
14
+ its(:nat_instance_type) { should have_field("ConstraintDescription").including("valid EC2 instance") }
15
+ end
14
16
  end
15
17
 
16
18
  describe "#mappings" do
17
- it { should have_mapping("AWSNATAMI") }
18
- it { should have_mapping("AWSInstanceType2Arch") }
19
- it { should have_mapping("SubnetConfig") }
20
-
21
- it { should have_mapping_key("us-east-1").including("AMI" => "ami-c6699baf").on("AWSNATAMI") }
22
- it { should have_mapping_key("m1.medium").including("Arch" => "64").on("AWSInstanceType2Arch") }
23
- it { should have_mapping_key("VPC").including("CIDR" => "10.0.0.0/16").on("SubnetConfig") }
24
- it { should have_mapping_key("Public").including("CIDR" => "10.0.0.0/24").on("SubnetConfig") }
25
- it { should have_mapping_key("Private").including("CIDR" => "10.0.1.0/24").on("SubnetConfig") }
26
- end
19
+ its(:mappings) { should have_mapping "AWSNATAMI" }
20
+ its(:mappings) { should have_mapping "AWSInstanceType2Arch" }
21
+ its(:mappings) { should have_mapping "SubnetConfig" }
27
22
 
28
- describe "#resources" do
29
- describe "VPC" do
30
- it { should have_resource("VPC").with_type("AWS::EC2::VPC") }
31
-
32
- it { should have_property("CidrBlock").on("VPC") }
33
- it { should have_tag("Application").with_reference("AWS::StackName").on("VPC") }
34
- it { should have_tag("Network").with_value("Public").on("VPC") }
23
+ describe "AWSInstanceType2Arch" do
24
+ its(:instance_type_arch) { should have_entry("m1.medium").including("Arch" => "64") }
35
25
  end
36
26
 
37
- describe "PublicSubnet" do
38
- it { should have_resource("PublicSubnet").with_type("AWS::EC2::Subnet") }
39
-
40
- it { should have_property("CidrBlock").on("PublicSubnet") }
41
- it { should have_tag("Application").with_reference("AWS::StackName").on("PublicSubnet") }
42
- it { should have_tag("Network").with_value("Public").on("PublicSubnet") }
27
+ describe "SubnetConfig" do
28
+ its(:subnet_config) { should have_entry("VPC").including("CIDR" => "10.0.0.0/16") }
29
+ its(:subnet_config) { should have_entry("Public").including("CIDR" => "10.0.0.0/24") }
30
+ its(:subnet_config) { should have_entry("Private").including("CIDR" => "10.0.1.0/24") }
43
31
  end
32
+ end
44
33
 
45
- describe "InternetGateway" do
46
- it { should have_resource("InternetGateway").with_type("AWS::EC2::InternetGateway") }
47
-
48
- it { should have_tag("Application").with_reference("AWS::StackName").on("InternetGateway") }
49
- it { should have_tag("Network").with_value("Public").on("InternetGateway") }
50
- end
34
+ describe "#resources" do
35
+ its(:resources) { should have_resource "OpsWorksSecurityGroup" }
36
+ its(:resources) { should have_resource "NATDevice" }
37
+ its(:resources) { should have_resource "ElasticLoadBalancer" }
38
+ its(:resources) { should have_resource "PrivateSubnet" }
39
+ its(:resources) { should have_resource "PublicSubnet" }
40
+ its(:resources) { should have_resource "InboundHTTPPublicNetworkAclEntry" }
51
41
 
52
- describe "GatewayToInternet" do
53
- it { should have_resource("GatewayToInternet").with_type("AWS::EC2::VPCGatewayAttachment") }
42
+ its(:resources) { should have_resource("VPC").with_type("AWS::EC2::VPC") }
54
43
 
55
- it { should have_property("VpcId").with_reference("VPC").on("GatewayToInternet") }
56
- it { should have_property("InternetGatewayId").with_reference("InternetGateway").on("GatewayToInternet") }
44
+ describe "VPC" do
45
+ its(:vpc) { should have_property("CidrBlock") }
46
+ its(:vpc) { should have_tag("Application").with_reference("AWS::StackName") }
47
+ its(:vpc) { should have_tag("Network").with_value("Public") }
57
48
  end
58
49
  end
50
+
51
+ describe "#outputs" do
52
+ its(:outputs) { should have_output("VPC").with_reference("VPC") }
53
+ its(:outputs) { should have_output("PublicSubnets").with_reference("PublicSubnet") }
54
+ its(:outputs) { should have_output("PrivateSubnets").with_reference("PrivateSubnet") }
55
+ its(:outputs) { should have_output("LoadBalancer").with_reference("ElasticLoadBalancer") }
56
+ end
59
57
  end
@@ -0,0 +1,11 @@
1
+ require "rspec/expectations"
2
+
3
+ module Chemtrail::RSpec
4
+ extend RSpec::Matchers::DSL
5
+
6
+ matcher :be_reference_to do |expected|
7
+ match do |actual|
8
+ actual.id == expected
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,36 @@
1
+ require "rspec/expectations"
2
+
3
+ module Chemtrail::RSpec
4
+ extend RSpec::Matchers::DSL
5
+
6
+ matcher :have_entry do |entry_name|
7
+ define_method :entry_for do |mapping|
8
+ mapping.entries[entry_name]
9
+ end
10
+
11
+ define_method :matches_value? do |entry|
12
+ if @included_value
13
+ entry.values_at(*@included_value.keys) == @included_value.values
14
+ else
15
+ true
16
+ end
17
+ end
18
+
19
+ match do |mapping|
20
+ entry = entry_for(mapping)
21
+ !mapping.nil? && !entry.nil? && matches_value?(entry)
22
+ end
23
+
24
+ chain :including do |value|
25
+ @included_value = value
26
+ end
27
+
28
+ failure_message_for_should do |mapping|
29
+ if entry = entry_for(mapping)
30
+ %(expected mapping #{mapping.id} field #{entry_name.inspect} to have value #{@included_value.inspect}, but got #{entry.inspect})
31
+ else
32
+ %(expected mapping #{mapping.id} to have type #{entry_name.inspect})
33
+ end
34
+ end
35
+ end
36
+ end
@@ -4,10 +4,6 @@ module Chemtrail::RSpec
4
4
  extend RSpec::Matchers::DSL
5
5
 
6
6
  matcher :have_field do |field_name|
7
- define_method :parameter_for do |actual|
8
- actual.parameters.detect { |p| p.id == @parameter_id }
9
- end
10
-
11
7
  define_method :field_for do |parameter|
12
8
  parameter.fields[field_name]
13
9
  end
@@ -22,14 +18,9 @@ module Chemtrail::RSpec
22
18
  end
23
19
  end
24
20
 
25
- match do |actual|
26
- parameter = parameter_for(actual)
21
+ match do |parameter|
27
22
  field = field_for(parameter)
28
- !parameter.nil? && !field.nil? && matches_value?(field)
29
- end
30
-
31
- chain :on do |parameter_id|
32
- @parameter_id = parameter_id
23
+ !field.nil? && matches_value?(field)
33
24
  end
34
25
 
35
26
  chain :with_value do |value|
@@ -40,16 +31,12 @@ module Chemtrail::RSpec
40
31
  @included_value = value
41
32
  end
42
33
 
43
- failure_message_for_should do |actual|
44
- if parameter = parameter_for(actual)
45
- if field = field_for(parameter)
46
- expected_field = @value || @included_value
47
- %(expected parameter #{@parameter_id.inspect} field #{field_name.inspect} to have value #{expected_field.inspect}, but got #{field.inspect})
48
- else
49
- %(expected parameter #{@parameter_id.inspect} to have type #{field_name.inspect})
50
- end
34
+ failure_message_for_should do |parameter|
35
+ if field = field_for(parameter)
36
+ expected_field = @value || @included_value
37
+ %(expected parameter #{parameter.id} field #{field_name.inspect} to have value #{expected_field.inspect}, but got #{field.inspect})
51
38
  else
52
- %(expected to find parameter #{@parameter_id.inspect}, but got nothing)
39
+ %(expected parameter #{parameter.id} to have type #{field_name.inspect})
53
40
  end
54
41
  end
55
42
  end
@@ -3,7 +3,9 @@ require "rspec/expectations"
3
3
  module Chemtrail::RSpec
4
4
  extend RSpec::Matchers::DSL
5
5
 
6
- matcher :have_mapping do |expected|
7
- match { |actual| actual.mappings.any? { |m| m.id == expected } }
6
+ matcher :have_mapping do |mapping_id|
7
+ match do |mapping_list|
8
+ mapping_list.any? { |m| m.id == mapping_id }
9
+ end
8
10
  end
9
11
  end
@@ -0,0 +1,46 @@
1
+ require "rspec/expectations"
2
+
3
+ module Chemtrail::RSpec
4
+ extend RSpec::Matchers::DSL
5
+
6
+ matcher :have_output do |output_id|
7
+ define_method :output_for do |output_list|
8
+ output_list.detect { |output| output.id == output_id }
9
+ end
10
+
11
+ define_method :matches_value? do |output|
12
+ if @value
13
+ output.value == @value
14
+ elsif @reference
15
+ output.value.id == @reference
16
+ else
17
+ true
18
+ end
19
+ end
20
+
21
+ match do |output_list|
22
+ output = output_for(output_list)
23
+ !output.nil? && matches_value?(output)
24
+ end
25
+
26
+ chain :with_value do |value|
27
+ @value = value
28
+ end
29
+
30
+ chain :with_reference do |reference|
31
+ @reference = reference
32
+ end
33
+
34
+ failure_message_for_should do |output_list|
35
+ if output = output_for(output_list)
36
+ if @value
37
+ %(expected output #{output.id} property #{property_name.inspect} to have value #{@value.inspect}, but got #{output.value.inspect})
38
+ else
39
+ %(expected output #{output.id} property #{property_name.inspect} to refer to #{@reference.inspect}, but got #{output.id.inspect})
40
+ end
41
+ else
42
+ %(expected to find output #{output_id.inspect}, but got nothing)
43
+ end
44
+ end
45
+ end
46
+ end
@@ -4,24 +4,25 @@ module Chemtrail::RSpec
4
4
  extend RSpec::Matchers::DSL
5
5
 
6
6
  matcher :have_parameter do |parameter_id|
7
- define_method :parameter_for do |actual|
8
- actual.parameters.detect { |param| param.id == parameter_id }
7
+ define_method :parameter_for do |parameter_list|
8
+ parameter_list.detect { |param| param.id == parameter_id }
9
9
  end
10
10
 
11
- define_method :matches_type? do |actual|
12
- @type.nil? || parameter_for(actual).type == @type
11
+ define_method :matches_type? do |parameter|
12
+ @type.nil? || parameter.type == @type
13
13
  end
14
14
 
15
- match do |actual|
16
- !parameter_for(actual).nil? && matches_type?(actual)
15
+ match do |parameter_list|
16
+ parameter = parameter_for(parameter_list)
17
+ !parameter.nil? && matches_type?(parameter)
17
18
  end
18
19
 
19
20
  chain :with_type do |type|
20
21
  @type = type
21
22
  end
22
23
 
23
- failure_message_for_should do |actual|
24
- if parameter = parameter_for(actual)
24
+ failure_message_for_should do |parameter_list|
25
+ if parameter = parameter_for(parameter_list)
25
26
  %(expected parameter #{parameter_id.inspect} to have type #{@type.inspect}, but got #{parameter.type.inspect})
26
27
  else
27
28
  %(expected to find parameter #{parameter_id.inspect}, but got nothing)
@@ -4,10 +4,6 @@ module Chemtrail::RSpec
4
4
  extend RSpec::Matchers::DSL
5
5
 
6
6
  matcher :have_property do |property_name|
7
- define_method :resource_for do |actual|
8
- actual.resources.detect { |resource| resource.id == @resource_id }
9
- end
10
-
11
7
  define_method :property_for do |resource|
12
8
  resource.properties[property_name]
13
9
  end
@@ -22,14 +18,27 @@ module Chemtrail::RSpec
22
18
  end
23
19
  end
24
20
 
25
- match do |actual|
26
- resource = resource_for(actual)
27
- property = property_for(resource)
28
- !resource.nil? && !property.nil? && matches_value?(property)
21
+ define_method :includes_value? do |property|
22
+ if @value
23
+ property.includes?(@value)
24
+ elsif @reference
25
+ property.any? { |p| p.id == @reference }
26
+ else
27
+ true
28
+ end
29
29
  end
30
30
 
31
- chain :on do |resource_id|
32
- @resource_id = resource_id
31
+ define_method :matches_strategy? do |property|
32
+ if @including
33
+ includes_value?(property)
34
+ else
35
+ matches_value?(property)
36
+ end
37
+ end
38
+
39
+ match do |resource|
40
+ property = property_for(resource)
41
+ !resource.nil? && !property.nil? && matches_strategy?(property)
33
42
  end
34
43
 
35
44
  chain :with_value do |value|
@@ -40,19 +49,25 @@ module Chemtrail::RSpec
40
49
  @reference = reference
41
50
  end
42
51
 
43
- failure_message_for_should do |actual|
44
- if resource = resource_for(actual)
45
- if property = property_for(resource)
46
- if @value
47
- %(expected resource #{@resource_id.inspect} property #{property_name.inspect} to have value #{@value.inspect}, but got #{property.inspect})
48
- else
49
- %(expected resource #{@resource_id.inspect} property #{property_name.inspect} to refer to #{@reference.inspect}, but got #{property.id.inspect})
50
- end
52
+ chain :including_value do |value|
53
+ @including = true
54
+ @value = value
55
+ end
56
+
57
+ chain :including_reference do |reference|
58
+ @including = true
59
+ @reference = reference
60
+ end
61
+
62
+ failure_message_for_should do |resource|
63
+ if property = property_for(resource)
64
+ if @value
65
+ %(expected resource #{resource.id} property #{property_name.inspect} to have value #{@value.inspect}, but got #{property.inspect})
51
66
  else
52
- %(expected resource #{@resource_id.inspect} to have property #{property_name.inspect})
67
+ %(expected resource #{resource.id} property #{property_name.inspect} to refer to #{@reference.inspect}, but got #{property.id.inspect})
53
68
  end
54
69
  else
55
- %(expected to find resource #{@resource_id.inspect}, but got nothing)
70
+ %(expected resource #{resource.id} to have property #{property_name.inspect})
56
71
  end
57
72
  end
58
73
  end