詹金斯起程拓殖秘密凭证与TF_VAR_经理



我一直在阅读的所有内容都说我应该使用TF_VAR_方法将我的客户端秘密传递给Terraform,但我一直得到这个错误:

Error: No value for required variable
on variables.tf line 1:
1: variable "clientid" {
The root module input variable "clientid" is not set, and has no default
value. Use a -var or -var-file command line argument to provide a value for
this variable.

请注意,如果我将值直接传递给-var标志,它会正常工作。所以,这个问题是关于如何使用TF_VAR_方法,而不是如何登录。

Jenkinsfile

//Jenkinsfile (Declarative Pipeline)
pipeline {
agent { label 'docker-agent' }
environment {
AZURE_SUBSCRIPTION_ID='<......>'
AZURE_TENANT_ID='<.......>'
CONTAINER_REGISTRY='containerregistry'
RESOURCE_GROUP='crrg'
REPO="sftp01"
IMAGE_NAME="sftptest"
TAG="0.01"
}

stages {
stage('build') {
steps {
//sh 'docker build -t containerregistry.azurecr.io/sftp01/sftptest:0.01 -f Dockerfile .'
//sh 'echo built'

withCredentials([usernamePassword(credentialsId: 'containerregistryCreds', passwordVariable: 'AZURE_CLIENT_SECRET', usernameVariable: 'AZURE_CLIENT_ID')]) {

sh 'export TF_VAR_clientid=$AZURE_CLIENT_ID'
sh 'export TF_VAR_clientsecret=$AZURE_CLIENT_SECRET'
sh 'export TF_VAR_subscriptionid=$AZURE_SUBSCRIPTION_ID'
sh 'export TF_VAR_tenantid=$AZURE_TENANT_ID'

//sh 'az login --service-principal -u $AZURE_CLIENT_ID -p $AZURE_CLIENT_SECRET -t $AZURE_TENANT_ID'
//sh 'az account set -s $AZURE_SUBSCRIPTION_ID'
//sh 'az acr login --name $CONTAINER_REGISTRY --resource-group $RESOURCE_GROUP'
//sh 'az acr build --image $REPO/$IMAGE_NAME:$TAG --registry $CONTAINER_REGISTRY --file Dockerfile . '

sh 'terraform init'
sh 'terraform fmt'
sh 'terraform validate'
sh 'terraform apply -auto-approve -no-color'

//If I pass the variables this way, it works fine.
//sh 'terraform apply -auto-approve -no-color -var clientid=$AZURE_CLIENT_ID -var clientsecret=$AZURE_CLIENT_SECRET -var subscriptionid=$AZURE_SUBSCRIPTION_ID -var tenantid=$AZURE_TENANT_ID'

sh 'terraform show'
sh 'terraform state list'
}
}
}
}
}

main.tf

# Configure the Azure provider
terraform {
required_providers {
azurerm = {
source  = "hashicorp/azurerm"
version = "~> 3.0.2"
}
}
}
provider "azurerm" {
client_id       = var.clientid
client_secret   = var.clientsecret
subscription_id = var.subscriptionid
tenant_id       = var.tenantid
features {}
}
resource "azurerm_resource_group" "resourceNameTFscopeOnly" {
name     = "myTFResourceGroup"
location = "westus2"
}

variables.tf

variable "clientid" {
description = "Azure Client ID"
type        = string
sensitive   = true
}
variable "clientsecret" {
description = "Azure Client Service Principal Secret"
type        = string
sensitive   = true
}
variable "subscriptionid" {
description = "Azure Subscription ID"
type        = string
sensitive   = true
}
variable "tenantid" {
description = "Azure Tenant ID"
type        = string
sensitive   = true
}
variable "testpassword" {
description = "For testing (not relevant to question)"
type        = string
sensitive   = true
}

我做错了什么?

Jenkins Pipeline中的withCredentials块已经将您的变量导出到其作用域内的环境中。您可以额外地修改env对象以获得额外的环境变量,并从env对象访问当前的环境变量(例如您在environment指令中分配的那些)。这就是terrform在没有变量值时出错的原因:它们都没有在环境中正确设置。

// assign password and username environment variables within block arguments
withCredentials([usernamePassword(credentialsId: 'containerregistryCreds', passwordVariable: 'TF_VAR_clientsecret', usernameVariable: 'TF_VAR_clientid')]) {
script {
// re-assign other environment variables from environment directive to env object within block scope           
env.TF_VAR_subscriptionid = env.AZURE_SUBSCRIPTION_ID
env.TF_VAR_tenantid = env.AZURE_TENANT_ID
...
}
}

这就是我最后所做的。感谢Matt回答了这个核心问题。此外,为了保持tenantId和subscriptionId不受源代码控制,我将它们放在Jenkins:

中它们自己的usernamePassword凭据中。
//Jenkinsfile (Declarative Pipeline)
pipeline {
agent { label 'docker-agent' }
environment {
//TF_LOG='DEBUG'
TF_LOG_PATH='/home/jenkins/terraform-debug.log'
CONTAINER_REGISTRY='ArcticaCR'
RESOURCE_GROUP='crrg'
REPO="sftp01"
IMAGE_NAME="sftptest"
TAG="0.01"
}

stages {
stage('build') {
steps {

withCredentials([
usernamePassword(credentialsId: 'sftpServicePrincipalCreds', passwordVariable: 'TF_VAR_clientsecret', usernameVariable: 'TF_VAR_clientid'),
usernamePassword(credentialsId: 'AzureTenantSubscription', passwordVariable: 'TF_VAR_tenantid', usernameVariable: 'TF_VAR_subscriptionid'),
usernamePassword(credentialsId: 'passwordtestCreds', passwordVariable: 'TEST_PASSWORD', usernameVariable: 'TEST_USERNAME')
]) {

sh 'az login --service-principal -u $TF_VAR_clientid -p $TF_VAR_clientsecret -t $TF_VAR_tenantid'
sh 'az account set -s $TF_VAR_subscriptionid'
sh 'az acr login --name $CONTAINER_REGISTRY --resource-group $RESOURCE_GROUP'
sh 'az acr build --image $REPO/$IMAGE_NAME:$TAG --registry $CONTAINER_REGISTRY --file Dockerfile . '
sh 'az logout'

sh 'terraform init'
sh 'terraform fmt'
sh 'terraform validate'

sh 'terraform apply -auto-approve -no-color -var testpassword=$TEST_PASSWORD'

sh 'terraform show'
sh 'terraform state list'
}
}
}
}
}

因此,正如在另一个答案中已经说明的那样,您在一个sh步骤中导出变量,但在另一个sh步骤中运行Terraform命令。导出的值不能跨步骤保存,因为这些步骤是独立的Bash进程。但是您可以在一步中运行它:

sh """
export TF_VAR_...=...
terraform ...
"""

我认为env.TF_VAR_... = ...的解决方案仍然更好。

最新更新