geoengineer 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/README.md +18 -8
- data/lib/geoengineer/cli/geo_cli.rb +4 -1
- data/lib/geoengineer/environment.rb +1 -1
- data/lib/geoengineer/resources/aws_cloudtrail.rb +20 -0
- data/lib/geoengineer/resources/aws_cloudwatch_event_rule.rb +26 -0
- data/lib/geoengineer/resources/aws_cloudwatch_event_target.rb +50 -0
- data/lib/geoengineer/resources/aws_db_instance.rb +5 -1
- data/lib/geoengineer/resources/aws_dynamodb_table.rb +24 -0
- data/lib/geoengineer/resources/aws_elasticache_cluster.rb +22 -9
- data/lib/geoengineer/resources/aws_iam_policy.rb +1 -0
- data/lib/geoengineer/resources/aws_iam_role_policy.rb +63 -0
- data/lib/geoengineer/resources/aws_kinesis_stream.rb +40 -0
- data/lib/geoengineer/resources/aws_lambda_alias.rb +18 -3
- data/lib/geoengineer/resources/aws_lambda_function.rb +11 -0
- data/lib/geoengineer/resources/aws_lambda_permission.rb +9 -0
- data/lib/geoengineer/resources/aws_load_balancer_backend_server_policy.rb +48 -0
- data/lib/geoengineer/resources/aws_load_balancer_policy.rb +43 -0
- data/lib/geoengineer/resources/aws_network_acl_rule.rb +27 -2
- data/lib/geoengineer/resources/aws_redshift_cluster.rb +10 -4
- data/lib/geoengineer/resources/aws_route.rb +2 -0
- data/lib/geoengineer/resources/aws_vpn_gateway_attachment.rb +8 -0
- data/lib/geoengineer/sub_resource.rb +13 -3
- data/lib/geoengineer/utils/aws_clients.rb +18 -2
- data/lib/geoengineer/utils/has_projects.rb +3 -1
- data/lib/geoengineer/utils/has_validations.rb +7 -0
- data/lib/geoengineer/version.rb +1 -1
- data/spec/resource_spec.rb +14 -0
- data/spec/resources/aws_cloudtrail_spec.rb +35 -0
- data/spec/resources/aws_cloudwatch_event_rule_spec.rb +33 -0
- data/spec/resources/aws_cloudwatch_event_target_spec.rb +54 -0
- data/spec/resources/aws_dynamodb_table_spec.rb +24 -0
- data/spec/resources/aws_iam_role_spec.rb +21 -18
- data/spec/resources/aws_iam_rule_policy_spec.rb +49 -0
- data/spec/resources/{aws_iam_user.rb → aws_iam_user_spec.rb} +9 -6
- data/spec/resources/aws_kinesis_stream_spec.rb +52 -0
- data/spec/resources/aws_lambda_alias_spec.rb +22 -3
- data/spec/resources/aws_load_balancer_backend_server_policy_spec.rb +42 -0
- data/spec/resources/aws_load_balancer_policy_spec.rb +44 -0
- data/spec/resources/aws_network_acl_rule_spec.rb +29 -1
- data/spec/resources/{aws_ses_receipt_rule_set.rb → aws_ses_receipt_rule_set_spec.rb} +13 -6
- data/spec/resources/{aws_ses_receipt_rule.rb → aws_ses_receipt_rule_spec.rb} +6 -5
- data/spec/resources/{aws_sns_topic_subscription.rb → aws_sns_topic_subscription_spec.rb} +0 -0
- data/spec/resources/aws_subnet_spec.rb +2 -2
- data/spec/resources/aws_vpc_dhcp_options_association_spec.rb +2 -2
- data/spec/resources/aws_vpc_spec.rb +2 -2
- data/spec/sub_resource_spec.rb +12 -0
- data/spec/utils/has_subresources_spec.rb +9 -0
- data/spec/utils/has_validations_spec.rb +23 -3
- metadata +34 -10
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dda3981b643cb0887fcdb1e794abfa4b8c6ac9c0
|
4
|
+
data.tar.gz: 68d052b3c9cd6a7a3f77571837cfda41b1413161
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8b2bae296535675da928d1decd4e9d96f448876642e953f40d50e6f4ed919ddb3cd6bebc89380a19dddf27305735d8ed2d212af29485baf42ccd582a54751432
|
7
|
+
data.tar.gz: 7e9eb34de6c0d0cb88d2f182ed1e618570404d30bc6c84f97c3a04bd13544e2191ba4bb82cc29e1e333f554881701f1630702072a60dea4ae005ca04d303a434
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/README.md
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
<a href="https://commons.wikimedia.org/wiki/File:Mantle_of_Responsibility.png"><img src="./assets/mantle.png" align="right" alt="Mantle_of_Responsibility" /></a>
|
6
6
|
|
7
|
-
GeoEngineer provides a Ruby DSL and command line tool (`geo`) to *
|
7
|
+
GeoEngineer provides a Ruby DSL and command line tool (`geo`) to *codify* then plan and execute changes to cloud resources.
|
8
8
|
|
9
9
|
GeoEngineer's goals/requirements/features are:
|
10
10
|
|
@@ -29,9 +29,19 @@ Instructions to install Ruby can be found [here](https://www.ruby-lang.org/en/do
|
|
29
29
|
|
30
30
|
### Install GeoEngineer
|
31
31
|
|
32
|
+
Secure install (this will validate the geoengineer gem):
|
33
|
+
|
34
|
+
```
|
35
|
+
gem cert --add <(curl -Ls https://raw.githubusercontent.com/coinbase/geoengineer/master/certs/geoengineer-gem.pem)
|
36
|
+
gem install geoengineer --trust-policy MediumSecurity
|
37
|
+
```
|
38
|
+
|
39
|
+
*Note: HighSecurity will not work because aws-sdk and other gems are not signed*
|
40
|
+
|
41
|
+
Or just install normally:
|
42
|
+
|
32
43
|
```
|
33
|
-
gem
|
34
|
-
gem install geoengineer --trust-policy HighSecurity
|
44
|
+
gem install geoengineer
|
35
45
|
```
|
36
46
|
|
37
47
|
Test it is installed correctly with:
|
@@ -353,7 +363,7 @@ The core models in GeoEngineer are:
|
|
353
363
|
|
354
364
|
1. `Environment` contains many resources that may exist outside of a project, like VPCs or routing tables. Also every project defined to be in the environment, for example the `test_www` project is in `staging` but `monorail` is in `staging` and `production` environments.
|
355
365
|
2. `Project` contains many resources and services grouped together into a name.
|
356
|
-
3. `Template` has a `type` and `name`, and a group of resources that are defined in a pattern, e.g. every Load Balancer requires a unique security group that allows traffic in. It is
|
366
|
+
3. `Template` has a `type` and `name`, and a group of resources that are defined in a pattern, e.g. every Load Balancer requires a unique security group that allows traffic in. It is a simple abstraction that can dramatically simplify and standardize cloud resources.
|
357
367
|
4. `Resource` and `SubResource` are based off of how terraform models cloud resources. A `Resource` instance can have many `SubResource` instances, but a `SubResource` instance belongs to only one `Resource` instance, e.g. a load balancer resource may have a `health_check` sub-resource to only allow specific incoming ports.
|
358
368
|
|
359
369
|
All these models can have arbitrary attributes assigned to them either by directly assigning on the instance, or through passing a block to the constructor. For example:
|
@@ -390,7 +400,7 @@ puts resource.lazy_attr
|
|
390
400
|
|
391
401
|
### Environment
|
392
402
|
|
393
|
-
The top level class in GeoEngineer is the `environment
|
403
|
+
The top level class in GeoEngineer is the `environment`: it contains all projects, resources and services, and there should only ever be one initialized at a time.
|
394
404
|
|
395
405
|
An environment can mean many things to different people, e.g. an AWS account, an AWS region, or a specific AWS VPC. The only real constraint is that a resource has one instance per environment, e.g. a load balancer that is defined to be in `staging` and `production` environments, will have an instance in each.
|
396
406
|
|
@@ -418,14 +428,14 @@ project = project('org', 'project_name') {
|
|
418
428
|
|
419
429
|
This projects organization is `org`, its name `project_name` and will be provisioned in the `staging` and `production` environments. The `org` and `name` must be unique across all other projects.
|
420
430
|
|
421
|
-
The method `project` will automatically add the project to the instantiated environment object **only if** that
|
431
|
+
The method `project` will automatically add the project to the instantiated environment object **only if** that environment's name is in the list of environments, otherwise it is ignored.
|
422
432
|
|
423
433
|
### Templates
|
424
434
|
|
425
435
|
A template is used to create a group of resources in a recommended pattern. For example, an HTTP service could create a load balancer, a load balancer security group, and a ec2 security group.
|
426
436
|
|
427
437
|
```ruby
|
428
|
-
template_instance = project.from_template('template_type', 'name',
|
438
|
+
template_instance = project.from_template('template_type', 'name', parameter: 'helloworld') { |resource, resource_sg|
|
429
439
|
|
430
440
|
# set attribute
|
431
441
|
attribute "custom attribute"
|
@@ -471,6 +481,6 @@ template.resource('type', 'identifier') {
|
|
471
481
|
|
472
482
|
The `type` of a resource must be a valid terraform type, where AWS types are listed [here](https://www.terraform.io/docs/providers/aws/index.html). Some resources are not supported yet by GeoEngineer.
|
473
483
|
|
474
|
-
`identifier` is used by GeoEngineer and terraform to reference this resource
|
484
|
+
`identifier` is used by GeoEngineer and terraform to reference this resource must be unique, however it is not stored in the cloud so can be changed without affecting a plan.
|
475
485
|
|
476
486
|
A resource also has a ruby block sent to it that contains parameters and sub-resources. These values are defined by terraform so for reference to what values are required please refer to the [terraform docs](https://www.terraform.io/docs/providers/aws/index.html).
|
@@ -140,7 +140,10 @@ class GeoCLI
|
|
140
140
|
|
141
141
|
@environment.execute_lifecycle(:before, action_name.to_sym)
|
142
142
|
errs = @environment.errors.flatten.sort
|
143
|
-
|
143
|
+
unless errs.empty?
|
144
|
+
print_validation_errors(errs)
|
145
|
+
exit 1
|
146
|
+
end
|
144
147
|
|
145
148
|
yield args, options
|
146
149
|
@environment.execute_lifecycle(:after, action_name.to_sym)
|
@@ -64,7 +64,7 @@ class GeoEngineer::Environment
|
|
64
64
|
# do not add the project if the project is not supported by this environment
|
65
65
|
return NullObject.new unless supported_environments.include?(@name)
|
66
66
|
|
67
|
-
|
67
|
+
project
|
68
68
|
end
|
69
69
|
|
70
70
|
def resource(type, id, &block)
|
@@ -0,0 +1,20 @@
|
|
1
|
+
########################################################################
|
2
|
+
# AwsCloudTrail is the +aws_cloudtrail+ terrform resource,
|
3
|
+
#
|
4
|
+
# {https://www.terraform.io/docs/providers/aws/r/cloudtrail.html}
|
5
|
+
########################################################################
|
6
|
+
class GeoEngineer::Resources::AwsCloudtrail < GeoEngineer::Resource
|
7
|
+
validate -> { validate_required_attributes([:name, :s3_bucket_name]) }
|
8
|
+
|
9
|
+
after :initialize, -> { _terraform_id -> { name } }
|
10
|
+
|
11
|
+
def self._fetch_remote_resources
|
12
|
+
cloudtrails = AwsClients.cloudtrail.describe_trails["trail_list"].map(&:to_h)
|
13
|
+
|
14
|
+
cloudtrails.map do |ct|
|
15
|
+
ct[:_terraform_id] = ct[:name]
|
16
|
+
ct[:_geo_id] = ct[:name]
|
17
|
+
ct
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
########################################################################
|
2
|
+
# AwsCloudwatchEventRule is the +aws_cloudwatch_event_rule+ terrform resource,
|
3
|
+
#
|
4
|
+
# {https://www.terraform.io/docs/providers/aws/r/cloudwatch_event_rule.html Terraform Docs}
|
5
|
+
########################################################################
|
6
|
+
class GeoEngineer::Resources::AwsCloudwatchEventRule < GeoEngineer::Resource
|
7
|
+
validate -> { validate_required_attributes([:name, :schedule_expression]) }
|
8
|
+
|
9
|
+
after :initialize, -> { _terraform_id -> { NullObject.maybe(remote_resource)._terraform_id } }
|
10
|
+
after :initialize, -> { _geo_id -> { self[:name] } }
|
11
|
+
|
12
|
+
def support_tags?
|
13
|
+
false
|
14
|
+
end
|
15
|
+
|
16
|
+
def self._fetch_remote_resources
|
17
|
+
AwsClients.cloudwatchevents.list_rules.rules.map(&:to_h).map do |cloudwatch_event_rule|
|
18
|
+
cloudwatch_event_rule.merge(
|
19
|
+
{
|
20
|
+
_terraform_id: cloudwatch_event_rule[:name],
|
21
|
+
_geo_id: cloudwatch_event_rule[:name]
|
22
|
+
}
|
23
|
+
)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
########################################################################
|
2
|
+
# AwsCloudwatchEventTarget is the +aws_cloudwatch_event_target+ terrform resource,
|
3
|
+
#
|
4
|
+
# {https://www.terraform.io/docs/providers/aws/r/cloudwatch_event_target.html Terraform Docs}
|
5
|
+
########################################################################
|
6
|
+
class GeoEngineer::Resources::AwsCloudwatchEventTarget < GeoEngineer::Resource
|
7
|
+
validate -> { validate_required_attributes([:rule, :arn, :target_id]) }
|
8
|
+
|
9
|
+
after :initialize, -> { _terraform_id -> { NullObject.maybe(remote_resource)._terraform_id } }
|
10
|
+
after :initialize, -> { _geo_id -> { "#{self.rule}-#{self.target_id}" } }
|
11
|
+
|
12
|
+
def to_terraform_state
|
13
|
+
tfstate = super
|
14
|
+
tfstate[:primary][:attributes] = {
|
15
|
+
'target_id' => self.target_id,
|
16
|
+
'rule' => self.rule
|
17
|
+
}
|
18
|
+
tfstate
|
19
|
+
end
|
20
|
+
|
21
|
+
def support_tags?
|
22
|
+
false
|
23
|
+
end
|
24
|
+
|
25
|
+
def self._fetch_remote_resources
|
26
|
+
AwsClients
|
27
|
+
.cloudwatchevents
|
28
|
+
.list_rules
|
29
|
+
.rules
|
30
|
+
.map(&:to_h)
|
31
|
+
.map { |rule| _get_rule_targets(rule) }
|
32
|
+
.flatten
|
33
|
+
.map do |rule_target|
|
34
|
+
rule_target.merge(
|
35
|
+
{
|
36
|
+
_terraform_id: "#{rule_target[:rule_name]}-#{rule_target[:id]}",
|
37
|
+
_geo_id: "#{rule_target[:rule_name]}-#{rule_target[:id]}"
|
38
|
+
}
|
39
|
+
)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def self._get_rule_targets(rule)
|
44
|
+
AwsClients
|
45
|
+
.cloudwatchevents
|
46
|
+
.list_targets_by_rule({ rule: rule[:name] })[:targets]
|
47
|
+
.map(&:to_h)
|
48
|
+
.map { |target| target.merge({ rule_name: rule[:name] }) }
|
49
|
+
end
|
50
|
+
end
|
@@ -14,7 +14,11 @@ class GeoEngineer::Resources::AwsDbInstance < GeoEngineer::Resource
|
|
14
14
|
)
|
15
15
|
end
|
16
16
|
}
|
17
|
-
validate -> {
|
17
|
+
validate -> {
|
18
|
+
if new? && !(snapshot_identifier || replicate_source_db)
|
19
|
+
validate_required_attributes([:password, :username, :name])
|
20
|
+
end
|
21
|
+
}
|
18
22
|
validate -> { validate_required_attributes([:instance_class, :engine]) }
|
19
23
|
validate -> { validate_subresource_required_attributes(:access_logs, [:bucket]) }
|
20
24
|
|
@@ -0,0 +1,24 @@
|
|
1
|
+
########################################################################
|
2
|
+
# AwsDynamodbTable +aws_dynamodb_table+ terrform resource,
|
3
|
+
#
|
4
|
+
# {https://www.terraform.io/docs/providers/aws/r/aws_dynamodb_table.html Terraform Docs}
|
5
|
+
########################################################################
|
6
|
+
class GeoEngineer::Resources::AwsDynamodbTable < GeoEngineer::Resource
|
7
|
+
validate -> { validate_required_attributes([:name, :read_capacity, :write_capacity, :hash_key]) }
|
8
|
+
|
9
|
+
after :initialize, -> { _terraform_id -> { name } }
|
10
|
+
|
11
|
+
def support_tags?
|
12
|
+
false
|
13
|
+
end
|
14
|
+
|
15
|
+
def self._fetch_remote_resources
|
16
|
+
AwsClients.dynamo.list_tables['table_names'].map { |name|
|
17
|
+
{
|
18
|
+
name: name,
|
19
|
+
_geo_id: name,
|
20
|
+
_terraform_id: name
|
21
|
+
}
|
22
|
+
}
|
23
|
+
end
|
24
|
+
end
|
@@ -4,6 +4,8 @@
|
|
4
4
|
# {https://www.terraform.io/docs/providers/aws/r/elasticache_cluster.html Terraform Docs}
|
5
5
|
########################################################################
|
6
6
|
class GeoEngineer::Resources::AwsElasticacheCluster < GeoEngineer::Resource
|
7
|
+
class SecurityGroupError < StandardError; end
|
8
|
+
|
7
9
|
validate -> {
|
8
10
|
validate_required_attributes(
|
9
11
|
[
|
@@ -21,14 +23,17 @@ class GeoEngineer::Resources::AwsElasticacheCluster < GeoEngineer::Resource
|
|
21
23
|
|
22
24
|
def to_terraform_state
|
23
25
|
tfstate = super
|
24
|
-
attributes = {
|
25
|
-
'port' => port.to_s,
|
26
|
-
'parameter_group_name' => parameter_group_name
|
27
|
-
}
|
26
|
+
attributes = { 'port' => port.to_s, 'parameter_group_name' => parameter_group_name }
|
28
27
|
|
29
28
|
# Security groups workaround
|
30
29
|
security_group_ids.each_with_index do |sg, i|
|
31
|
-
|
30
|
+
if sg.is_a?(GeoEngineer::Resource)
|
31
|
+
attributes["security_group_ids.#{i}"] = sg._terraform_id
|
32
|
+
elsif sg.is_a?(String)
|
33
|
+
attributes["security_group_ids.#{i}"] = sg
|
34
|
+
else
|
35
|
+
raise SecurityGroupError, "Please pass a Geo Resource or string ID"
|
36
|
+
end
|
32
37
|
end
|
33
38
|
attributes['security_group_ids.#'] = security_group_ids.count.to_s
|
34
39
|
|
@@ -41,10 +46,18 @@ class GeoEngineer::Resources::AwsElasticacheCluster < GeoEngineer::Resource
|
|
41
46
|
end
|
42
47
|
|
43
48
|
def self._fetch_remote_resources
|
44
|
-
AwsClients
|
45
|
-
|
46
|
-
|
47
|
-
|
49
|
+
AwsClients
|
50
|
+
.elasticache
|
51
|
+
.describe_cache_clusters['cache_clusters']
|
52
|
+
.map(&:to_h)
|
53
|
+
.select { |ec| ec[:replication_group_id].nil? }
|
54
|
+
.map do |ec|
|
55
|
+
ec.merge(
|
56
|
+
{
|
57
|
+
_terraform_id: ec[:cache_cluster_id],
|
58
|
+
_geo_id: ec[:cache_cluster_id]
|
59
|
+
}
|
60
|
+
)
|
48
61
|
end
|
49
62
|
end
|
50
63
|
end
|
@@ -5,6 +5,7 @@
|
|
5
5
|
########################################################################
|
6
6
|
class GeoEngineer::Resources::AwsIamPolicy < GeoEngineer::Resource
|
7
7
|
validate -> { validate_required_attributes([:name, :policy]) }
|
8
|
+
validate -> { validate_policy_length(self.policy) }
|
8
9
|
|
9
10
|
after :initialize, -> {
|
10
11
|
_terraform_id -> { NullObject.maybe(remote_resource)._terraform_id }
|
@@ -0,0 +1,63 @@
|
|
1
|
+
########################################################################
|
2
|
+
# AwsIamRolePolicy +aws_iam_role_policy+ terrform resource,
|
3
|
+
#
|
4
|
+
# {https://www.terraform.io/docs/providers/aws/r/iam_role_policy.html Terraform Docs}
|
5
|
+
########################################################################
|
6
|
+
class GeoEngineer::Resources::AwsIamRolePolicy < GeoEngineer::Resource
|
7
|
+
validate -> { validate_required_attributes([:name, :policy, :role]) }
|
8
|
+
validate -> { validate_policy_length(self.policy) }
|
9
|
+
|
10
|
+
after :initialize, -> {
|
11
|
+
_terraform_id -> { "#{role}:#{name}" }
|
12
|
+
}
|
13
|
+
|
14
|
+
def to_terraform_state
|
15
|
+
tfstate = super
|
16
|
+
attributes = {
|
17
|
+
'policy' => policy,
|
18
|
+
'role' => role,
|
19
|
+
'name' => name
|
20
|
+
}
|
21
|
+
|
22
|
+
tfstate[:primary][:attributes] = attributes
|
23
|
+
|
24
|
+
tfstate
|
25
|
+
end
|
26
|
+
|
27
|
+
def support_tags?
|
28
|
+
false
|
29
|
+
end
|
30
|
+
|
31
|
+
def _policy_file(path, binding_obj = nil)
|
32
|
+
_json_file(:policy, path, binding_obj)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self._fetch_remote_resources
|
36
|
+
AwsClients
|
37
|
+
.iam
|
38
|
+
.list_roles
|
39
|
+
.roles
|
40
|
+
.map(&:to_h)
|
41
|
+
.map { |role| _get_role_policies(role) }
|
42
|
+
.flatten
|
43
|
+
.compact
|
44
|
+
.map { |role_policy| _get_policy(role_policy) }
|
45
|
+
end
|
46
|
+
|
47
|
+
def self._get_role_policies(role)
|
48
|
+
AwsClients
|
49
|
+
.iam
|
50
|
+
.list_role_policies({ role_name: role[:role_name] })
|
51
|
+
.map(&:policy_names)
|
52
|
+
.flatten
|
53
|
+
.map { |policy| { role_name: role[:role_name], policy_name: policy } }
|
54
|
+
end
|
55
|
+
|
56
|
+
def self._get_policy(role_policy)
|
57
|
+
AwsClients
|
58
|
+
.iam
|
59
|
+
.get_role_policy(role_policy)
|
60
|
+
.to_h
|
61
|
+
.merge({ _terraform_id: "#{role_policy[:role_name]}:#{role_policy[:policy_name]}" })
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
########################################################################
|
2
|
+
# AwsKinesisStream is the +aws_kinesis_stream+ terrform resource,
|
3
|
+
#
|
4
|
+
# {https://www.terraform.io/docs/providers/aws/r/aws_kinesis_stream.html Terraform Docs}
|
5
|
+
########################################################################
|
6
|
+
class GeoEngineer::Resources::AwsKinesisStream < GeoEngineer::Resource
|
7
|
+
validate -> { validate_required_attributes([:name, :shard_count]) }
|
8
|
+
validate -> { validate_has_tag(:Name) }
|
9
|
+
|
10
|
+
after :initialize, -> { _terraform_id -> { NullObject.maybe(remote_resource)._terraform_id } }
|
11
|
+
after :initialize, -> { _geo_id -> { self[:name] } }
|
12
|
+
|
13
|
+
def to_terraform_state
|
14
|
+
tfstate = super
|
15
|
+
tfstate[:primary][:attributes] = {
|
16
|
+
'name' => self.name,
|
17
|
+
'shard_count' => self.shard_count.to_s
|
18
|
+
}
|
19
|
+
tfstate
|
20
|
+
end
|
21
|
+
|
22
|
+
def self._all_streams
|
23
|
+
streams = []
|
24
|
+
AwsClients.kinesis.list_streams[:stream_names].each do |stream_name|
|
25
|
+
AwsClients.kinesis.describe_stream({ stream_name: stream_name }).map(&:to_h).map do |stream|
|
26
|
+
streams << stream[:stream_description]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
streams
|
30
|
+
end
|
31
|
+
|
32
|
+
def self._fetch_remote_resources
|
33
|
+
self._all_streams.map do |stream|
|
34
|
+
stream.merge({
|
35
|
+
_terraform_id: stream[:stream_arn],
|
36
|
+
_geo_id: stream[:stream_name]
|
37
|
+
})
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -4,12 +4,18 @@
|
|
4
4
|
# {https://www.terraform.io/docs/providers/aws/r/lambda_alias.html Terraform Docs}
|
5
5
|
########################################################################
|
6
6
|
class GeoEngineer::Resources::AwsLambdaAlias < GeoEngineer::Resource
|
7
|
+
# Note: function_name here actually means function_arn, even though
|
8
|
+
# function_name is also a key on a lambda function.
|
7
9
|
validate -> { validate_required_attributes([:name, :function_name, :function_version]) }
|
8
10
|
validate -> {
|
9
|
-
|
11
|
+
if name && (name =~ /(?!^[0-9]+$)([a-zA-Z0-9\-_]+)/).nil?
|
12
|
+
"#{name} must match: /(?!^[0-9]+$)([a-zA-Z0-9\-_]+)/"
|
13
|
+
end
|
10
14
|
}
|
11
15
|
validate -> {
|
12
|
-
|
16
|
+
if function_version && (function_version =~ /(\$LATEST|[0-9]+)/).nil?
|
17
|
+
"#{function_version} must match: /(\$LATEST|[0-9]+)/"
|
18
|
+
end
|
13
19
|
}
|
14
20
|
|
15
21
|
after :initialize, -> { _terraform_id -> { NullObject.maybe(remote_resource)._terraform_id } }
|
@@ -19,6 +25,15 @@ class GeoEngineer::Resources::AwsLambdaAlias < GeoEngineer::Resource
|
|
19
25
|
false
|
20
26
|
end
|
21
27
|
|
28
|
+
def to_terraform_state
|
29
|
+
tfstate = super
|
30
|
+
tfstate[:primary][:attributes] = {
|
31
|
+
'function_name' => function_name,
|
32
|
+
'name' => name
|
33
|
+
}
|
34
|
+
tfstate
|
35
|
+
end
|
36
|
+
|
22
37
|
# TODO(Brad) - May need to implement solution for pagination...
|
23
38
|
def self._fetch_functions
|
24
39
|
AwsClients
|
@@ -31,7 +46,7 @@ class GeoEngineer::Resources::AwsLambdaAlias < GeoEngineer::Resource
|
|
31
46
|
def self._fetch_aliases(function)
|
32
47
|
options = { function_name: function[:function_name] }
|
33
48
|
AwsClients.lambda.list_aliases(options)[:aliases].map(&:to_h).map do |f_alias|
|
34
|
-
geo_id_components = [f_alias[:name],
|
49
|
+
geo_id_components = [f_alias[:name], function[:function_arn], f_alias[:function_version]]
|
35
50
|
f_alias.merge(
|
36
51
|
{
|
37
52
|
_terraform_id: f_alias[:alias_arn],
|