为什么terraform要从Hashicorp中提取提供者?

为什么terraform要从Hashicorp中提取提供者?,terraform,Terraform,我正在尝试为terraform提供程序测试一些新代码,出于我不理解的原因,它似乎想尝试使用hashicorp找到一个资源定义,尽管它是在这个提供程序中专门定义的。显然,我遗漏了一些东西: [provider][1]的代码: 以下是我构建和安装它的方式: christianb@unifiterraform提供程序工件%rm-fR.terraform christianb@unifiterraform provider artifactory%go build&&mkdir-p.terraform/

我正在尝试为terraform提供程序测试一些新代码,出于我不理解的原因,它似乎想尝试使用hashicorp找到一个资源定义,尽管它是在这个提供程序中专门定义的。显然,我遗漏了一些东西:

[provider][1]的代码:

以下是我构建和安装它的方式:

christianb@unifiterraform提供程序工件%rm-fR.terraform
christianb@unifiterraform provider artifactory%go build&&mkdir-p.terraform/plugins/registry.terraform.io/jfrog/artifactory/2.2.6-alpha/darwin_amd64&&mv terraform provider artifactory.terraform/plugins/registry.io/jfrog/artifactory/2.2.6-alpha/darwin_amd64
现在运行它

christianb@unifi terraform-provider-artifactory % TF_LOG=trace terraform init
2021/02/25 13:12:56 [INFO] Terraform version: 0.13.5  
2021/02/25 13:12:56 [INFO] Go runtime version: go1.14.10
2021/02/25 13:12:56 [INFO] CLI args: []string{"/usr/local/bin/terraform", "init"}
2021/02/25 13:12:56 [DEBUG] Attempting to open CLI config file: /Users/christianb/.terraformrc
2021/02/25 13:12:56 [DEBUG] File doesn't exist, but doesn't need to. Ignoring.
2021/02/25 13:12:56 [DEBUG] ignoring non-existing provider search directory terraform.d/plugins
2021/02/25 13:12:56 [DEBUG] ignoring non-existing provider search directory /Users/christianb/.terraform.d/plugins
2021/02/25 13:12:56 [DEBUG] ignoring non-existing provider search directory /Users/christianb/Library/Application Support/io.terraform/plugins
2021/02/25 13:12:56 [DEBUG] ignoring non-existing provider search directory /Library/Application Support/io.terraform/plugins
2021/02/25 13:12:56 [INFO] CLI command args: []string{"init"}

Initializing the backend...
2021/02/25 13:12:56 [TRACE] Meta.Backend: no config given or present on disk, so returning nil config
2021/02/25 13:12:56 [TRACE] Meta.Backend: backend has not previously been initialized in this working directory
2021/02/25 13:12:56 [DEBUG] New state was assigned lineage "b7f7e5b9-b88c-6195-aaaf-e38b3008b8e5"
2021/02/25 13:12:56 [TRACE] Meta.Backend: using default local state only (no backend configuration, and no existing initialized backend)
2021/02/25 13:12:56 [TRACE] Meta.Backend: instantiated backend of type <nil>
2021/02/25 13:12:56 [DEBUG] checking for provisioner in "."
2021/02/25 13:12:56 [DEBUG] checking for provisioner in "/usr/local/bin"
2021/02/25 13:12:56 [INFO] Failed to read plugin lock file .terraform/plugins/darwin_amd64/lock.json: open .terraform/plugins/darwin_amd64/lock.json: no such file or directory
2021/02/25 13:12:56 [TRACE] Meta.Backend: backend <nil> does not support operations, so wrapping it in a local backend
2021/02/25 13:12:56 [TRACE] backend/local: state manager for workspace "default" will:
 - read initial snapshot from terraform.tfstate
 - write new snapshots to terraform.tfstate
 - create any backup at terraform.tfstate.backup
2021/02/25 13:12:56 [TRACE] statemgr.Filesystem: reading initial snapshot from terraform.tfstate
2021/02/25 13:12:56 [TRACE] statemgr.Filesystem: snapshot file has nil snapshot, but that's okay
2021/02/25 13:12:56 [TRACE] statemgr.Filesystem: read nil snapshot

2021/02/25 13:12:56 [TRACE] providercache.fillMetaCache: scanning directory .terraform/plugins
2021/02/25 13:12:56 [TRACE] getproviders.SearchLocalDirectory: .terraform/plugins is a symlink to .terraform/plugins
Initializing provider plugins...
2021/02/25 13:12:56 [TRACE] getproviders.SearchLocalDirectory: found registry.terraform.io/jfrog/artifactory v2.2.6-alpha for darwin_amd64 at .terraform/plugins/registry.terraform.io/jfrog/artifactory/2.2.6-alpha/darwin_amd64
2021/02/25 13:12:56 [TRACE] providercache.fillMetaCache: including .terraform/plugins/registry.terraform.io/jfrog/artifactory/2.2.6-alpha/darwin_amd64 as a candidate package for registry.terraform.io/jfrog/artifactory 2.2.6-alpha
2021/02/25 13:12:56 [DEBUG] Service discovery for registry.terraform.io at https://registry.terraform.io/.well-known/terraform.json
2021/02/25 13:12:56 [TRACE] HTTP client GET request to https://registry.terraform.io/.well-known/terraform.json
- Using previously-installed jfrog/artifactory v2.2.6-alpha
- Finding latest version of hashicorp/xray...
2021/02/25 13:12:56 [DEBUG] GET https://registry.terraform.io/v1/providers/hashicorp/xray/versions
2021/02/25 13:12:56 [TRACE] HTTP client GET request to https://registry.terraform.io/v1/providers/hashicorp/xray/versions
2021/02/25 13:12:57 [TRACE] providercache.fillMetaCache: using cached result from previous scan of .terraform/plugins
2021/02/25 13:12:57 [DEBUG] GET https://registry.terraform.io/v1/providers/-/xray/versions
2021/02/25 13:12:57 [TRACE] HTTP client GET request to https://registry.terraform.io/v1/providers/-/xray/versions

Error: Failed to install provider

Error while installing hashicorp/xray: provider registry registry.terraform.io
does not have a provider named registry.terraform.io/hashicorp/xray

我发现它是基于资源类型的名称的——因此,它不是以
artifactory
开始的,这会产生不同。我想知道的是这个查找背后的逻辑
[1] :

Terraform v0.13引入了属于其他名称空间的第三方提供者的想法,这些名称空间不受HashiCorp直接控制,但为了最大限度地提高与为Terraform v0.12及更早版本编写的模块的向后兼容性,存在一种回退行为,Terraform将假定任何未明确声明的提供程序需求旨在使用一个官方提供程序,该提供程序现在位于注册表中的“hashicorp”命名空间中,因为对于Terraform v0.12和早期版本,第三方提供商根本无法自动安装

在为Terraform v0.13或更高版本编写模块时,您应该包括explicit,以指定模块使用的每个提供程序的完整源地址,如下所示:

terraform {
  required_providers {
    artifactory = {
      source = "jfrog/artifactory"
    }
    xray = {
      source = "ryndaniels/xray"
    }
  }
}

不幸的是,在我写这篇文章的时候,您尝试在这里使用的“X射线”提供者还没有在中发布。我上面使用的源地址
ryndaiels/xray
是如果作者按原样将其发布到注册表中,该提供者将采用的地址,因为Terraform注册表使用一种有系统的命名方案从GitHub存储库地址生成提供者源地址

但是,除非该提供程序稍后在注册表中发布,否则您需要在本地系统上手动安装它,以便Terraform找到并使用它。要实现这一点,请参阅查看Terraform在您的平台上搜索插件的目录,然后您可以为Terraform创建必要的目录结构以查找提供者

作为示例,我将使用terraform在Linux上支持的
$HOME/.terraform.d/plugins/
前缀,但请注意,Windows和macOS上的路径不同,因此您需要在这些操作系统上调整为不同的路径前缀:

$HOME/.terraform.d/plugins/registry.terraform.io/ryndaniels/xray/0.0.1/linux_amd64/terraform-provider-xray
关于上述内容,还有几点需要注意:

  • registry.terraform.io/ryndaiels/xray
    部分是terraform与您在
    provider\u requirements
    块中设置的
    source
    匹配的部分
    registry.terraform.io
    是不包含主机名的源地址的默认主机名,因此
    ryndaiels/xray
    是registry.terraform.io/ryndaiels/xray的缩写

  • 这个特定的提供程序没有任何标记的版本,因此没有要使用的特定版本号。因为Terraform希望所有提供者都有一个版本号,所以我在上面的路径中任意选择了
    0.0.1
    作为版本号。只有在模块中编写显式的
    version
    参数来约束允许的版本时,这才有意义

  • 我在这里使用
    linux\u amd64
    作为目标平台,继续我使用linux风格镜像路径的示例。通过运行
    terraform version
    ,您可以找到适合您的平台,在最新的terraform版本中,该版本包括构建terraform CLI可执行文件的平台名称:

    Terraform v0.14.4
    on linux_amd64
    
在启动时,Terraform将扫描当前平台的所有隐含本地镜像目录,并记录在那里找到的任何提供者,并假设您打算从本地文件系统而不是从注册表安装这些提供者。因此,只要目录结构如上所述是正确的,
terraform init
将看到您在本地安装了
Ryandiels/xray
,并将使用那里的副本,而不是询问terraform注册表该提供商可以使用哪些版本


如果提供者作者稍后将此提供者发布到Terraform注册表,并且他们这样做时没有重命名存储库或将其移动到其他GitHub帐户,它应该以
Ryndaiels/xray
的形式出现在注册表中,因此
terraform init
将能够从那里自动安装它,而无需对您的模块进行任何进一步修改。

我知道该提供商不在注册表中-我是在本地构建和安装的。但是,您关于向后兼容性的解释有助于解释问题。当我回答有关堆栈溢出的问题时,我会尝试提供足够的背景信息,以便回答可能对以后有类似问题并通过搜索找到此问题的其他人有用;我很抱歉报道了你们已经知道的内容,但我不想假设所有的读者都有相同的知识。
Terraform v0.14.4
on linux_amd64