Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .envrc.template
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
eval $(esc env open pulumi/providers/cloudflare --format shell)
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,6 @@ go.work.sum

# Ignore local build tracking directory
.make

# Developers define their own direnv config but the repo provides a template in `.envrc.template`.
.envrc
26 changes: 26 additions & 0 deletions provider/pkg/migrations/token/hook.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package migratetoken

import (
"github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfbridge/info"
"github.com/pulumi/pulumi-tool-generate-migration/pkg/bridge"
"github.com/pulumi/pulumi-tool-generate-migration/pkg/pvbind"
"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
)

var (
unmarshalOpts = pvbind.UnmarshalOpts{
StrictModeIgnoreField: func(pk resource.PropertyKey) bool {
return pk == "id"
},
}

hook = bridge.NewPreStateUpgradeHook(Migrate, unmarshalOpts)
)

func PreStateUpgradeHook(args info.PreStateUpgradeHookArgs) (int64, resource.PropertyMap, error) {
// Only apply speculative schema correction when prior state is v=0.
if args.PriorStateSchemaVersion != 0 {
return args.ResourceSchemaVersion, args.PriorState, nil
}
return hook(args)
}
116 changes: 116 additions & 0 deletions provider/pkg/migrations/token/token.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package migratetoken

import (
"github.com/pulumi/pulumi/sdk/v3/go/common/resource"
)

type ApiTokenConditionRequestIp struct {
Ins []resource.PropertyValue `pulumi:"ins"`
NotIns []resource.PropertyValue `pulumi:"notIns"`
}

type ApiTokenCondition struct {
RequestIp ApiTokenConditionRequestIp `pulumi:"requestIp"`
}

type ApiTokenPolicy struct {
Effect resource.PropertyValue `pulumi:"effect"`
PermissionGroups []resource.PropertyValue `pulumi:"permissionGroups"`
Resources map[string]resource.PropertyValue `pulumi:"resources"`
}

type R1State struct {
Condition ApiTokenCondition `pulumi:"condition"`
IssuedOn resource.PropertyValue `pulumi:"issuedOn"`
Name resource.PropertyValue `pulumi:"name"`
NotBefore resource.PropertyValue `pulumi:"notBefore"`
Status resource.PropertyValue `pulumi:"status"`
Value resource.PropertyValue `pulumi:"value"`
ExpiresOn resource.PropertyValue `pulumi:"expiresOn"`
ModifiedOn resource.PropertyValue `pulumi:"modifiedOn"`
Policies []ApiTokenPolicy `pulumi:"policies"`
}

type ApiTokenPolicyPermissionGroupMeta struct {
Key resource.PropertyValue `pulumi:"key"`
Value resource.PropertyValue `pulumi:"value"`
}

type ApiTokenPolicyPermissionGroup struct {
Id resource.PropertyValue `pulumi:"id"`
Meta ApiTokenPolicyPermissionGroupMeta `pulumi:"meta"`
Name resource.PropertyValue `pulumi:"name"`
}

type ApiTokenPolicy1 struct {
PermissionGroups []ApiTokenPolicyPermissionGroup `pulumi:"permissionGroups"`
Resources map[string]resource.PropertyValue `pulumi:"resources"`
Effect resource.PropertyValue `pulumi:"effect"`
Id resource.PropertyValue `pulumi:"id"`
}

type ApiTokenConditionRequestIp1 struct {
NotIns []resource.PropertyValue `pulumi:"notIns"`
Ins []resource.PropertyValue `pulumi:"ins"`
}

type ApiTokenCondition1 struct {
RequestIp ApiTokenConditionRequestIp1 `pulumi:"requestIp"`
}

type R2State struct {
IssuedOn resource.PropertyValue `pulumi:"issuedOn"`
LastUsedOn resource.PropertyValue `pulumi:"lastUsedOn"`
Name resource.PropertyValue `pulumi:"name"`
Policies []ApiTokenPolicy1 `pulumi:"policies"`
Condition ApiTokenCondition1 `pulumi:"condition"`
ExpiresOn resource.PropertyValue `pulumi:"expiresOn"`
Status resource.PropertyValue `pulumi:"status"`
Value resource.PropertyValue `pulumi:"value"`
ModifiedOn resource.PropertyValue `pulumi:"modifiedOn"`
NotBefore resource.PropertyValue `pulumi:"notBefore"`
}

func Migrate(r1 R1State) (R2State, error) {
// Migrate policies
var policies []ApiTokenPolicy1
for _, p := range r1.Policies {
// Convert permissionGroups from []resource.PropertyValue to []ApiTokenPolicyPermissionGroup
var permissionGroups []ApiTokenPolicyPermissionGroup
for _, pg := range p.PermissionGroups {
permissionGroups = append(permissionGroups, ApiTokenPolicyPermissionGroup{
Id: pg,
// Meta and Name are optional, so we leave them unset
})
}

policy1 := ApiTokenPolicy1{
PermissionGroups: permissionGroups,
Resources: p.Resources,
Effect: p.Effect,
// Id is optional, so we leave it unset
}
policies = append(policies, policy1)
}

// Migrate condition
condition1 := ApiTokenCondition1{
RequestIp: ApiTokenConditionRequestIp1{
NotIns: r1.Condition.RequestIp.NotIns,
Ins: r1.Condition.RequestIp.Ins,
},
}

return R2State{
IssuedOn: r1.IssuedOn,
LastUsedOn: resource.PropertyValue{}, // New field, set to zero value
Name: r1.Name,
Policies: policies,
Condition: condition1,
ExpiresOn: r1.ExpiresOn,
Status: r1.Status,
Value: r1.Value,
ModifiedOn: r1.ModifiedOn,
NotBefore: r1.NotBefore,
}, nil
}
5 changes: 5 additions & 0 deletions provider/provider_program_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,11 @@ func TestAccessPolicyUpgrade(t *testing.T) {
t, "test-programs/access_policy/access_policyv5", optproviderupgrade.NewSourcePath("test-programs/access_policy"))
}

func TestApiTokenUpgrade(t *testing.T) {
testUpgrade(t, "test-programs/api_token/v5",
optproviderupgrade.NewSourcePath("test-programs/api_token"))
}

func TestRuleSetUpgrade(t *testing.T) {
testUpgrade(t, "test-programs/ruleset/ruleset_v5")
}
Expand Down
6 changes: 6 additions & 0 deletions provider/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import (
"github.com/pulumi/pulumi-terraform-bridge/v3/pkg/tfgen"
"github.com/pulumi/pulumi/sdk/v3/go/common/resource"

migratetoken "github.com/pulumi/pulumi-cloudflare/provider/v6/pkg/migrations/token"
"github.com/pulumi/pulumi-cloudflare/provider/v6/pkg/version"
)

Expand Down Expand Up @@ -94,6 +95,11 @@ func Provider() info.Provider {
},

Resources: map[string]*info.Resource{
"cloudflare_api_token": {
Tok: "cloudflare:index/apiToken:ApiToken",
PreStateUpgradeHook: migratetoken.PreStateUpgradeHook,
},

// We cannot use TF's ID field as Pulumi's ID field automatically,
// since it can (theoretically) be set by the user.
//
Expand Down
21 changes: 21 additions & 0 deletions provider/test-programs/api_token/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: example-ruleset
runtime: yaml

config:
cloudflare-zone-id:
type: string

resources:
exampleApiToken:
type: cloudflare:index/apiToken:ApiToken
properties:
name: "readonly token"
policies:
- effect: "allow"
permissionGroups:
- id: "c8fed203ed3043cba015a93ad1616f1f"
- id: "82e64a83756745bbbb1c9c2701bf816b"
resources:
"com.cloudflare.api.account.zone.${cloudflare-zone-id}": "*"
expiresOn: "2030-01-01T00:00:00Z"
notBefore: "2018-07-01T05:20:00Z"
23 changes: 23 additions & 0 deletions provider/test-programs/api_token/v5/Pulumi.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
name: example-ruleset
runtime: yaml

config:
cloudflare-zone-id:
type: string

resources:
exampleApiToken:
type: cloudflare:index/apiToken:ApiToken
options:
version: 5.49.1
properties:
name: "readonly token"
policies:
- effect: "allow"
permissionGroups:
- "c8fed203ed3043cba015a93ad1616f1f"
- "82e64a83756745bbbb1c9c2701bf816b"
resources:
"com.cloudflare.api.account.zone.${cloudflare-zone-id}": "*"
expiresOn: "2030-01-01T00:00:00Z"
notBefore: "2018-07-01T05:20:00Z"
22 changes: 22 additions & 0 deletions provider/testdata/recorded/TestProviderUpgrade/v5/5.49.0/grpc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{"method":"/pulumirpc.LanguageRuntime/GetPluginInfo","request":{},"response":{"version":"v1.21.1"}}
{"method":"/pulumirpc.LanguageRuntime/GetRequiredPackages","request":{"info":{"entryPoint":".","options":{},"programDirectory":"/private/var/folders/gd/3ncjb1lj5ljgk8xl5ssn_gvc0000gn/T/com.apple.shortcuts.mac-helper/TestApiTokenUpgrade3952610907/007/v5","rootDirectory":"/private/var/folders/gd/3ncjb1lj5ljgk8xl5ssn_gvc0000gn/T/com.apple.shortcuts.mac-helper/TestApiTokenUpgrade3952610907/007/v5"}},"response":{"packages":[{"kind":"resource","name":"cloudflare","version":"5.49.1"}]}}
{"method":"/pulumirpc.ResourceMonitor/SupportsFeature","request":{"id":"resourceReferences"},"response":{"hasSupport":true}}
{"method":"/pulumirpc.ResourceMonitor/SupportsFeature","request":{"id":"outputValues"},"response":{"hasSupport":true}}
{"method":"/pulumirpc.ResourceMonitor/SupportsFeature","request":{"id":"deletedWith"},"response":{"hasSupport":true}}
{"method":"/pulumirpc.ResourceMonitor/SupportsFeature","request":{"id":"aliasSpecs"},"response":{"hasSupport":true}}
{"method":"/pulumirpc.ResourceMonitor/SupportsFeature","request":{"id":"transforms"},"response":{"hasSupport":true}}
{"method":"/pulumirpc.ResourceMonitor/SupportsFeature","request":{"id":"invokeTransforms"},"response":{"hasSupport":true}}
{"method":"/pulumirpc.ResourceMonitor/SupportsFeature","request":{"id":"parameterization"},"response":{"hasSupport":true}}
{"method":"/pulumirpc.ResourceMonitor/RegisterResource","request":{"acceptResources":true,"acceptSecrets":true,"customTimeouts":{},"name":"example-ruleset-test","object":{},"sourcePosition":{"line":317,"uri":"project://%2Fhome%2Frunner%2Fwork%2Fpulumi-yaml%2Fpulumi-yaml%2Fpkg%2Fserver%2Fserver.go"},"supportsResultReporting":true,"type":"pulumi:pulumi:Stack"},"response":{"object":{},"urn":"urn:pulumi:test::example-ruleset::pulumi:pulumi:Stack::example-ruleset-test"}}
{"method":"/pulumirpc.ResourceMonitor/RegisterResourceOutputs","request":{"outputs":{},"urn":"urn:pulumi:test::example-ruleset::pulumi:pulumi:Stack::example-ruleset-test"},"response":{}}
{"method":"/pulumirpc.ResourceProvider/Handshake","request":{"configureWithUrn":true,"engineAddress":"127.0.0.1:60577","supportsRefreshBeforeUpdate":true,"supportsViews":true}}
{"method":"/pulumirpc.ResourceProvider/Attach","request":{"address":"127.0.0.1:60577"},"response":{}}
{"method":"/pulumirpc.ResourceProvider/GetPluginInfo","request":{},"response":{"version":"5.49.0"}}
{"method":"/pulumirpc.ResourceProvider/CheckConfig","request":{"name":"default_5_49_1","news":{"version":"5.49.1"},"olds":{},"type":"pulumi:providers:cloudflare","urn":"urn:pulumi:test::example-ruleset::pulumi:providers:cloudflare::default_5_49_1"},"response":{"inputs":{"apiClientLogging":"false","maxBackoff":"30","minBackoff":"1","retries":"3","rps":"4","version":"5.49.1"}}}
{"method":"/pulumirpc.ResourceProvider/Configure","request":{"acceptResources":true,"acceptSecrets":true,"args":{"apiClientLogging":"false","maxBackoff":"30","minBackoff":"1","retries":"3","rps":"4","version":"5.49.1"},"id":"e8048b51-bf6d-4fd8-bd29-bd4049eb5aea","name":"default_5_49_1","sendsOldInputs":true,"sendsOldInputsToDelete":true,"type":"pulumi:providers:cloudflare","urn":"urn:pulumi:test::example-ruleset::pulumi:providers:cloudflare::default_5_49_1","variables":{"cloudflare:config:apiClientLogging":"false","cloudflare:config:maxBackoff":"30","cloudflare:config:minBackoff":"1","cloudflare:config:retries":"3","cloudflare:config:rps":"4"}},"response":{"supportsAutonamingConfiguration":true,"supportsPreview":true}}
{"method":"/pulumirpc.ResourceProvider/Check","request":{"name":"exampleApiToken","news":{"expiresOn":"2030-01-01T00:00:00Z","name":"readonly token","notBefore":"2018-07-01T05:20:00Z","policies":[{"effect":"allow","permissionGroups":["c8fed203ed3043cba015a93ad1616f1f","82e64a83756745bbbb1c9c2701bf816b"],"resources":{"com.cloudflare.api.account.zone.cabcdb3c8548af2e275acc42ed1fea45":"*"}}]},"olds":{},"randomSeed":"9tE1mdYAiXR4mICtKrRcxU20R+0EL1hacIU99yMoLy8=","type":"cloudflare:index/apiToken:ApiToken","urn":"urn:pulumi:test::example-ruleset::cloudflare:index/apiToken:ApiToken::exampleApiToken"},"response":{"inputs":{"__defaults":[],"expiresOn":"2030-01-01T00:00:00Z","name":"readonly token","notBefore":"2018-07-01T05:20:00Z","policies":[{"__defaults":[],"effect":"allow","permissionGroups":["c8fed203ed3043cba015a93ad1616f1f","82e64a83756745bbbb1c9c2701bf816b"],"resources":{"com.cloudflare.api.account.zone.cabcdb3c8548af2e275acc42ed1fea45":"*"}}]}}}
{"method":"/pulumirpc.ResourceProvider/Create","request":{"name":"exampleApiToken","properties":{"__defaults":[],"expiresOn":"2030-01-01T00:00:00Z","name":"readonly token","notBefore":"2018-07-01T05:20:00Z","policies":[{"__defaults":[],"effect":"allow","permissionGroups":["c8fed203ed3043cba015a93ad1616f1f","82e64a83756745bbbb1c9c2701bf816b"],"resources":{"com.cloudflare.api.account.zone.cabcdb3c8548af2e275acc42ed1fea45":"*"}}]},"resourceStatusAddress":"127.0.0.1:60580","resourceStatusToken":"34007757-dabf-4778-b2b6-179eae598f78","type":"cloudflare:index/apiToken:ApiToken","urn":"urn:pulumi:test::example-ruleset::cloudflare:index/apiToken:ApiToken::exampleApiToken"},"response":{"id":"a87de25e1833e5e0b52e69547673b478","properties":{"condition":null,"expiresOn":"2030-01-01T00:00:00Z","id":"a87de25e1833e5e0b52e69547673b478","issuedOn":"2025-07-01T20:01:23Z","modifiedOn":"2025-07-01T20:01:24Z","name":"readonly token","notBefore":"2018-07-01T05:20:00Z","policies":[{"effect":"allow","permissionGroups":["82e64a83756745bbbb1c9c2701bf816b","c8fed203ed3043cba015a93ad1616f1f"],"resources":{"com.cloudflare.api.account.zone.cabcdb3c8548af2e275acc42ed1fea45":"*"}}],"status":"active","value":{"4dabf18193072939515e22adb298388d":"1b47061264138c4ac30d75fd1eb44270","value":"REDACTED BY PROVIDERTEST"}}}}
{"method":"/pulumirpc.ResourceMonitor/RegisterResource","request":{"acceptResources":true,"acceptSecrets":true,"additionalSecretOutputs":["value"],"custom":true,"customTimeouts":{},"name":"exampleApiToken","object":{"expiresOn":"2030-01-01T00:00:00Z","name":"readonly token","notBefore":"2018-07-01T05:20:00Z","policies":[{"effect":"allow","permissionGroups":["c8fed203ed3043cba015a93ad1616f1f","82e64a83756745bbbb1c9c2701bf816b"],"resources":{"com.cloudflare.api.account.zone.cabcdb3c8548af2e275acc42ed1fea45":"*"}}]},"parent":"urn:pulumi:test::example-ruleset::pulumi:pulumi:Stack::example-ruleset-test","propertyDependencies":{"expiresOn":{},"name":{},"notBefore":{},"policies":{}},"sourcePosition":{"line":1357,"uri":"project://%2Fhome%2Frunner%2Fwork%2Fpulumi-yaml%2Fpulumi-yaml%2Fpkg%2Fpulumiyaml%2Frun.go"},"supportsResultReporting":true,"type":"cloudflare:index/apiToken:ApiToken","version":"5.49.1"},"response":{"id":"a87de25e1833e5e0b52e69547673b478","object":{"condition":null,"expiresOn":"2030-01-01T00:00:00Z","id":"a87de25e1833e5e0b52e69547673b478","issuedOn":"2025-07-01T20:01:23Z","modifiedOn":"2025-07-01T20:01:24Z","name":"readonly token","notBefore":"2018-07-01T05:20:00Z","policies":[{"effect":"allow","permissionGroups":["82e64a83756745bbbb1c9c2701bf816b","c8fed203ed3043cba015a93ad1616f1f"],"resources":{"com.cloudflare.api.account.zone.cabcdb3c8548af2e275acc42ed1fea45":"*"}}],"status":"active","value":{"4dabf18193072939515e22adb298388d":"1b47061264138c4ac30d75fd1eb44270","value":"REDACTED BY PROVIDERTEST"}},"urn":"urn:pulumi:test::example-ruleset::cloudflare:index/apiToken:ApiToken::exampleApiToken"}}
{"method":"/pulumirpc.LanguageRuntime/Run","request":{"config":{"example-ruleset:cloudflare-account-id":"48364b099cc965f71761d67bc5314bd4","example-ruleset:cloudflare-domain":"pulumi-cloudflare-demo.com","example-ruleset:cloudflare-zone-id":"cabcdb3c8548af2e275acc42ed1fea45"},"configPropertyMap":{"example-ruleset:cloudflare-account-id":"48364b099cc965f71761d67bc5314bd4","example-ruleset:cloudflare-domain":"pulumi-cloudflare-demo.com","example-ruleset:cloudflare-zone-id":"cabcdb3c8548af2e275acc42ed1fea45"},"info":{"entryPoint":".","options":{},"programDirectory":"/private/var/folders/gd/3ncjb1lj5ljgk8xl5ssn_gvc0000gn/T/com.apple.shortcuts.mac-helper/TestApiTokenUpgrade3952610907/007/v5","rootDirectory":"/private/var/folders/gd/3ncjb1lj5ljgk8xl5ssn_gvc0000gn/T/com.apple.shortcuts.mac-helper/TestApiTokenUpgrade3952610907/007/v5"},"loaderTarget":"127.0.0.1:60582","monitorAddress":"127.0.0.1:60581","organization":"organization","parallel":48,"program":".","project":"example-ruleset","pwd":"/private/var/folders/gd/3ncjb1lj5ljgk8xl5ssn_gvc0000gn/T/com.apple.shortcuts.mac-helper/TestApiTokenUpgrade3952610907/007/v5","stack":"test"},"response":{}}
{"method":"/grpc.health.v1.Health/Check","request":{},"response":{"status":"SERVING"}}
{"method":"/grpc.health.v1.Health/Check","request":{},"response":{"status":"SERVING"}}
115 changes: 115 additions & 0 deletions provider/testdata/recorded/TestProviderUpgrade/v5/5.49.0/stack.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
{
"version": 3,
"deployment": {
"manifest": {
"time": "2025-07-01T16:01:24.261247-04:00",
"magic": "6a5f1cff8ef65523800fc5c9de7d17699a6e5b813cf7d2dab78054c0abf00cfc",
"version": "v3.178.0"
},
"secrets_providers": {
"type": "passphrase",
"state": {
"salt": "v1:9EFQYES7DEM=:v1:/yV4XJT+VnJdTPrr:YmC0elvpt+d94OiOUmUjZVa/2uig1Q=="
}
},
"resources": [
{
"urn": "urn:pulumi:test::example-ruleset::pulumi:pulumi:Stack::example-ruleset-test",
"custom": false,
"type": "pulumi:pulumi:Stack",
"created": "2025-07-01T20:01:23.607367Z",
"modified": "2025-07-01T20:01:23.607367Z"
},
{
"urn": "urn:pulumi:test::example-ruleset::pulumi:providers:cloudflare::default_5_49_1",
"custom": true,
"id": "e8048b51-bf6d-4fd8-bd29-bd4049eb5aea",
"type": "pulumi:providers:cloudflare",
"inputs": {
"__internal": {},
"apiClientLogging": "false",
"maxBackoff": "30",
"minBackoff": "1",
"retries": "3",
"rps": "4",
"version": "5.49.1"
},
"outputs": {
"apiClientLogging": "false",
"maxBackoff": "30",
"minBackoff": "1",
"retries": "3",
"rps": "4",
"version": "5.49.1"
},
"created": "2025-07-01T20:01:23.621232Z",
"modified": "2025-07-01T20:01:23.621232Z"
},
{
"urn": "urn:pulumi:test::example-ruleset::cloudflare:index/apiToken:ApiToken::exampleApiToken",
"custom": true,
"id": "a87de25e1833e5e0b52e69547673b478",
"type": "cloudflare:index/apiToken:ApiToken",
"inputs": {
"__defaults": [],
"expiresOn": "2030-01-01T00:00:00Z",
"name": "readonly token",
"notBefore": "2018-07-01T05:20:00Z",
"policies": [
{
"__defaults": [],
"effect": "allow",
"permissionGroups": [
"c8fed203ed3043cba015a93ad1616f1f",
"82e64a83756745bbbb1c9c2701bf816b"
],
"resources": {
"com.cloudflare.api.account.zone.cabcdb3c8548af2e275acc42ed1fea45": "*"
}
}
]
},
"outputs": {
"condition": null,
"expiresOn": "2030-01-01T00:00:00Z",
"id": "a87de25e1833e5e0b52e69547673b478",
"issuedOn": "2025-07-01T20:01:23Z",
"modifiedOn": "2025-07-01T20:01:24Z",
"name": "readonly token",
"notBefore": "2018-07-01T05:20:00Z",
"policies": [
{
"effect": "allow",
"permissionGroups": [
"82e64a83756745bbbb1c9c2701bf816b",
"c8fed203ed3043cba015a93ad1616f1f"
],
"resources": {
"com.cloudflare.api.account.zone.cabcdb3c8548af2e275acc42ed1fea45": "*"
}
}
],
"status": "active",
"value": {
"4dabf18193072939515e22adb298388d": "1b47061264138c4ac30d75fd1eb44270",
"plaintext": "\"REDACTED BY PROVIDERTEST\""
}
},
"parent": "urn:pulumi:test::example-ruleset::pulumi:pulumi:Stack::example-ruleset-test",
"provider": "urn:pulumi:test::example-ruleset::pulumi:providers:cloudflare::default_5_49_1::e8048b51-bf6d-4fd8-bd29-bd4049eb5aea",
"propertyDependencies": {
"expiresOn": [],
"name": [],
"notBefore": [],
"policies": []
},
"additionalSecretOutputs": [
"value"
],
"created": "2025-07-01T20:01:24.255885Z",
"modified": "2025-07-01T20:01:24.255885Z"
}
],
"metadata": {}
}
}
Loading