I try to create groups and projects in gitlab with terraform. Later I want to create a new resource "project_membership" to give the new projects the groups as members. Therefore I need the Group_ID and the Project ID.
If I create all resources in own resource blocks, I can refer to it with ${gitlab_group.NAME_OF_THE_RESSOURCE.id} but when I use for_each I do not specify a name. How I can get the group and project IDs?
terraform {
backend "http" {
}
required_providers {
gitlab = {
source = "gitlabhq/gitlab"
version = "~> 3.1"
}
}
}
locals {
services_project_names = toset( [
"values",
"releases",
"design",
"execution"
] )
permission_project_names = toset( [
"vendor",
"maintainer"
] )
}
################################
#### permissions repository ####
################################
resource "gitlab_group" "permissions_group" {
name = var.service_name
path = var.service_name
parent_id = var.permissions_parent_grp
visibility_level = "private"
}
resource "gitlab_group" "permissions_sub_group" {
for_each = local.permission_project_names
name = "${var.service_name}_${each.key}"
path = "${var.service_name}_${each.key}"
parent_id = "${gitlab_group.permissions_group.id}"
visibility_level = "private"
}
############################
#### service repository ####
############################
resource "gitlab_group" "services_group" {
name = var.service_name
path = var.service_name
parent_id = var.services_parent_grp
visibility_level = "private"
}
resource "gitlab_project" "services_projects" {
for_each = local.services_project_names
name = "${var.service_name}_${each.key}"
default_branch = "main"
description = ""
issues_enabled = false
merge_requests_enabled = false
namespace_id = "${gitlab_group.services_group.id}"
snippets_enabled = false
visibility_level = "private"
wiki_enabled = false
}
You can reference individual values created via for_each by using the key that was used in the for_each. In your case here are some examplels:
"${gitlab_project.services_projects["values"]}"
"${gitlab_project.services_projects["releases"]}"
To get the ID of a specific project:
gitlab_project.services_projects["values"].id
Related
I have written code that works well in order to create Azure Firewall Network Rules via Terraform. Weeks later i'm asked to add an attribute "expiration" in order to enable users to create temporary network rules.
If the expiration field is 0, means the rule is permanent, if not, i compare the date with the sysdate.
I have tried nearly every possible "for_each" with "for" and "if" combinations, but nothing seems to work. That "expiration" attribute seems inaccessible from outside the loop.
Here are the files of my code:
main.tf
module.tf (edits must be done here, in the dynamic "rule" bloçk of the network_rule_collection block, all other files have been simplified and are here only for better understanding of the code logic)
variables.tf
net_rules.yaml
fw_collections.yaml
Main.tf
locals {
collections = yamldecode(file("../environments/fw_collections.yaml"))
netrules = yamldecode(file("../environments/net_rules.yaml"))
apprules = yamldecode(file("../environments/app_rules.yaml"))
}
module "tdf_az_firewall_policy_rule_collection_group" {
source = "../../modules/tdf_az_firewall_policy_rule_collection_group"
fw_policy_id = module.tdf_az_firewall_policy.firewall_policy_id
fw_c = local.collections.FW_Collections
fw_nr = local.netrules.FW_NET_Rules
fw_ar = local.apprules.FW_APP_Rules
rgname = data.azurerm_resource_group.ipgrg.name
sub = element(split("/", module.tdf_az_virtual_hub_module.virtual_hub_id), 2)
depends_on = [module.tdf_az_firewall_policy, module.tdf_az_firewall]
}
Module.tf
resource "azurerm_firewall_policy_rule_collection_group" "fw-prcg" {
for_each = var.fw_c
name = each.key
firewall_policy_id = var.fw_policy_id
priority = each.value[0]
dynamic "network_rule_collection" {
for_each = { for nr, name in var.fw_nr : nr => name if nr == each.key }
content {
name = each.key
priority = each.value[0]
action = each.value[1]
dynamic "rule" {
for_each = { for x, y in var.fw_nr[each.key] : x => y.expiration if timecmp(y.expiration, timestamp()) == 1 }
content {
name = rule.value.name
protocols = rule.value.protocols
source_ip_groups = [for s in rule.value.source_ip_groups : join("/", ["/subscriptions", var.sub, "resourceGroups", var.rgname, "providers/Microsoft.Network/ipGroups", s])]
destination_ip_groups = [for d in rule.value.destination_ip_groups : join("/", ["/subscriptions", var.sub, "resourceGroups", var.rgname, "providers/Microsoft.Network/ipGroups", d])]
destination_ports = rule.value.destination_ports
}
}
}
}
dynamic "application_rule_collection" {
for_each = { for ar, name in var.fw_ar : ar => name if ar == each.key }
content {
name = each.key
priority = each.value[0]
action = each.value[1]
dynamic "rule" {
for_each = var.fw_ar[each.key]
content {
name = rule.value.name
dynamic "protocols" {
for_each = rule.value.protocols
content {
type = protocols.value.type
port = protocols.value.port
}
}
source_ip_groups = [for s in rule.value.source_ip_groups : join("/", ["/subscriptions", var.sub, "resourceGroups", var.rgname, "providers/Microsoft.Network/ipGroups", s])]
destination_fqdns = rule.value.destination_fqdns
destination_urls = rule.value.destination_urls
terminate_tls = rule.value.terminate_tls
web_categories = rule.value.web_categories
destination_fqdn_tags = rule.value.destination_fqdn_tags
}
}
}
}}
variables.tf
variable "fw_policy_id" {}
variable "fw_c" {}
variable "fw_nr" {}
variable "fw_ar" {}
variable "sub" {}
variable "rgname" {}
netrules.yaml
FW_NET_Rules:
Blacklist-Net:
- name: blacklisted_inbound_ips_rule_inbound
source_ip_groups: ["blacklisted_inbound_ips"]
destination_ip_groups: ["Any-ip"]
estination_ports: ["*"]
protocols: ["Any"]
expiration: 0
- name: k8saas_backlisted_idps_rule_inbound
source_ip_groups: ["k8saas_blacklist_ip_inbound"]
destination_ip_groups: ["Any-ip"]
destination_ports: ["*"]
protocols: ["Any"]
expiration: 0
Mobility:
- name: Mobility-LAN-VNET
source_ip_groups: ["Mobility-LAN"]
destination_ip_groups: ["Mobility-VNET"]
destination_ports: ["443"]
protocols: ["TCP"]
expiration: "2022-12-12T00:00:00Z"
- name: Mobility-LAN-To-Data
source_ip_groups: ["Mobility-LAN"]
destination_ip_groups: ["Data-VNET"]
destination_ports: ["443"]
protocols: ["TCP"]
expiration: "2022-12-12T00:00:00Z"
fw_collections.yaml
FW_Collections:
Blacklist-Net: [100, "Deny"]
Mobility: [105, "Allow"]
I have above terraform which will create resource group from csv list and run loop, its showing me error, as object id is not reading.
Any idea how to add owner to resource group created in loop in terraform?
locals {
project_info = csvdecode(test.csv)
}
module "azurerm_resource_group" {
for_each = { for proj in local.project_info : proj.project_name => proj }
source = "../../../modules/azurerm_resource_group"
project_name = each.value.project_name
tags = {
costcenter = ""
expiration = each.value.end_date
owner = each.value.project_owner
project = each.value.project_name
}
}
#------------------------------------------------------------------------------
# Get Object ID of Owner
#------------------------------------------------------------------------------
data "azuread_user" "owner" {
for_each = module.azurerm_resource_group
user_principal_name = lookup(each.value.resourcegroup_tags, "owner")
}
#------------------------------------------------------------------------------
# Assign RG owner access to owner of this project
#------------------------------------------------------------------------------
module "azurerm_role_assignment" {
source = "../../../modules/azurerm_role_assignment"
for_each = module.azurerm_resource_group
scope_id = each.value.id
role_definition_name = "Owner"
principal_id = values(data.azuread_user.owner)[*].object_id
}
Try this:
module "azurerm_role_assignment" {
source = "../../../modules/azurerm_role_assignment"
for_each = module.azurerm_resource_group
scope_id = each.value.id
role_definition_name = "Owner"
principal_id = "${data.azuread_user.owner[each.key].object_id}
}
Share with me the error if it doesn't work.
Hope this helps!
I have a terraform file with the following contents:
resource "aws_iam_group" "developers" {
name = each.value
for_each = toset(var.groups)
}
resource "aws_iam_group_membership" "developers_team" {
name = "Developers Team"
users = [each.value]
for_each = toset(var.group_users)
group = aws_iam_group.developers.name
}
I would like to reference aws_iam_group from aws_iam_group_membership. How would I do that? The current terraform file is not working.
I tried this:
group = aws_iam_group.developers[each.value] //This will not work since it uses the for_each of
its own code block
The variable file is as below:
variable "groups" {
type = list(string)
default = [
"terraform_group1",
"terraform_group2",
"terraform_group3",
]
}
variable "group_users" {
type = list(string)
default = [
"terraform_test_user1",
"terraform_test_user2"
]
}
Edit:
I tried the below, but it is not working
resource "aws_iam_group_membership" "developers_team" {
name = "Developers Team"
users = [for group_user in var.group_users : group_user]
for_each = toset(var.groups)
group = aws_iam_group.developers[each.key]
}
Apparently, this is working:
resource "aws_iam_group" "developer" {
name = "truedeveloper"
}
resource "aws_iam_group_membership" "developers_team" {
name = "Developers_Team"
users = [for group_user in var.group_users : group_user]
for_each = toset(var.groups)
group = aws_iam_group.developer.name
}
Need suggestion.
I am trying to run the below code. First adf is imported which has the vsts configuration.
For second adf, i dont need the vsts configuration. I have tried using dymanic block, but getting error as below.
on main.tf line 16, in resource "azurerm_data_factory" "adf":
2020-12-24T08:13:44.3101544Z 16: dynamic [4m"action"
[0m {
2020-12-24T08:13:44.3101802Z [0m
2020-12-24T08:13:44.3102076Z Blocks of type "action" are not expected here.
Main.tf
resource "azurerm_data_factory" "adf"{
for_each = var.purposes
name=lower("${var.component}-${var.project}-${var.regionname}-${var.azureregion}-${var.environment}-${each.value.purpose}")
location = data.azurerm_resource_group.rg.location
resource_group_name = data.azurerm_resource_group.rg.name
identity{
type="SystemAssigned"
}
dynamic "action" {
for_each = var.vsts_config ? [1] : []
content {
vsts_configuration {
account_name = var.accountname
branch_name = var.branchname
project_name = var.projectname
repository_name = var.repository
tenant_id = "__tenantId__"
root_folder = var.rootfolder
}
}
}
}
input.tfvars
purposes = {
a = {
purpose = "load",
}
b = {
purpose = "live",
}
}
action is not a valid block in azurerm_data_factory. If you want to make vsts_configuration block optional, then you code should be:
dynamic "vsts_configuration" {
for_each = var.vsts_config ? [1] : []
content {
account_name = var.accountname
branch_name = var.branchname
project_name = var.projectname
repository_name = var.repository
tenant_id = "__tenantId__"
root_folder = var.rootfolder
}
}
I'm starting to use (and learn) terraform, for now, I need to create multiple DO droplets and attach them to the aws route53 zone, what I'm trying to do:
My DO terraform file:
# Configure the DigitalOcean Provider
provider "digitalocean" {
token = var.do_token
}
# Create a new tag
resource "digitalocean_tag" "victor" {
name = "victor-fee1good22"
}
resource "digitalocean_droplet" "web" {
count = 2
image = var.do_config["image"]
name = "web-${count.index}"
region = var.do_config["region"]
size = var.do_config["size"]
ssh_keys = [var.public_ssh_key, var.pv_ssh_key]
tags = [digitalocean_tag.victor.name]
}
My route53 file:
provider "aws" {
version = "~> 2.0"
region = "us-east-1"
access_key = var.aws_a_key
secret_key = var.aws_s_key
}
data "aws_route53_zone" "selected" {
name = "devops.rebrain.srwx.net"
}
resource "aws_route53_record" "www" {
сount = length(digitalocean_droplet.web)
zone_id = data.aws_route53_zone.selected.zone_id
name = "web_${count.index}"
type = "A"
ttl = "300"
records = [digitalocean_droplet.web[count.index].ipv4_address]
}
But I always get The "count" object can be used only in "resource" and "data" blocks, and only
when the "count" argument is set. error, what did I wrong?
Thanks!
UPDATE:
I've resolved this one like — add сount = 2 instead of сount = length(digitalocean_droplet.web)
It works but would be better to have the dynamic variable instead of constant count. :)
you want to get number of services, that not yet created. Terraform couldn't do that.
As I think simplest way use common var with the number of droplets.
resource "digitalocean_droplet" "test" {
count = var.number_of_vps
image = "ubuntu-18-04-x64"
name = "test-1"
region = data.digitalocean_regions.available.regions[0].slug
size = "s-1vcpu-1gb"
}
resource "aws_route53_record" "test" {
count = var.number_of_vps
zone_id = data.aws_route53_zone.primary.zone_id
name = "${local.login}-${count.index}.${data.aws_route53_zone.primary.name}"
type = "A"
ttl = "300"
records = [digitalocean_droplet.test[count.index].ipv4_address]
}
This trick helped - https://github.com/hashicorp/terraform/issues/12570#issuecomment-291517239
resource "aws_route53_record" "dns" {
count = "${length(var.ips) > 0 ? length(var.domains) : 0}"
// ...
}