geoengineer 0.1.0
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.
- checksums.yaml +7 -0
- data/LICENSE +13 -0
- data/README.md +476 -0
- data/bin/geo +7 -0
- data/lib/geoengineer.rb +29 -0
- data/lib/geoengineer/cli/geo_cli.rb +208 -0
- data/lib/geoengineer/cli/status_command.rb +101 -0
- data/lib/geoengineer/cli/terraform_commands.rb +59 -0
- data/lib/geoengineer/environment.rb +186 -0
- data/lib/geoengineer/output.rb +27 -0
- data/lib/geoengineer/project.rb +79 -0
- data/lib/geoengineer/resource.rb +200 -0
- data/lib/geoengineer/resources/aws_db_instance.rb +46 -0
- data/lib/geoengineer/resources/aws_db_parameter_group.rb +25 -0
- data/lib/geoengineer/resources/aws_elasticache_cluster.rb +50 -0
- data/lib/geoengineer/resources/aws_elasticache_parameter_group.rb +30 -0
- data/lib/geoengineer/resources/aws_elasticache_replication_group.rb +44 -0
- data/lib/geoengineer/resources/aws_elasticache_subnet_group.rb +25 -0
- data/lib/geoengineer/resources/aws_elasticsearch_domain.rb +35 -0
- data/lib/geoengineer/resources/aws_elb.rb +57 -0
- data/lib/geoengineer/resources/aws_iam_policy.rb +53 -0
- data/lib/geoengineer/resources/aws_iam_user.rb +42 -0
- data/lib/geoengineer/resources/aws_instance.rb +24 -0
- data/lib/geoengineer/resources/aws_proxy_protocol_policy.rb +39 -0
- data/lib/geoengineer/resources/aws_redshift_cluster.rb +23 -0
- data/lib/geoengineer/resources/aws_route53_record.rb +32 -0
- data/lib/geoengineer/resources/aws_route53_zone.rb +21 -0
- data/lib/geoengineer/resources/aws_s3_bucket.rb +54 -0
- data/lib/geoengineer/resources/aws_security_group.rb +53 -0
- data/lib/geoengineer/resources/aws_ses_receipt_rule.rb +38 -0
- data/lib/geoengineer/resources/aws_ses_receipt_rule_set.rb +28 -0
- data/lib/geoengineer/resources/aws_sns_topic.rb +28 -0
- data/lib/geoengineer/resources/aws_sns_topic_subscription.rb +42 -0
- data/lib/geoengineer/resources/aws_sqs_queue.rb +37 -0
- data/lib/geoengineer/resources/iam/statement.rb +43 -0
- data/lib/geoengineer/sub_resource.rb +35 -0
- data/lib/geoengineer/template.rb +28 -0
- data/lib/geoengineer/utils/aws_clients.rb +63 -0
- data/lib/geoengineer/utils/has_attributes.rb +97 -0
- data/lib/geoengineer/utils/has_lifecycle.rb +54 -0
- data/lib/geoengineer/utils/has_resources.rb +63 -0
- data/lib/geoengineer/utils/has_sub_resources.rb +43 -0
- data/lib/geoengineer/utils/has_validations.rb +57 -0
- data/lib/geoengineer/utils/null_object.rb +17 -0
- data/lib/geoengineer/version.rb +3 -0
- data/spec/environment_spec.rb +140 -0
- data/spec/output_spec.rb +3 -0
- data/spec/project_spec.rb +79 -0
- data/spec/resource_spec.rb +169 -0
- data/spec/resources/aws_db_instance_spec.rb +23 -0
- data/spec/resources/aws_db_parameter_group_spec.rb +23 -0
- data/spec/resources/aws_elasticache_replication_group_spec.rb +29 -0
- data/spec/resources/aws_elasticache_subnet_group_spec.rb +31 -0
- data/spec/resources/aws_elasticcache_cluster_spec.rb +23 -0
- data/spec/resources/aws_elasticcache_parameter_group_spec.rb +26 -0
- data/spec/resources/aws_elasticsearch_domain_spec.rb +22 -0
- data/spec/resources/aws_elb_spec.rb +65 -0
- data/spec/resources/aws_iam_policy.rb +35 -0
- data/spec/resources/aws_iam_user.rb +35 -0
- data/spec/resources/aws_instance_spec.rb +26 -0
- data/spec/resources/aws_proxy_protocol_policy_spec.rb +5 -0
- data/spec/resources/aws_redshift_cluster_spec.rb +25 -0
- data/spec/resources/aws_route53_record_spec.rb +41 -0
- data/spec/resources/aws_route53_zone_spec.rb +34 -0
- data/spec/resources/aws_s3_bucket_spec.rb +39 -0
- data/spec/resources/aws_security_group_spec.rb +80 -0
- data/spec/resources/aws_ses_receipt_rule.rb +33 -0
- data/spec/resources/aws_ses_receipt_rule_set.rb +25 -0
- data/spec/resources/aws_sns_topic_spec.rb +23 -0
- data/spec/resources/aws_sns_topic_subscription.rb +35 -0
- data/spec/resources/aws_sqs_queue_spec.rb +20 -0
- data/spec/rubocop_spec.rb +13 -0
- data/spec/spec_helper.rb +71 -0
- data/spec/sub_resource_spec.rb +20 -0
- data/spec/template_spec.rb +39 -0
- data/spec/utils/has_attributes_spec.rb +118 -0
- data/spec/utils/has_lifecycle_spec.rb +24 -0
- data/spec/utils/has_resources_spec.rb +68 -0
- data/spec/utils/has_subresources_spec.rb +29 -0
- data/spec/utils/has_validations_spec.rb +35 -0
- data/spec/utils/null_object_spec.rb +18 -0
- metadata +303 -0
@@ -0,0 +1,54 @@
|
|
1
|
+
########################################################################
|
2
|
+
# HasLifecycle provides methods to enable lifecycle hooks
|
3
|
+
########################################################################
|
4
|
+
module HasLifecycle
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
# ClassMethods
|
10
|
+
module ClassMethods
|
11
|
+
def _init_validation_hash
|
12
|
+
{
|
13
|
+
after: {},
|
14
|
+
before: {}
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
def lifecycle_actions(stage, step)
|
19
|
+
all = []
|
20
|
+
# inherit lifecycle_actions
|
21
|
+
sclazz = self.superclass
|
22
|
+
all.concat(sclazz.lifecycle_actions(stage, step)) if sclazz.respond_to?(:lifecycle_actions)
|
23
|
+
|
24
|
+
# Add this lifecycle actions
|
25
|
+
la_exists = @_actions && @_actions[stage] && @_actions[stage][step]
|
26
|
+
all.concat(@_actions[stage][step]) if la_exists
|
27
|
+
all
|
28
|
+
end
|
29
|
+
|
30
|
+
# Currently only supporting after(:initialize)
|
31
|
+
def after(lifecycle_step, method_name_or_proc)
|
32
|
+
@_actions = _init_validation_hash unless @_actions
|
33
|
+
@_actions[:after][lifecycle_step] = [] unless @_actions[:after][lifecycle_step]
|
34
|
+
@_actions[:after][lifecycle_step] << method_name_or_proc
|
35
|
+
end
|
36
|
+
|
37
|
+
def before(lifecycle_step, method_name_or_proc)
|
38
|
+
@_actions = _init_validation_hash unless @_actions
|
39
|
+
@_actions[:before][lifecycle_step] = [] unless @_actions[:before][lifecycle_step]
|
40
|
+
@_actions[:before][lifecycle_step] << method_name_or_proc
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# This method will return a list of errors if not valid, or nil
|
45
|
+
def execute_lifecycle(stage, step)
|
46
|
+
self.class.lifecycle_actions(stage, step).each do |actions|
|
47
|
+
if actions.is_a? Proc
|
48
|
+
self.instance_exec(&actions)
|
49
|
+
else
|
50
|
+
self.send(actions)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
########################################################################
|
2
|
+
# HasResources provides methods for a class to contain and query a set of resources
|
3
|
+
########################################################################
|
4
|
+
module HasResources
|
5
|
+
def self.included(base)
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
# ClassMethods
|
10
|
+
module ClassMethods
|
11
|
+
def get_resource_class_from_type(type)
|
12
|
+
c_name = type.split('_').collect(&:capitalize).join
|
13
|
+
c_name = "GeoEngineer::Resources::#{c_name}"
|
14
|
+
clazz = Object.const_defined?(c_name) ? Object.const_get(c_name) : GeoEngineer::Resource
|
15
|
+
clazz
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def resources
|
20
|
+
@_resources = [] unless @_resources
|
21
|
+
@_resources
|
22
|
+
end
|
23
|
+
|
24
|
+
# Overridden By Project and Environment
|
25
|
+
def all_resources
|
26
|
+
resources
|
27
|
+
end
|
28
|
+
|
29
|
+
def find_resource(type, id)
|
30
|
+
all_resources.select { |r| r.type == type && r.id == id }.first
|
31
|
+
end
|
32
|
+
|
33
|
+
def find_resource_by_ref(ref)
|
34
|
+
return nil unless ref.start_with?("${")
|
35
|
+
ref = ref.delete('${').delete('}')
|
36
|
+
type, name = ref.split('.')
|
37
|
+
find_resource(type, name)
|
38
|
+
end
|
39
|
+
|
40
|
+
def resources_grouped_by
|
41
|
+
all_resources.each_with_object({}) do |r, c|
|
42
|
+
value = yield r
|
43
|
+
c[value] ||= []
|
44
|
+
c[value] << r
|
45
|
+
c
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def resources_of_type(type)
|
50
|
+
all_resources.select { |r| r.type == type }
|
51
|
+
end
|
52
|
+
|
53
|
+
# Factory to create resource and attach
|
54
|
+
def create_resource(type, id, &block)
|
55
|
+
# This will look for a class that is defined by the type so it can override functionality
|
56
|
+
# For example, if `type='aws_security_group'` then the class would be `AwsSecurityGroup`
|
57
|
+
clazz = self.class.get_resource_class_from_type(type)
|
58
|
+
|
59
|
+
res = clazz.new(type, id, &block)
|
60
|
+
resources << res # Add the resource
|
61
|
+
res
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
########################################################################
|
2
|
+
# HasSubResources provides methods for a object to contain subresources
|
3
|
+
########################################################################
|
4
|
+
module HasSubResources
|
5
|
+
# This overrides assign_block from HasAttributes
|
6
|
+
# when a block is passed to an attribute it becomes a SubResource
|
7
|
+
def assign_block(name, *args, &block)
|
8
|
+
sr = GeoEngineer::SubResource.new(self, name, &block)
|
9
|
+
subresources << sr
|
10
|
+
sr
|
11
|
+
end
|
12
|
+
|
13
|
+
def attribute_missing(name)
|
14
|
+
all = false
|
15
|
+
if name.start_with?('all_')
|
16
|
+
name = name[4..-1]
|
17
|
+
all = true
|
18
|
+
end
|
19
|
+
srl = subresources.select { |s| s.type == name.to_s }
|
20
|
+
|
21
|
+
if srl.empty?
|
22
|
+
return [] if all
|
23
|
+
return nil
|
24
|
+
else
|
25
|
+
return srl if all
|
26
|
+
return srl.first
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def subresources
|
31
|
+
@_subresources = [] unless @_subresources
|
32
|
+
@_subresources
|
33
|
+
end
|
34
|
+
|
35
|
+
def delete_subresources_where(&block)
|
36
|
+
# Only leave sub resources that dont
|
37
|
+
@_subresources = subresources.reject(&block)
|
38
|
+
end
|
39
|
+
|
40
|
+
def delete_all_subresources(type)
|
41
|
+
@_subresources = subresources.select { |s| s.type != type.to_s }
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'netaddr'
|
2
|
+
|
3
|
+
########################################################################
|
4
|
+
# HasValidations provides methods to enable validations
|
5
|
+
########################################################################
|
6
|
+
module HasValidations
|
7
|
+
def self.included(base)
|
8
|
+
base.extend(ClassMethods)
|
9
|
+
end
|
10
|
+
|
11
|
+
# ClassMethods
|
12
|
+
module ClassMethods
|
13
|
+
def validations
|
14
|
+
all_validations = []
|
15
|
+
all_validations.concat(@_validations) if @_validations
|
16
|
+
# inherit validations
|
17
|
+
sclazz = self.superclass
|
18
|
+
all_validations.concat(sclazz.validations) if sclazz.respond_to?(:validations)
|
19
|
+
all_validations
|
20
|
+
end
|
21
|
+
|
22
|
+
def validate(method_name_or_proc)
|
23
|
+
@_validations = [] unless @_validations
|
24
|
+
@_validations << method_name_or_proc
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# This method will return a list of errors if not valid, or nil
|
29
|
+
def errors
|
30
|
+
execute_lifecycle(:before, :validation) if self.respond_to? :execute_lifecycle
|
31
|
+
errs = []
|
32
|
+
self.class.validations.each do |validation|
|
33
|
+
errs << (validation.is_a?(Proc) ? self.instance_exec(&validation) : self.send(validation))
|
34
|
+
end
|
35
|
+
# remove nils
|
36
|
+
errs = errs.flatten.select { |x| !x.nil? }
|
37
|
+
errs
|
38
|
+
end
|
39
|
+
|
40
|
+
# Validation Helper Methods
|
41
|
+
def validate_required_attributes(keys)
|
42
|
+
errs = []
|
43
|
+
keys.each do |key|
|
44
|
+
errs << "#{key} attribute nil for #{self}" if self[key].nil?
|
45
|
+
end
|
46
|
+
errs
|
47
|
+
end
|
48
|
+
|
49
|
+
# Validates CIDR block format
|
50
|
+
# Returns error when argument fails validation
|
51
|
+
def validate_cidr_block(cidr_block)
|
52
|
+
parsed_cidr = NetAddr::CIDR.create(cidr_block)
|
53
|
+
return [parsed_cidr, nil]
|
54
|
+
rescue NetAddr::ValidationError
|
55
|
+
return [nil, "Bad cidr block \"#{cidr_block}\" #{for_resource}"]
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
########################################################################
|
2
|
+
# NullObject and NullObject.maybe provide the NullObject pattern
|
3
|
+
# as defined {http://devblog.avdi.org/2011/05/30/null-objects-and-falsiness/ here}
|
4
|
+
#
|
5
|
+
########################################################################
|
6
|
+
class NullObject
|
7
|
+
def method_missing(name, *args, &block)
|
8
|
+
nil
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.maybe(value)
|
12
|
+
case value
|
13
|
+
when nil then NullObject.new
|
14
|
+
else value
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
require_relative './spec_helper'
|
2
|
+
|
3
|
+
describe("GeoEngineer::Environment") do
|
4
|
+
describe 'validations' do
|
5
|
+
it 'should have unique terrform id' do
|
6
|
+
env = GeoEngineer::Environment.new("test") {
|
7
|
+
region "us-west-1"
|
8
|
+
account_id 1
|
9
|
+
}
|
10
|
+
env.resource('type', 'id1') {
|
11
|
+
_terraform_id "tid"
|
12
|
+
_geo_id 'gid1'
|
13
|
+
}
|
14
|
+
env.resource('type', 'id2') {
|
15
|
+
_terraform_id "tid"
|
16
|
+
_geo_id 'gid2'
|
17
|
+
}
|
18
|
+
expect(env.all_resources.length).to eq 2
|
19
|
+
expect(env.errors.length).to eq 1
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'should have unique geo_id' do
|
23
|
+
env = GeoEngineer::Environment.new("test") {
|
24
|
+
region "us-west-1"
|
25
|
+
account_id 1
|
26
|
+
}
|
27
|
+
env.resource('type', 'id1') {
|
28
|
+
_terraform_id "tid1"
|
29
|
+
_geo_id 'gid'
|
30
|
+
}
|
31
|
+
env.resource('type', 'id2') {
|
32
|
+
_terraform_id "tid2"
|
33
|
+
_geo_id 'gid'
|
34
|
+
}
|
35
|
+
expect(env.all_resources.length).to eq 2
|
36
|
+
expect(env.errors.length).to eq 1
|
37
|
+
end
|
38
|
+
|
39
|
+
it 'should have unique type and ids' do
|
40
|
+
env = GeoEngineer::Environment.new("test") {
|
41
|
+
region "us-west-1"
|
42
|
+
account_id 1
|
43
|
+
}
|
44
|
+
env.resource('type', 'id1') {
|
45
|
+
_terraform_id "tid1"
|
46
|
+
_geo_id 'gid1'
|
47
|
+
}
|
48
|
+
env.resource('type', 'id1') {
|
49
|
+
_terraform_id "tid2"
|
50
|
+
_geo_id 'gid2'
|
51
|
+
}
|
52
|
+
expect(env.all_resources.length).to eq 2
|
53
|
+
expect(env.errors.length).to eq 1
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
describe '#codifies_resources' do
|
58
|
+
it 'should return both codified and uncodified resources' do
|
59
|
+
class GeoEngineer::Resources::CodifiedResource < GeoEngineer::Resource
|
60
|
+
def self._fetch_remote_resources
|
61
|
+
[{ _geo_id: "geo_id1" }, { _geo_id: "geo_id2" }]
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
env = GeoEngineer::Environment.new("test")
|
66
|
+
env.resource('codified_resource', 'id1') {
|
67
|
+
_terraform_id "geo_id1"
|
68
|
+
}
|
69
|
+
expect(env.codified_resources('codified_resource').length).to eq 1
|
70
|
+
expect(env.uncodified_resources('codified_resource').length).to eq 1
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe '#to_terraform_state' do
|
75
|
+
it 'should return state of resources' do
|
76
|
+
env = GeoEngineer::Environment.new("test")
|
77
|
+
env.resource('type', 'id1') {
|
78
|
+
_terraform_id "tid"
|
79
|
+
_geo_id 'gid1'
|
80
|
+
}
|
81
|
+
tfstate = env.to_terraform_state
|
82
|
+
expect(tfstate[:modules].first[:resources].length).to eq 1
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
describe '#to_terraform_json' do
|
87
|
+
it 'should return terraform of all resources' do
|
88
|
+
env = GeoEngineer::Environment.new("test")
|
89
|
+
env.resource('type', 'id1') {
|
90
|
+
_terraform_id "tid"
|
91
|
+
_geo_id 'gid1'
|
92
|
+
}
|
93
|
+
tfjson = env.to_terraform_json
|
94
|
+
expect(tfjson[:resource].length).to eq 1
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe '#project' do
|
99
|
+
it 'should create a project with this as environment' do
|
100
|
+
env = GeoEngineer::Environment.new("test")
|
101
|
+
env.project("org", "name") {
|
102
|
+
environments 'test'
|
103
|
+
}
|
104
|
+
expect(env.projects.length).to eq 1
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'should only load projects in the environment' do
|
108
|
+
env = GeoEngineer::Environment.new("test")
|
109
|
+
p0 = env.project("org", "0") {
|
110
|
+
environments 'test'
|
111
|
+
}
|
112
|
+
|
113
|
+
p1 = env.project("org", "1") {
|
114
|
+
environments 'nottest'
|
115
|
+
}
|
116
|
+
|
117
|
+
expect(p0.class).to eq GeoEngineer::Project
|
118
|
+
expect(p1.class).to eq NullObject
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
describe '#all_resources' do
|
123
|
+
it 'should include local and project resources (if project in env)' do
|
124
|
+
env = GeoEngineer::Environment.new("test")
|
125
|
+
env.resource('type', 'id0') { x 2 }
|
126
|
+
|
127
|
+
p0 = env.project("org", "0") {
|
128
|
+
environments 'test'
|
129
|
+
}
|
130
|
+
p0.resource('type', 'id1') { x 2 }
|
131
|
+
|
132
|
+
p1 = env.project("org", "1") {
|
133
|
+
environments 'nottest'
|
134
|
+
}
|
135
|
+
p1.resource('type', 'id2') { x 2 }
|
136
|
+
|
137
|
+
expect(env.all_resources.length).to eq 2
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
data/spec/output_spec.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
require_relative './spec_helper'
|
2
|
+
|
3
|
+
describe("GeoEngineer::Project") do
|
4
|
+
class OutModuleTemplate < GeoEngineer::Template
|
5
|
+
attr_reader :res1, :res2
|
6
|
+
|
7
|
+
def initialize(name, project, parameters)
|
8
|
+
super(name, project, parameters)
|
9
|
+
|
10
|
+
res1 = resource('type', '1') {
|
11
|
+
name "Resource1"
|
12
|
+
param parameters[:res1]
|
13
|
+
}
|
14
|
+
|
15
|
+
res2 = resource('type', '2') {
|
16
|
+
name "Resource2"
|
17
|
+
rel res1
|
18
|
+
}
|
19
|
+
|
20
|
+
@res1 = res1
|
21
|
+
@res2 = res2
|
22
|
+
end
|
23
|
+
|
24
|
+
def template_resources
|
25
|
+
[@res1, @res2]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class GeoEngineer::Templates::InModuleTemplate < GeoEngineer::Template
|
30
|
+
end
|
31
|
+
|
32
|
+
describe 'validations' do
|
33
|
+
it 'should validate its resources' do
|
34
|
+
project = GeoEngineer::Project.new('org', "project_name", nil)
|
35
|
+
project.environments = 'test'
|
36
|
+
project.resource('res', 'id') {
|
37
|
+
x 10
|
38
|
+
}
|
39
|
+
expect(project.errors.length).to eq 1 # geo_id nil
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should validate it has an environmnet' do
|
43
|
+
project = GeoEngineer::Project.new('org', "project_name", nil)
|
44
|
+
expect(project.errors.length).to eq 1
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe '#from_template' do
|
49
|
+
it 'should create a template from a class' do
|
50
|
+
project = GeoEngineer::Project.new('org', "project_name", nil)
|
51
|
+
temp1 = project.from_template('in_module_template', 'in')
|
52
|
+
temp2 = project.from_template('out_module_template', 'out')
|
53
|
+
expect(temp1.template_resources.length).to eq 0
|
54
|
+
expect(temp2.template_resources.length).to eq 2
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should error if the template is not found' do
|
58
|
+
project = GeoEngineer::Project.new('org', "project_name", nil)
|
59
|
+
expect { project.from_template('not_a_template') }.to raise_error(StandardError)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe '#all_resources' do
|
64
|
+
it 'should return all resources created in templates and directly' do
|
65
|
+
project = GeoEngineer::Project.new('org', "project_name", nil)
|
66
|
+
project.resource('res', 'id') { x 10 }
|
67
|
+
project.from_template('out_module_template', 'out')
|
68
|
+
expect(project.all_resources.length).to eq 3
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe '#resource' do
|
73
|
+
it 'should create a resource and assign itself as project' do
|
74
|
+
project = GeoEngineer::Project.new('org', "project_name", nil)
|
75
|
+
res = project.resource('res', 'id') { x 10 }
|
76
|
+
expect(res.project).to eq project
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|