Terraform with Localstack basic setup doesn't work - terraform-provider-aws

I want to try basic setup for localstack with terraform.
My docker-compose file, from the localstack docs
version: "3.8"
services:
localstack:
container_name: "${LOCALSTACK_DOCKER_NAME-localstack_main}"
image: localstack/localstack
ports:
- "127.0.0.1:4566:4566" # LocalStack Gateway
- "127.0.0.1:4510-4559:4510-4559" # external services port range
- "127.0.0.1:53:53" # DNS config (only required for Pro)
- "127.0.0.1:53:53/udp" # DNS config (only required for Pro)
- "127.0.0.1:443:443" # LocalStack HTTPS Gateway (only required for Pro)
environment:
- DEBUG=1
- LOCALSTACK_HOSTNAME=localhost
- PERSISTENCE=${PERSISTENCE-}
- LAMBDA_EXECUTOR=${LAMBDA_EXECUTOR-}
- LOCALSTACK_API_KEY=${LOCALSTACK_API_KEY-} # only required for Pro
- DOCKER_HOST=unix:///var/run/docker.sock
- SERVICES=s3
volumes:
- "${LOCALSTACK_VOLUME_DIR:-./volume}:/var/lib/localstack"
- "/var/run/docker.sock:/var/run/docker.sock"
My terraform file to create s3 bucket
# Public Cloud Configuration
provider "aws" {
region = "us-east-1"
access_key = "test123"
secret_key = "testabc"
skip_credentials_validation = true
skip_requesting_account_id = true
skip_metadata_api_check = true
endpoints {
s3 = "http://localhost:4566"
}
}
# Create Bucket
resource "aws_s3_bucket" "my_bucket" {
bucket = "bucket"
}
I got the next error when running the command terraform apply
│ Error: creating Amazon S3 (Simple Storage) Bucket (bucket): RequestError: send request failed
│ caused by: Put "http://bucket.localhost:4566/": dial tcp: lookup bucket.localhost on 10.222.50.10:53: no such host
│
│ with aws_s3_bucket.my_bucket,
│ on main.tf line 15, in resource "aws_s3_bucket" "my_bucket":
│ 15: resource "aws_s3_bucket" "my_bucket" {
I'm able to create s3 bucket manually in the localstack with command like
aws --endpoint-url http://localhost:4566 s3 mb s3://user-uploads
docker ps output
c9497bcff0e3 localstack/localstack "docker-entrypoint.sh" 23 minutes ago Up 18 minutes (healthy) 127.0.0.1:53->53/tcp, 127.0.0.1:443->443/tcp, 127.0.0.1:4510-4559->4510-4559/tcp, 127.0.0.1:4566->4566/tcp, 127.0.0.1:53->53/udp, 5678/tcp localstack_main
So why localstack is trying to access some different address like 192.168.178.1:53? Do I need to specify somewhere different address? Checked a number of tutorials and for everyone, the setup works fine.

The issue herein lies with your Terraform configuration. The following code inside main.tf works perfectly with tflocal (LocalStack's wrapper for Terraform CLI):
resource "aws_s3_bucket" "my_bucket" {
bucket = "bucket"
}
tflocal init
tflocal apply
If you don't wish to use tflocal, you would need to have a configuration like this:
provider "aws" {
access_key = "mock_access_key"
secret_key = "mock_secret_key"
region = "us-east-1"
s3_force_path_style = true
skip_credentials_validation = true
skip_metadata_api_check = true
skip_requesting_account_id = true
endpoints {
s3 = "http://s3.localhost.localstack.cloud:4566"
}
}
resource "aws_s3_bucket" "test-bucket" {
bucket = "my-bucket"
}
I hope this helps.

I solve it adding a property in provider aws
s3_use_path_style = true
Sample:
terraform {
required_version = ">= 0.12"
backend local {}
}
provider "aws" {
region = "localhost"
access_key = "local"
secret_key = "local"
skip_region_validation = true
skip_credentials_validation = true
skip_metadata_api_check = true
skip_requesting_account_id = true
s3_use_path_style = true // <<- this property here
endpoints {
dynamodb = "http://localhost:4566"
s3 = "http://localhost:4566"
}
}
// S3
resource "aws_s3_bucket" "my-bucket" {
bucket = "teste"
}
I hope help you

Related

Azure Bicep RG Deployment - Object reference not set to an instance of an object [duplicate]

I'm trying to create a simple App Service Plan with the below code.
param Location string = 'eastus'
resource appServicePlan1 'Microsoft.Web/serverfarms#2020-12-01' = {
name: 'myasp'
location: Location
sku: {
name: 'S1'
capacity: 1
}
}
Below is the Azure CLI command that I'm using to execute the above Bicep script
az deployment group create --name deploy1 --resource-group az-devops-eus-dev-rg1 --template-file main.bicep
Below is the screenshot
All this was working earlier. I'm using the latest version of Bicep (v0.9.1) which is available as of today.
Any pointers on why this is occurring now would be much appreciated.
Just had this issue in a MS workshop. We solved it by adding a empty properties-element to the appServicePlan. Ex.
param Location string = 'eastus'
resource appServicePlan1 'Microsoft.Web/serverfarms#2020-12-01' = {
name: 'myasp'
location: Location
properties: {}
sku: {
name: 'S1'
capacity: 1
}
}

How to retrieve the EKS kubeconfig?

I have defined an aws_eks_cluster and aws_eks_node_group as follows:
resource "aws_eks_cluster" "example" {
count = var.create_eks_cluster ? 1 : 0
name = local.cluster_name
role_arn = aws_iam_role.example[count.index].arn
vpc_config {
subnet_ids = [
aws_subnet.main2.id,
aws_subnet.main3.id
]
security_group_ids = [
module.network.security_group_allow_all_from_client_ip,
module.network.security_group_main_id
]
endpoint_private_access = true
endpoint_public_access = false
}
# Ensure that IAM Role permissions are created before and deleted after EKS Cluster handling.
# Otherwise, EKS will not be able to properly delete EKS managed EC2 infrastructure such as Security Groups.
depends_on = [
aws_iam_role_policy_attachment.example-AmazonEKSClusterPolicy,
aws_iam_role_policy_attachment.example-AmazonEKSVPCResourceController,
]
}
resource "aws_eks_node_group" "example" {
count = var.create_eks_cluster ? 1 : 0
cluster_name = aws_eks_cluster.example[count.index].name
node_group_name = random_uuid.deployment_uuid.result
node_role_arn = aws_iam_role.eks-node-group-example[count.index].arn
subnet_ids = [
aws_subnet.main2.id,
aws_subnet.main3.id
]
scaling_config {
desired_size = 1
max_size = 5
min_size = 1
}
# Ensure that IAM Role permissions are created before and deleted after EKS Node Group handling.
# Otherwise, EKS will not be able to properly delete EC2 Instances and Elastic Network Interfaces.
depends_on = [
aws_iam_role_policy_attachment.example-AmazonEKSWorkerNodePolicy,
aws_iam_role_policy_attachment.example-AmazonEKS_CNI_Policy,
aws_iam_role_policy_attachment.example-AmazonEC2ContainerRegistryReadOnly,
]
}
How can I retrieve the KubeConfig?
I have seen that the kubeconfig is available as an output on the eks module.
Do I need to replace aws_eks_cluster and aws_eks_node_group with the eks module?
The EKS module composes a kubeconfig based on a template.
You can include that template alongside your terraform code.
You will need to provide default values for all the variables in the templatefile function call and reference your own EKS resource name. It's fine to drop all the coalescelist functions too.
e.g.:
locals {
kubeconfig = templatefile("templates/kubeconfig.tpl", {
kubeconfig_name = local.kubeconfig_name
endpoint = aws_eks_cluster.example.endpoint
cluster_auth_base64 = aws_eks_cluster.example.certificate_authority[0].data
aws_authenticator_command = "aws-iam-authenticator"
aws_authenticator_command_args = ["token", "-i", aws_eks_cluster.example.name]
aws_authenticator_additional_args = []
aws_authenticator_env_variables = {}
})
}
output "kubeconfig" { value = local.kubeconfig }

Terraform auth not working when adding resources

I wanted to try out terraform on our OpenStack environment. I tried to set it up and it seems to work when only the following is defined:
provider "openstack" {
user_name = "test"
tenant_name = "test"
password = "testpassword"
auth_url = "https://test:5000/v3/"
region = "test"
}
I can run terraform plan without any problem it says:
No changes. Infrastructure is up-to-date.
This means that Terraform did not detect any differences between your
configuration and real physical resources that exist. As a result, no
actions need to be performed.
When i try to add a resource:
resource "openstack_compute_instance_v2" "test" {
name = "test_server"
image_id = "test_id123"
flavor_id = "3"
key_pair = "test"
security_groups = ["default"]
network {
name = "Default Network"
}
}
When i run terraform plan i now get
Error: Error running plan: 1 error(s) occurred:
provider.openstack: Authentication failed
The authentication is working. Something in your provider section is incorrect.
Terraform does not verify the provider information when there is no resource using it.
I validated your findings, and then took it a step farther. I created two providers, one for AWS and one for OpenStack using your example. I then added a resource to create an AWS VPC. My AWS credentials were correct. When I ran terraform plan it returned the action plan for building the VPC. It did not check the fake OpenStack credentials.
One other thing, once there is a resource for a provider it always uses the credentials even if there is nothing to do.
provider "aws" {
access_key = "<redacted>"
secret_key = "<redacted>"
region = "us-east-1"
}
provider "openstack" {
user_name = "test"
tenant_name = "test"
password = "testpassword"
auth_url = "https://test:5000/v3/"
region = "test"
}
/* Create VPC */
resource "aws_vpc" "default" {
cidr_block = "10.200.0.0/16"
enable_dns_support = true
enable_dns_hostnames = true
tags {
Name = "testing"
}
}
Produced the following output verifying the OpenStack provider wasn't checked:
$ terraform plan
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.
------------------------------------------------------------------------
An execution plan has been generated and is shown below.
Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
+ aws_vpc.default
id: <computed>
arn: <computed>
assign_generated_ipv6_cidr_block: "false"
cidr_block: "10.200.0.0/16"
default_network_acl_id: <computed>
default_route_table_id: <computed>
default_security_group_id: <computed>
dhcp_options_id: <computed>
enable_classiclink: <computed>
enable_classiclink_dns_support: <computed>
enable_dns_hostnames: "true"
enable_dns_support: "true"
provider "aws" {
instance_tenancy: "default"
ipv6_association_id: <computed>
ipv6_cidr_block: <computed>
main_route_table_id: <computed>
tags.%: "1"
tags.Name: "testing"
Plan: 1 to add, 0 to change, 0 to destroy.
------------------------------------------------------------------------
Note: You didn't specify an "-out" parameter to save this plan, so Terraform
can't guarantee that exactly these actions will be performed if
"terraform apply" is subsequently run.

Terraform: how to support different providers

I have a set of terraform codes in a directory called myproject:
\myproject\ec2.tf
\myproject\provider.tf
\myproject\s3.tf
....
the provider.tf shows:
provider "aws" {
region = "us-west-1"
profile = "default"
}
so, if I terraform apply in myproject folder, a set of aws resources are launched in us-west-1 under my account.
Now I want to introduce a AWS Glue resource, which is only available in a different region us-west-2. then how do I layout glue.tf file?
Currently I store it in a sub-directory under myproject and run terraform apply in that sub-directory i.e.
\myproject\glue\glue.tf
\myproject\glue\another_provider.tf
another_provider.tf is:
provider "aws" {
region = "us-west-2"
profile = "default"
}
Is it the only way to store a file launching resources in different regions? any better way?
If there is no better way, then I need to have another backend file in glue sub-folder as well, besides, some common variables in myproject directory cannot be shared.
--------- update:
I followed the link posted by Phuong Nguyen,
provider "aws" {
region = "us-west-1"
profile = "default"
}
provider "aws" {
alias = "oregon"
region = "us-west-2"
profile = "default"
}
resource "aws_glue_connection" "example" {
provider = "aws.oregon"
....
}
But I saw:
Error: aws_glue_connection.example: Provider doesn't support resource: aws_glue_connection
you can use provider alias to define multiple providers, .e.g.
# this is default provider
provider "aws" {
region = "us-west-1"
profile = "default"
}
# additional provider
provider "aws" {
alias = "west-2"
region = "us-west-2"
profile = "default"
}
and then in your glue.tf, you can refer to alias provider as:
resource "aws_glue_job" "example" {
provider = "aws.west-2"
# ...
}
More details at Multiple Provider Instances section: https://www.terraform.io/docs/configuration/providers.html
Read my comment ...
Which basically means that you should keep out aws profiles and regions and what not from your terraform code as much as possible and use them as configuration as follows:
terraform {
required_version = "1.0.1"
required_providers {
aws = {
version = ">= 3.56.0"
source = "hashicorp/aws"
}
}
backend "s3" {}
}
provider "aws" {
region = var.region
profile = var.profile
}
Than use tfvars configuration files:
cat cnf/env/spe/prd/tf/03-static-website.backend-config.tfvars
profile = "prd-spe-rcr-web"
region = "eu-north-1"
bucket = "prd-bucket-spe"
foobar = "baz"
which you will apply during the terraform plan and apply calls as follows:
terraform -chdir=$tf_code_path plan -var-file=<<line-one-^^^>>.tfvars
terraform -chdir=$tf_code_path plan -var-file=<<like-the-one-^^^>>.tfvars -auto-approve
As a rule of thumb you SHOULD separate your code and configuration always, the more mixed they are the deeper you will get into troubles ... this applies to ANY programming language / project etc. Now some wise heads will argue that terraform code is in itself configuration , but no it is not. The terraform code in your application is the declarative source code, which is used to provision your binary infrastructure used by the application source code etc. in your application ...

Terraform and docker networking

I have defined a terraform recipe with a docker provisioner like this:
provider "docker" {
host = "tcp://127.0.0.1:2375/"
}
# Create the network
resource "docker_network" "private_network" {
name = "${var.customer_name}_network"
}
resource "docker_container" "goagent" {
image = "${docker_image.goagent.latest}"
name = "${var.customer_name}_goagent"
command = [ "/bin/sh", "-c", "/usr/bin/supervisord" ]
network_mode = "bridge"
networks = [ "${docker_network.private_network.name}" ]
hostname = "${var.customer_name}_goagent"
}
resource "docker_image" "goagent" {
name = "local/goagent"
}
I would expect that the container will be connected just to the network created on the fly (using the variable customer_name).
But what I see is that the container gets connected also to the default bridge network (172.17.0.0/16), so it gets connected to two networks.
Is there a way to configure the container in terraform in a way that it gets connected only to the network I specify in the networks list?
Apparently this is an unresolved bug as of 0.10.8

Resources