geoengineer 0.1.1 → 0.1.2
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 +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],
|