Add Go support for config.*Object (#3526)

This commit is contained in:
Evan Boyle 2019-11-18 18:53:27 -08:00 committed by GitHub
parent 3ac8dd5285
commit 8547ede659
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 128 additions and 0 deletions

View file

@ -3,6 +3,8 @@ CHANGELOG
## HEAD (Unreleased)
- Support for config.GetObject and related variants for Golang. [#3526](https://github.com/pulumi/pulumi/pull/3526)
- Add support for IgnoreChanges in the go SDK [#3514](https://github.com/pulumi/pulumi/pull/3514)
- Support for a `go run` style workflow. Building or installing a pulumi program written in go is

View file

@ -85,6 +85,12 @@ func (c *Config) GetInt64(key string) int64 {
return GetInt64(c.ctx, c.fullKey(key))
}
// GetObject loads an optional configuration value into the specified output by its key,
// or returns an error if unable to do so.
func (c *Config) GetObject(key string, output interface{}) error {
return GetObject(c.ctx, c.fullKey(key), output)
}
// GetUint loads an optional uint configuration value by its key, or returns 0 if it doesn't exist.
func (c *Config) GetUint(key string) uint {
return GetUint(c.ctx, c.fullKey(key))
@ -155,6 +161,12 @@ func (c *Config) RequireInt64(key string) int64 {
return RequireInt64(c.ctx, c.fullKey(key))
}
// RequireObject loads a required configuration value into the specified output by its key,
// or panics if unable to do so.
func (c *Config) RequireObject(key string, output interface{}) {
RequireObject(c.ctx, c.fullKey(key), output)
}
// RequireUint loads a uint configuration value by its key, or panics if it doesn't exist.
func (c *Config) RequireUint(key string) uint {
return RequireUint(c.ctx, c.fullKey(key))
@ -225,6 +237,12 @@ func (c *Config) TryInt64(key string) (int64, error) {
return TryInt64(c.ctx, c.fullKey(key))
}
// TryObject loads an optional configuration value into the specified output by its key,
// or returns an error if unable to do so.
func (c *Config) TryObject(key string, output interface{}) error {
return TryObject(c.ctx, c.fullKey(key), output)
}
// TryUint loads an optional uint configuration value by its key, or returns an error if it doesn't exist.
func (c *Config) TryUint(key string) (uint, error) {
return TryUint(c.ctx, c.fullKey(key))

View file

@ -23,6 +23,11 @@ import (
"github.com/pulumi/pulumi/sdk/go/pulumi"
)
type TestStruct struct {
Foo map[string]string
Bar string
}
// TestConfig tests the basic config wrapper.
func TestConfig(t *testing.T) {
ctx, err := pulumi.NewContext(context.Background(), pulumi.RunInfo{
@ -31,12 +36,33 @@ func TestConfig(t *testing.T) {
"testpkg:bbb": "true",
"testpkg:intint": "42",
"testpkg:fpfpfp": "99.963",
"testpkg:obj": `
{
"foo": {
"a": "1",
"b": "2"
},
"bar": "abc"
}
`,
"testpkg:malobj": "not_a_struct",
},
})
assert.Nil(t, err)
cfg := New(ctx, "testpkg")
var testStruct TestStruct
var emptyTestStruct TestStruct
fooMap := make(map[string]string)
fooMap["a"] = "1"
fooMap["b"] = "2"
expectedTestStruct := TestStruct{
Foo: fooMap,
Bar: "abc",
}
// Test basic keys.
assert.Equal(t, "testpkg:sss", cfg.fullKey("sss"))
@ -46,12 +72,43 @@ func TestConfig(t *testing.T) {
assert.Equal(t, 42, cfg.GetInt("intint"))
assert.Equal(t, 99.963, cfg.GetFloat64("fpfpfp"))
assert.Equal(t, "", cfg.Get("missing"))
// missing key GetObj
err = cfg.GetObject("missing", &testStruct)
assert.Equal(t, emptyTestStruct, testStruct)
assert.Nil(t, err)
testStruct = TestStruct{}
// malformed key GetObj
err = cfg.GetObject("malobj", &testStruct)
assert.Equal(t, emptyTestStruct, testStruct)
assert.NotNil(t, err)
testStruct = TestStruct{}
// GetObj
err = cfg.GetObject("obj", &testStruct)
assert.Equal(t, expectedTestStruct, testStruct)
assert.Nil(t, err)
testStruct = TestStruct{}
// Test Require, which panics for missing entries.
assert.Equal(t, "a string value", cfg.Require("sss"))
assert.Equal(t, true, cfg.RequireBool("bbb"))
assert.Equal(t, 42, cfg.RequireInt("intint"))
assert.Equal(t, 99.963, cfg.RequireFloat64("fpfpfp"))
cfg.RequireObject("obj", &testStruct)
assert.Equal(t, expectedTestStruct, testStruct)
testStruct = TestStruct{}
// GetObj panics if value is malformed
willPanic := func() { cfg.RequireObject("malobj", &testStruct) }
assert.Panics(t, willPanic)
testStruct = TestStruct{}
func() {
defer func() {
if r := recover(); r == nil {
t.Errorf("expected malformed value for RequireObject to panic")
}
}()
cfg.RequireObject("malobj", &testStruct)
}()
testStruct = TestStruct{}
func() {
defer func() {
if r := recover(); r == nil {
@ -74,6 +131,21 @@ func TestConfig(t *testing.T) {
k4, err := cfg.TryFloat64("fpfpfp")
assert.Nil(t, err)
assert.Equal(t, 99.963, k4)
// happy path TryObject
err = cfg.TryObject("obj", &testStruct)
assert.Nil(t, err)
assert.Equal(t, expectedTestStruct, testStruct)
testStruct = TestStruct{}
// missing TryObject
err = cfg.TryObject("missing", &testStruct)
assert.NotNil(t, err)
assert.Equal(t, emptyTestStruct, testStruct)
testStruct = TestStruct{}
// malformed TryObject
err = cfg.TryObject("malobj", &testStruct)
assert.NotNil(t, err)
assert.Equal(t, emptyTestStruct, testStruct)
testStruct = TestStruct{}
_, err = cfg.Try("missing")
assert.NotNil(t, err)
}

View file

@ -15,6 +15,8 @@
package config
import (
"encoding/json"
"github.com/spf13/cast"
"github.com/pulumi/pulumi/sdk/go/pulumi"
@ -90,6 +92,17 @@ func GetInt64(ctx *pulumi.Context, key string) int64 {
return 0
}
// GetObject attempts to load an optional configuration value by its key into the specified output variable.
func GetObject(ctx *pulumi.Context, key string, output interface{}) error {
if v, ok := ctx.GetConfig(key); ok {
if err := json.Unmarshal([]byte(v), output); err != nil {
return err
}
}
return nil
}
// GetUint loads an optional configuration value by its key, as a uint, or returns 0 if it doesn't exist.
func GetUint(ctx *pulumi.Context, key string) uint {
if v, ok := ctx.GetConfig(key); ok {

View file

@ -15,6 +15,8 @@
package config
import (
"encoding/json"
"github.com/spf13/cast"
"github.com/pulumi/pulumi/pkg/util/contract"
@ -78,6 +80,15 @@ func RequireInt64(ctx *pulumi.Context, key string) int64 {
return cast.ToInt64(v)
}
// RequireObject loads an optional configuration value by its key into the output variable,
// or panics if unable to do so.
func RequireObject(ctx *pulumi.Context, key string, output interface{}) {
v := Require(ctx, key)
if err := json.Unmarshal([]byte(v), output); err != nil {
contract.Failf("unable to unmarshall required configuration variable '%s'; %s", key, err.Error())
}
}
// RequireUint loads an optional configuration value by its key, as a uint, or panics if it doesn't exist.
func RequireUint(ctx *pulumi.Context, key string) uint {
v := Require(ctx, key)

View file

@ -15,6 +15,8 @@
package config
import (
"encoding/json"
"github.com/pkg/errors"
"github.com/spf13/cast"
@ -103,6 +105,16 @@ func TryInt64(ctx *pulumi.Context, key string) (int64, error) {
return cast.ToInt64(v), nil
}
// TryObject loads an optional configuration value by its key into the output variable,
// or returns an error if unable to do so.
func TryObject(ctx *pulumi.Context, key string, output interface{}) error {
v, err := Try(ctx, key)
if err != nil {
return err
}
return json.Unmarshal([]byte(v), output)
}
// TryUint loads an optional configuration value by its key, as a uint, or returns an error if it doesn't exist.
func TryUint(ctx *pulumi.Context, key string) (uint, error) {
v, err := Try(ctx, key)