Terraform 提供程序方法配置未被调用

问题描述 投票:0回答:1

我正在开发一个自定义 Terraform 提供程序。 我已完成所有用于创建/读取/更新/删除资源的自定义逻辑,但我无法配置提供程序。 我已克隆此存储库作为基础https://github.com/hashicorp/terraform-provider-scaffolding-framework/tree/main。 如果我调试该存储库中的代码,然后在

provider.go
类型的
Configure
方法处的
hashicupsProvider
文件中添加一行,以便在该方法中获得断点,则该断点永远不会命中。 我自己的提供商有完全相同的“骨架”,所以我认为没有必要提供整个源代码,因为即使从 HashiCorp 提供的示例来看它也不起作用。

我已使用

.terraformrc
覆盖了提供程序地址/路径,并且可以使用
terraform providers schema -json
成功生成提供程序的架构。

我在文档中遗漏了一些您必须做的事情,以便 Terraform 认识到它应该调用

Configure
方法吗?

编辑: 添加提供程序结构和部分接口实现的代码。

type myproviderProvider struct {
version string
}

func (p *myproviderProvider) Metadata(_ context.Context, _ provider.MetadataRequest, resp *provider.MetadataResponse) {
resp.TypeName = "myprovider"
resp.Version = p.version
}

func (p *myproviderProvider) Configure(ctx context.Context, req provider.ConfigureRequest, resp *provider.ConfigureResponse) {

tflog.Debug(ctx, "Configure myprovider provider was called")

tflog.Info(ctx, "Creating myprovider client")
// And so on......
}

func (p *myproviderProvider) Schema(_ context.Context, _ provider.SchemaRequest, resp *provider.SchemaResponse) {

resp.Schema = schema.Schema{

Description: "Interact with myprovider.",

Attributes: map[string]schema.Attribute{

"username": schema.StringAttribute{

Description: "Username for myapp API. May also be provided via myprovider_USER environment variable.",

Optional: true,

},

"password": schema.StringAttribute{

Description: "Password for myapp API. May also be provided via myprovider_PW environment variable.",

Optional: true,

},

"api_url": schema.StringAttribute{

Description: "Url for myapp API. May also be provided via myprovider_URL environment variable.",

Optional: true,

Sensitive: true,

},

"domain_id": schema.StringAttribute{

Description: "DomainId for myapp API. May also be provided via myprovider_DOMAIN_ID environment variable.",

Optional: true,

Sensitive: true,

},

},

}

}

这是用于将提供者返回到

Serve
方法

的函数
func New(version string) func() provider.Provider {
    return func() provider.Provider {
        return &myproviderProvider{
            version: version,
        }
    }
}

Terraform 代码

terraform {
  required_providers {
    myprov = {
      source = "hashicorp.com/myuser/myprov"
      version = "0.1.0"
    }
  }
}

provider "myprov" {
  username  = "myuser"
  password  = "verysecret"
  api_url   = "https://someurl.com"
  domain_id = "a-guid"
}
go terraform
1个回答
0
投票

我遇到了这样的问题,尽管由于缺少上下文,所以并不能 100% 清楚它是否“完全”是这样。我的问题是:

我用
provider.Provider

函数创建了自己的

Configure()
。这会读取配置,实例化
http.Client
并将其设置为与以下内容一起使用:
resp.DataSourceData = client
resp.ResourceData = client

然后我创建了一个 
resource.Resource

,它还有一个

Configure()
方法,通过以下方式使用此客户端:
client, ok := req.ProviderData.(*http.Client)

规划/应用时,
req.ProviderData

中的值将是

nil
,并且我的资源将无法创建。 然后我进入
Provider.Configure()
方法并尝试通过
tflog.Info
放置日志 - 它从未出现在输出中。

事实证明这是预期的行为 - 您的资源/数据源必须妥善处理它。在应用/计划期间,可以调用
Resource.Configure()

方法

多次
,而您的 Provider.Configure() 方法
可能尚未被调用
在这种情况下,

req.ProviderData

nil
,因为配置尚未运行。正确处理这个问题的方法是检查并尽早返回:
func (r *ApplicationResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
    if req.ProviderData == nil {
        // IMPORTANT: This method is called MULTIPLE times. An initial call might not have configured the Provider yet, so we need
        // to handle this gracefully. It will eventually be called with a configured provider.
        return
    }

    client, ok := req.ProviderData.(*http.Client)

    if !ok {
        resp.Diagnostics.AddError(
            "Unexpected Resource Configure Type",
            fmt.Sprintf("Expected *http.Client, got: %T. Please report this issue to the provider developers.", req.ProviderData),
        )

        return
    }

    r.client = client
}

	
© www.soinside.com 2019 - 2024. All rights reserved.