如何解组 Pulumi auto.Result 对象的结构或映射?

huangapple go评论68阅读模式
英文:

How to unmarshal Pulumi auto.Result object struct or map

问题

我正在使用Pulumi的自动化API在Go中部署服务器到Hetzner,但是无法找到如何从部署结果中获取连接信息的方法。

以下是截断的代码:

import (
    ...

	"github.com/pulumi/pulumi-command/sdk/go/command/remote"
	"github.com/pulumi/pulumi/sdk/v3/go/auto"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

...

deployFunc := func(ctx *pulumi.Context) error {
        // 创建SSH密钥对,将它们上传到Hetzner,返回一个`*hcloud.SshKey`
        ...
        
        // `server` 是一个 *hcloud.Server 对象
		server, _ := DeployServerToHetzner(ctx, sshKey)

        // 这是我想从结果中检索的信息
		connectInfo := remote.ConnectionArgs{
			Host:       server.Ipv4Address,
			Port:       pulumi.Float64(22),
			User:       pulumi.String("root"),
			PrivateKey: sshKeyPair.Private,
		}

		ctx.Export("server-connect-info", connectInfo)

		return nil
	}

stack, _ := auto.UpsertStackInlineSource(ctx, stackName, projectName, deployFunc, opts...)

res, _ := stack.Up(ctx)

// 这是一个字符串,但我需要它作为映射或结构体
serverConnectInfo := fmt.Sprintf("%v", res.Outputs["server-connect-info"].Value)

我能够从res.Outputs中检索结果,但它是一个字符串。我知道服务器部署和响应连接详细信息是成功的,因为当我记录serverConnectInfo时,它看起来像这样:

serverConnectInfo map[host:123.456.789.10 port:22 privateKey:-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNza...
-----END OPENSSH PRIVATE KEY-----
user:root]

根据一些可疑的在线解决方案,我尝试将其编组为我们将JSON进行编组的方式,然后将其解组为Pulumi的remote.ConnectionArgs实例。显然这行不通,因为结构体如下所示:

// 来自 https://pkg.go.dev/github.com/pulumi/pulumi-command/sdk@v0.7.2/go/command/remote#ConnectionArgs

type ConnectionArgs struct {
    ...
    Host pulumi.StringInput `pulumi:"host"`
    Port pulumi.Float64PtrInput `pulumi:"port"`
    PrivateKey pulumi.StringPtrInput `pulumi:"privateKey"`
    User pulumi.StringPtrInput `pulumi:"user"`
}

我正在考虑构建自己的结构体,然后重试JSON解组和编组的解决方案,但似乎如果ConnectionArgs结构体已经有了pulumi标签,应该有一种pulumi.Unmarshal方法。我错了吗?无论如何,我找不到它。

我也查阅了文档,但没有找到有用的信息。也许我错过了某个页面?

英文:

I'm deploying servers to Hetzner using Pulumi's automation API in Go, but can't figure out how to get the resulting connection information out of the deployment result.

Here's the truncated code:

import (
    ...

	"github.com/pulumi/pulumi-command/sdk/go/command/remote"
	"github.com/pulumi/pulumi/sdk/v3/go/auto"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

...

deployFunc := func(ctx *pulumi.Context) error {
        // Create SSH key pair, upload them to Hetzner, get back a `*hcloud.SshKey`
        ...
        
        // `server` is a *hcloud.Server object
		server, _ := DeployServerToHetzner(ctx, sshKey)

        // This is the info I want to retrieve from the result
		connectInfo := remote.ConnectionArgs{
			Host:       server.Ipv4Address,
			Port:       pulumi.Float64(22),
			User:       pulumi.String("root"),
			PrivateKey: sshKeyPair.Private,
		}

		ctx.Export("server-connect-info", connectInfo)

		return nil
	}

stack, _ := auto.UpsertStackInlineSource(ctx, stackName, projectName, deployFunc, opts...)

res, _ := stack.Up(ctx)

// This is a string but I need it as either map or struct
serverConnectInfo := fmt.Sprintf("%v", res.Outputs["server-connect-info"].Value)

I'm able to retrieve the result from res.Outputs, but it's a string. I know the server deployment and response with connection details are successful because when I log serverConnectInfo, it looks like this:

serverConnectInfo map[host:123.456.789.10 port:22 privateKey:-----BEGIN OPENSSH PRIVATE KEY-----
b3BlbnNza...
-----END OPENSSH PRIVATE KEY-----
user:root]

Based on a few dubious solutions online, I tried marshalling it as we would a JSON and then unmarshalling it into a Pulumi remote.ConnectionArgs instance. That obviously didn't work, because the struct looks like this:

// From https://pkg.go.dev/github.com/pulumi/pulumi-command/sdk@v0.7.2/go/command/remote#ConnectionArgs

type ConnectionArgs struct {
    ...
    Host pulumi.StringInput `pulumi:"host"`
    Port pulumi.Float64PtrInput `pulumi:"port"`
    PrivateKey pulumi.StringPtrInput `pulumi:"privateKey"`
    User pulumi.StringPtrInput `pulumi:"user"`
}

I'm thinking of constructing my own struct and then retrying the JSON unmarshalling and marshalling solution but it seems like if the ConnectionArgs struct already has pulumi tags, there should be some kind of pulumi.Unmarshal method somewhere. Am I wrong? I couldn't find it anyway.

I've looked into the docs too but haven't seen anything that helps. Maybe I missed a page?

答案1

得分: 0

正如Peter在评论中指出的那样,res.Outputs["server-connect-info"].Value是一个映射,并且正确地猜测我将其通过fmt.Sprintf运行。这真是我太傻了。

这样可以工作:

serverConnectInfo := res.Outputs["server-connect-info"].Value.(map[string]interface{})

在使用内置的testing包进行Go测试时也可以正常工作:

assert.NotEmpty(t, serverConnectInfo["host"])
assert.Equal(t, serverConnectInfo["user"], "root")
英文:

As Peter pointed out in a comment, res.Outputs["server-connect-info"].Value is a map and correctly guessed that I ran it through fmt.Sprintf. That was just silly of me.

This works:

serverConnectInfo := res.Outputs["server-connect-info"].Value.(map[string]interface{})

Works well in a Go test using the built-in testing package too:

assert.NotEmpty(t, serverConnectInfo["host"])
assert.Equal(t, serverConnectInfo["user"], "root")

huangapple
  • 本文由 发表于 2023年4月28日 02:23:04
  • 转载请务必保留本文链接:https://go.coder-hub.com/76123545.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定