def test_duplicate_key_collisions(): """When creating two different types of Provider objects they would collide with each other during recursive update because they had the same __hash__ value The fix was use the hash() value of the key being provide PLUS our incremented ID This test covers that by making sure that all of the expected providers are in our compiled output. """ TFObject.reset() Provider("aws", alias="aws1") Provider("aws", alias="aws2") Provider("mysql", alias="mysql1") Provider("mysql", alias="mysql2") assert len(Provider._instances) == 4 compiled = Provider.compile() seen = [] for data in six.itervalues(compiled["provider"]): seen.append(data["alias"]) seen.sort() assert seen == ["aws1", "aws2", "mysql1", "mysql2"]
def test_provider(): TFObject.reset() Provider("mysql", host="db-wordpress") Provider("mysql", host="db-finpro") result = json.dumps(TFObject.compile(), sort_keys=True) desired = '{"provider": {"mysql": {"host": "db-wordpress"}, "mysql": {"host": "db-finpro"}}}' assert result == desired
def test_provider(): TFObject.reset() Provider("mysql", host="db-wordpress") Provider("mysql", host="db-finpro") compiled = TFObject.compile() seen = [] for data in six.itervalues(compiled["provider"]): seen.append(data["host"]) seen.sort() assert seen == ["db-finpro", "db-wordpress"]
def test_named_object_hooks(mocker): TFObject.reset() def aws_hook(attrs): new_attrs = attrs.copy() new_attrs["region"] = "us-east-1" return new_attrs mock_hook = mocker.MagicMock(side_effect=aws_hook) Provider.add_hook("aws", mock_hook) Provider("aws", alias="aws1") compiled = TFObject.compile() assert mock_hook.mock_calls == [mocker.call({"alias": "aws1"})] # since providers use DuplicateKey as their key we need to json dump to compare equality here assert json.dumps(compiled) == json.dumps( {"provider": { "aws": { "alias": "aws1", "region": "us-east-1" } }})
def config(self): name = self.name region = self.region private_number = self.private_number public_number = self.public_number Provider("aws", region=region) params = dict( source=self.module("aws-vps"), name=name, cidr="10.0.0.0/16", azs=[region + "a", region + "b"], private_subnets=[ "10.0.{}.0/24".format(k) for k in range(1, private_number + 1) ], public_subnets=[ "10.0.10{}.0/24".format(k) for k in range(1, public_number + 1) ], enable_ipv6="true", enable_nat_gateway="true", single_nat_gateway="true", public_subnet_tags={"Name": "overridden-name-public"}, tags={ "Owner": "user", "Environment": "dev" }, vpc_tags={"Name": name}, ) Module(name, **params)
def render(stackvars): # Terraform configuration. Terraform(required_version=stackvars.get("config.terraform.version")) # Backend configuration. Terraform( dict(backend=dict(gcs=dict( bucket=stackvars.get("config.terraform.backend.gcp.bucket"), prefix=stackvars.stack, credentials=stackvars.get("config.gcp.credentials"), )))) # Providers. Provider("google", **stackvars.get("config.gcp")) # Modules. # Resources. cluster = Resource( "google_container_cluster", "cluster", name="project-" + stackvars.environment, location=stackvars.get("config.gcp.region"), # The API requires a node pool or an initial count to be defined; that initial # count creates the "default node pool" with that # of nodes. So, we need to set # an initial_node_count of 1. This will make a default node pool with # server-defined defaults that Terraform will immediately delete as part of # Create. This leaves us in our desired state- with a cluster master with no # node pools. remove_default_node_pool=True, initial_node_count=1, ) Resource( "google_container_node_pool", "preemptible_nodes", name="preemptible-node-pool", location=stackvars.get("config.gcp.region"), cluster=cluster.name, # `node_count` represents the number of nodes PER ZONE. node_count=1, node_config=dict( preemptible=True, machine_type="n1-standard-1", oauth_scopes=[ "https://www.googleapis.com/auth/logging.write", "https://www.googleapis.com/auth/monitoring", ], ), # `node_count` represents the number of nodes PER ZONE. autoscaling=dict( min_node_count=1, max_node_count=3, ), management=dict( auto_repair=True, auto_upgrade=True, ), )
def test_explicit_provider(): # When a resource is given an explicit provider argument it should take precendence # Even if we're in a provider resource block p1 = Provider("aws", region="us-west-2", alias="west2") with Provider("aws", region="us-east-1", alias="east1"): sg1 = Resource("aws_security_group", "sg", ingress=["foo"], provider=p1.as_provider()) sg2 = Resource("aws_security_group", "sg", ingress=["foo"]) with Provider("aws", region="eu-west-2", alias="london"): sg3 = Resource("aws_security_group", "sg", ingress=["foo"]) assert sg1.provider == "aws.west2" assert sg2.provider == "aws.east1" assert sg3.provider == "aws.london"
def test_equality(): # NamedObject p1 = Provider("mysql", host="db") p2 = Provider("mysql", host="db") v1 = Variable("mysql", host="db") assert p1 == p2 assert p1 != v1 # TypedObject r1 = Resource("aws_security_group", "sg", name="sg") r2 = Resource("aws_security_group", "sg", name="sg") d1 = Data("aws_security_group", "sg", name="sg") assert r1 == r2 assert r1 != d1 # Invalid comparisons assert r1 != "string" assert r1 != 0
def test_provider_context(): with Provider("aws", region="us-east-1", alias="east1"): sg1 = Resource("aws_security_group", "sg", ingress=["foo"]) # Since thing1 is not an aws_ resource it will not get the provider by default thing1 = Resource("some_thing", "foo", bar="baz") # var1 is not a typedobject so it will not get a provider either var1 = Variable("var1", default="foo") with Provider("aws", region="us-west-2", alias="west2"): sg2 = Resource("aws_security_group", "sg", ingress=["foo"]) assert sg1.provider == "aws.east1" assert sg2.provider == "aws.west2" # thing1's provider is the default interpolation string assert thing1.provider == "${some_thing.foo.provider}" # var1 will raise a AttributeError with pytest.raises(AttributeError): assert var1.provider
def test_provider_context(): with Provider("aws", region="us-east-1", alias="east1"): sg1 = Resource('aws_security_group', 'sg', ingress=['foo']) # Since thing1 is not an aws_ resource it will not get the provider by default thing1 = Resource('some_thing', 'foo', bar='baz') # var1 is not a typedobject so it will not get a provider either var1 = Variable('var1', default='foo') with Provider("aws", region="us-west-2", alias="west2"): sg2 = Resource('aws_security_group', 'sg', ingress=['foo']) assert sg1.provider == 'aws.east1' assert sg2.provider == 'aws.west2' # thing1's provider is the default interpolation string assert thing1.provider == '${some_thing.foo.provider}' # var1 will raise a AttributeError with pytest.raises(AttributeError): assert var1.provider
In this example the VPC data we pull in from the remote state has 3 AZs/subnets that want to spread our spot fleet our across. """ from terraformpy import Data, Provider, Resource # we build our launch configs based on the following data # each key should be an instance type and the value should be a tuple: (price, vCPUs) spot_config = { 'c4.large': (0.105, 2), 'c4.xlarge': (0.209, 4), 'c4.2xlarge': (0.419, 8), } Provider('aws', region='us-west-2', profile='nwdev') vpc = Data('terraform_remote_state', 'vpc', backend='s3', config=dict(bucket='nw-terraform', key='devops/vpc.tfstate', region='us-east-1', profile='nwprod')) ami = Data('aws_ami', 'ecs_ami', most_recent=True, filter=[ dict(name='name', values=['*amazon-ecs-optimized']), dict(name='owner-alias', values=['amazon'])
# each key should be an instance type and the value should be a tuple: (price, vCPUs) spot_config = { "c4.large": (0.105, 2), "c4.xlarge": (0.209, 4), "c4.2xlarge": (0.419, 8), } Terraform(backend=dict(s3=dict( region="us-east-1", bucket="terraform-tfstate-bucket", key="terraform.tfstate", workspace_key_prefix="my_prefix", dynamodb_table="terraform_locks", ))) Provider("aws", region="us-west-2", profile="nwdev") vpc = Data( "terraform_remote_state", "vpc", backend="s3", config=dict( bucket="nw-terraform", key="devops/vpc.tfstate", region="us-east-1", profile="nwprod", ), ) ami = Data( "aws_ami",
from terraformpy import Provider #Define project and region in the variables below project = "define_project_here" region = "define_region_here" Provider("google", project=project, region=region)