diff --git a/go.mod b/go.mod index 7bfb9ec..bc50492 100644 --- a/go.mod +++ b/go.mod @@ -15,8 +15,7 @@ require ( github.com/muesli/reflow v0.3.0 github.com/otiai10/copy v1.14.0 github.com/pulumi/providertest v0.0.12 - github.com/pulumi/pulumi-go-provider v0.16.0 - github.com/pulumi/pulumi-go-provider/integration v0.10.1-0.20240314105842-9fbffb634faf + github.com/pulumi/pulumi-go-provider v0.16.1-0.20240426163030-72606b1e6fb7 github.com/pulumi/pulumi-java/pkg v0.10.0 github.com/pulumi/pulumi/pkg/v3 v3.113.3 github.com/pulumi/pulumi/sdk/go/pulumi-language-go/v3 v3.0.0-20240415162817-44c8de53d5d2 @@ -455,7 +454,7 @@ require ( golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect golang.org/x/exp/typeparams v0.0.0-20240314144324-c7f7c6466f7f // indirect golang.org/x/mod v0.16.0 // indirect - golang.org/x/net v0.22.0 // indirect + golang.org/x/net v0.23.0 // indirect golang.org/x/oauth2 v0.18.0 // indirect golang.org/x/sync v0.6.0 // indirect golang.org/x/sys v0.18.0 // indirect diff --git a/go.sum b/go.sum index e564154..c0f092a 100644 --- a/go.sum +++ b/go.sum @@ -2316,10 +2316,8 @@ github.com/pulumi/esc v0.6.2 h1:+z+l8cuwIauLSwXQS0uoI3rqB+YG4SzsZYtHfNoXBvw= github.com/pulumi/esc v0.6.2/go.mod h1:jNnYNjzsOgVTjCp0LL24NsCk8ZJxq4IoLQdCT0X7l8k= github.com/pulumi/providertest v0.0.12 h1:UjcFQHHs4AGJyJqxhvC2q8yVQ7Li+UyCyP95HZcK03U= github.com/pulumi/providertest v0.0.12/go.mod h1:REAoaN+hGOtdWJGirfWYqcSjCejlbGfzyVTUuemJTuE= -github.com/pulumi/pulumi-go-provider v0.16.0 h1:vLAiECprIoLdTPd0UFs9Vv/HgSw7l/SBAurRBm3vpSU= -github.com/pulumi/pulumi-go-provider v0.16.0/go.mod h1:2yjjeyMSmsb/o/BRJeWk+kcXrJWF5U2EulJKnN7qVLs= -github.com/pulumi/pulumi-go-provider/integration v0.10.1-0.20240314105842-9fbffb634faf h1:7fDWArOUFH+qQ9EywoC4K2ElXP76Ks/CtVJkEBmv2pk= -github.com/pulumi/pulumi-go-provider/integration v0.10.1-0.20240314105842-9fbffb634faf/go.mod h1:sf87soow+4JkV361vHI0W04hpJmWiWajzJytFMNonCE= +github.com/pulumi/pulumi-go-provider v0.16.1-0.20240426163030-72606b1e6fb7 h1:zHoiZbyFIeEfdoaqwA9Lp3jzdDgtdCPKM2aWhaA4EGg= +github.com/pulumi/pulumi-go-provider v0.16.1-0.20240426163030-72606b1e6fb7/go.mod h1:sJUl1EjF3BQXAkrOeRhS3kZq17lz2o2QnTQd+c1FepU= github.com/pulumi/pulumi-java/pkg v0.10.0 h1:D1i5MiiNrxYr2uJ1szcj1aQwF9DYv7TTsPmajB9dKSw= github.com/pulumi/pulumi-java/pkg v0.10.0/go.mod h1:xu6UgYtQm+xXOo1/DZNa2CWVPytu+RMkZVTtI7w7ffY= github.com/pulumi/pulumi-yaml v1.6.0 h1:mb/QkebWXTa1fR+P3ZkCCHGXOYC6iTN8X8By9eNz8xM= @@ -3003,8 +3001,8 @@ golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= -golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= diff --git a/provider/internal/cli.go b/provider/internal/cli.go index bf58da4..771e21e 100644 --- a/provider/internal/cli.go +++ b/provider/internal/cli.go @@ -19,6 +19,7 @@ package internal import ( "bufio" "bytes" + "context" "encoding/json" "errors" "fmt" @@ -40,7 +41,6 @@ import ( "github.com/sirupsen/logrus" provider "github.com/pulumi/pulumi-go-provider" - "github.com/pulumi/pulumi/sdk/v3/go/common/diag" "github.com/pulumi/pulumi/sdk/v3/go/common/resource" "github.com/pulumi/pulumi/sdk/v3/go/common/util/contract" ) @@ -157,7 +157,7 @@ func (c *cli) rc() *regclient.RegClient { // tail is meant to be called as a goroutine and will pipe output from the CLI // back to the Pulumi engine. Requires a corresponding call to close. -func (c *cli) tail(ctx provider.Context) { +func (c *cli) tail(ctx context.Context) { c.done = make(chan struct{}, 1) defer func() { c.done <- struct{}{} @@ -171,18 +171,18 @@ func (c *cli) tail(ctx provider.Context) { s := bufio.NewScanner(c.r) for s.Scan() { text := s.Text() - ctx.LogStatus(diag.Info, text) + provider.GetLogger(ctx).InfoStatus(text) _, _ = b.WriteString(text + "\n") } - ctx.LogStatus(diag.Info, "") // clear confusing "DONE" statements. + provider.GetLogger(ctx).InfoStatus("") // clear confusing "DONE" statements. if c.dumplogs { // Persist the full Docker output on error for easier debugging. if b.Len() > 0 { - ctx.Log(diag.Info, b.String()) + provider.GetLogger(ctx).Info(b.String()) } if c.err.Len() > 0 { - ctx.Log(diag.Error, c.err.String()) + provider.GetLogger(ctx).Error(c.err.String()) } } } diff --git a/provider/internal/client.go b/provider/internal/client.go index 34ef2fd..6a37ce5 100644 --- a/provider/internal/client.go +++ b/provider/internal/client.go @@ -45,20 +45,19 @@ import ( "github.com/regclient/regclient/types/ref" provider "github.com/pulumi/pulumi-go-provider" - "github.com/pulumi/pulumi/sdk/v3/go/common/diag" "github.com/pulumi/pulumi/sdk/v3/go/common/util/contract" ) // Client handles all our Docker API calls. type Client interface { - Build(ctx provider.Context, b Build) (*client.SolveResponse, error) + Build(ctx context.Context, b Build) (*client.SolveResponse, error) BuildKitEnabled() (bool, error) Inspect(ctx context.Context, id string) ([]descriptor.Descriptor, error) Delete(ctx context.Context, id string) error - ManifestCreate(ctx provider.Context, push bool, target string, refs ...string) error - ManifestInspect(ctx provider.Context, target string) (string, error) - ManifestDelete(ctx provider.Context, target string) error + ManifestCreate(ctx context.Context, push bool, target string, refs ...string) error + ManifestInspect(ctx context.Context, target string) (string, error) + ManifestDelete(ctx context.Context, target string) error } // Build encapsulates all of the user-provider build parameters and options. @@ -98,13 +97,12 @@ func newDockerCLI(config *Config) (*command.DockerCli, error) { // "default", if no targets were specified) to SolveResponses, which capture // the build's digest and tags (if any). func (c *cli) Build( - pctx provider.Context, + ctx context.Context, build Build, ) (*client.SolveResponse, error) { - ctx := context.Context(pctx) opts := build.BuildOptions() - go c.tail(pctx) + go c.tail(ctx) defer contract.IgnoreClose(c) if build.ShouldExec() { @@ -134,7 +132,7 @@ func (c *cli) Build( for _, d := range w.Detail { fmt.Fprintf(b, "\n%s", d) } - pctx.Log(diag.Warning, b.String()) + provider.GetLogger(ctx).Warning(b.String()) } }() @@ -247,7 +245,7 @@ func (c *cli) BuildKitEnabled() (bool, error) { return c.Cli.BuildKitEnabled() } -func (c *cli) ManifestCreate(ctx provider.Context, push bool, target string, refs ...string) error { +func (c *cli) ManifestCreate(ctx context.Context, push bool, target string, refs ...string) error { go c.tail(ctx) defer contract.IgnoreClose(c) @@ -271,11 +269,11 @@ func (c *cli) ManifestCreate(ctx provider.Context, push bool, target string, ref cmd.SetErr(c.Err()) cmd.SetOut(c.Out()) - ctx.Log(diag.Debug, fmt.Sprint("creating manifest with args", args)) + provider.GetLogger(ctx).Debug(fmt.Sprint("creating manifest with args", args)) return cmd.ExecuteContext(ctx) } -func (c *cli) ManifestInspect(ctx provider.Context, target string) (string, error) { +func (c *cli) ManifestInspect(ctx context.Context, target string) (string, error) { rc := c.rc() ref, err := ref.New(target) @@ -291,7 +289,7 @@ func (c *cli) ManifestInspect(ctx provider.Context, target string) (string, erro return string(m.GetDescriptor().Digest), nil } -func (c *cli) ManifestDelete(ctx provider.Context, target string) error { +func (c *cli) ManifestDelete(ctx context.Context, target string) error { rc := c.rc() ref, err := ref.New(target) @@ -299,9 +297,9 @@ func (c *cli) ManifestDelete(ctx provider.Context, target string) error { return err } - err = rc.ManifestDelete(context.Context(ctx), ref) + err = rc.ManifestDelete(ctx, ref) if errors.Is(err, errs.ErrHTTPStatus) { - ctx.Log(diag.Warning, "this registry does not support deletions") + provider.GetLogger(ctx).Warning("this registry does not support deletions") return nil } if err != nil { diff --git a/provider/internal/client_test.go b/provider/internal/client_test.go index 6970f4f..c7f5c93 100644 --- a/provider/internal/client_test.go +++ b/provider/internal/client_test.go @@ -17,6 +17,8 @@ package internal import ( "bytes" "context" + "io" + "log/slog" "os" "path/filepath" "testing" @@ -24,9 +26,6 @@ import ( "github.com/docker/docker/api/types/registry" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" - "go.uber.org/mock/gomock" - - "github.com/pulumi/pulumi/sdk/v3/go/common/diag" ) func TestAuth(t *testing.T) { @@ -79,21 +78,9 @@ func TestCustomHost(t *testing.T) { func TestBuild(t *testing.T) { t.Parallel() - // Workaround for https://github.com/pulumi/pulumi-go-provider/issues/159 - ctrl, ctx := gomock.WithContext(context.Background(), t) - pctx := NewMockProviderContext(ctrl) - pctx.EXPECT().Log(gomock.Any(), gomock.Any()).AnyTimes() - pctx.EXPECT().LogStatus(gomock.Any(), gomock.Any()).AnyTimes() - pctx.EXPECT().Done().Return(ctx.Done()).AnyTimes() - pctx.EXPECT(). - Value(gomock.Any()). - DoAndReturn(func(key any) any { return ctx.Value(key) }). - AnyTimes() - pctx.EXPECT().Err().Return(ctx.Err()).AnyTimes() - pctx.EXPECT().Deadline().Return(ctx.Deadline()).AnyTimes() tmpdir := t.TempDir() - max := Max + Max := Max exampleContext := &BuildContext{Context: Context{Location: "../../examples/app"}} @@ -135,7 +122,7 @@ func TestBuild(t *testing.T) { Tags: []string{"cached"}, CacheTo: []CacheTo{{Local: &CacheToLocal{ Dest: filepath.Join(tmpdir, "cache"), - CacheWithMode: CacheWithMode{Mode: &max}, + CacheWithMode: CacheWithMode{Mode: &Max}, }}}, CacheFrom: []CacheFrom{{Local: &CacheFromLocal{ Src: filepath.Join(tmpdir, "cache"), @@ -300,12 +287,13 @@ func TestBuild(t *testing.T) { if tt.skip { t.Skip() } + ctx := context.Background() cli := testcli(t, true, tt.auths...) - build, err := tt.args.toBuild(pctx, false) + build, err := tt.args.toBuild(ctx, false) require.NoError(t, err) - _, err = cli.Build(pctx, build) + _, err = cli.Build(ctx, build) assert.NoError(t, err, cli.err.String()) }) } @@ -366,14 +354,22 @@ func TestNormalizeReference(t *testing.T) { } } +//nolint:paralleltest // Overrides default logger. func TestBuildError(t *testing.T) { - t.Parallel() - if os.Getenv("CI") != "" { t.Skip("flaky on CI for some reason") } - ctrl, ctx := gomock.WithContext(context.Background(), t) + l := slog.Default() + defer slog.SetDefault(l) + + // Override go-provider's default logger to capture and tee to stdout. + logger := &bytes.Buffer{} + slog.SetDefault( + slog.New( + slog.NewTextHandler(io.MultiWriter(logger, os.Stdout), nil), + ), + ) exampleContext := &BuildContext{Context: Context{Location: "../../examples/app"}} @@ -383,28 +379,14 @@ func TestBuildError(t *testing.T) { Inline: "FROM alpine\nRUN echo hello\nRUN badcmd", }, } - logged := bytes.Buffer{} - - pctx := NewMockProviderContext(ctrl) - pctx.EXPECT().Done().Return(ctx.Done()).AnyTimes() - pctx.EXPECT(). - Value(gomock.Any()). - DoAndReturn(func(key any) any { return ctx.Value(key) }). - AnyTimes() - pctx.EXPECT().Err().Return(ctx.Err()).AnyTimes() - pctx.EXPECT().Deadline().Return(ctx.Deadline()).AnyTimes() - - pctx.EXPECT().LogStatus(gomock.Any(), gomock.Any()).AnyTimes() - pctx.EXPECT().Log(gomock.Any(), gomock.Any()).DoAndReturn(func(_ diag.Severity, msg string) { - logged.WriteString(msg) - }).AnyTimes() + ctx := context.Background() cli := testcli(t, true) - build, err := args.toBuild(pctx, false) + build, err := args.toBuild(ctx, false) require.NoError(t, err) - _, err = cli.Build(pctx, build) + _, err = cli.Build(ctx, build) assert.Error(t, err) want := []string{ @@ -413,7 +395,7 @@ func TestBuildError(t *testing.T) { } for _, want := range want { - assert.Contains(t, logged.String(), want) + assert.Contains(t, logger.String(), want) } assert.ErrorContains(t, err, `process "/bin/sh -c badcmd" did not complete successfully: exit code: 127`, @@ -422,7 +404,6 @@ func TestBuildError(t *testing.T) { func TestBuildExecError(t *testing.T) { t.Parallel() - ctrl, _ := gomock.WithContext(context.Background(), t) exampleContext := &BuildContext{Context: Context{Location: "../../examples/app"}} @@ -434,20 +415,13 @@ func TestBuildExecError(t *testing.T) { Exec: true, } - pctx := NewMockProviderContext(ctrl) - pctx.EXPECT().Log( - diag.Warning, - "No exports were specified so the build will only remain in the local build cache. "+ - "Use `push` to upload the image to a registry, or silence this warning with a `cacheonly` export.", - ) - pctx.EXPECT().LogStatus(gomock.Any(), gomock.Any()).AnyTimes() - + ctx := context.Background() cli := testcli(t, true) - build, err := args.toBuild(pctx, false) + build, err := args.toBuild(ctx, false) require.NoError(t, err) - _, err = cli.Build(pctx, build) + _, err = cli.Build(ctx, build) assert.Error(t, err) want := []string{ diff --git a/provider/internal/deprecated/configencoding.go b/provider/internal/deprecated/configencoding.go index a10d48e..e54d0e6 100644 --- a/provider/internal/deprecated/configencoding.go +++ b/provider/internal/deprecated/configencoding.go @@ -17,9 +17,6 @@ package deprecated import ( "encoding/json" "fmt" - "sort" - - "google.golang.org/protobuf/types/known/structpb" "github.com/pulumi/pulumi/pkg/v3/codegen/schema" "github.com/pulumi/pulumi/sdk/v3/go/common/resource" @@ -113,6 +110,7 @@ func (enc *ConfigEncoding) unmarshalOpts() plugin.MarshalOptions { return plugin.MarshalOptions{ Label: "config", KeepUnknowns: true, + KeepSecrets: true, SkipNulls: true, RejectAssets: true, } @@ -120,15 +118,10 @@ func (enc *ConfigEncoding) unmarshalOpts() plugin.MarshalOptions { // Like plugin.UnmarshalPropertyValue but overrides string parsing with convertStringToPropertyValue. func (enc *ConfigEncoding) unmarshalPropertyValue(key resource.PropertyKey, - v *structpb.Value, -) (*resource.PropertyValue, error) { + pv resource.PropertyValue, +) (resource.PropertyValue, error) { opts := enc.unmarshalOpts() - pv, err := plugin.UnmarshalPropertyValue(key, v, enc.unmarshalOpts()) - if err != nil { - return nil, fmt.Errorf("error unmarshalling property %q: %w", key, err) - } - prop, ok := enc.schema.Variables[string(key)] // Only apply JSON-encoded recognition for known fields. @@ -136,8 +129,10 @@ func (enc *ConfigEncoding) unmarshalPropertyValue(key resource.PropertyKey, return pv, nil } - var jsonString string - var jsonStringDetected, jsonStringSecret bool + var ( + jsonString string + jsonStringDetected, jsonStringSecret bool + ) if pv.IsString() { jsonString = pv.StringValue() @@ -153,22 +148,21 @@ func (enc *ConfigEncoding) unmarshalPropertyValue(key resource.PropertyKey, if jsonStringDetected { v, err := enc.convertStringToPropertyValue(jsonString, prop) if err != nil { - return nil, fmt.Errorf("error unmarshalling property %q: %w", key, err) + return resource.PropertyValue{}, fmt.Errorf("error unmarshalling property %q: %w", key, err) } if jsonStringSecret { - s := resource.MakeSecret(v) - return &s, nil + return resource.MakeSecret(v), nil } - return &v, nil + return v, nil } - // Computed sentinels are coming in as always having an empty string, but the encoding coerses them to a zero + // Computed sentinels are coming in as always having an empty string, but the encoding coerces them to a zero // value of the appropriate type. if pv.IsComputed() { el := pv.V.(resource.Computed).Element if el.IsString() && el.StringValue() == "" { res := resource.MakeComputed(enc.zeroValue(prop.Type)) - return &res, nil + return res, nil } } @@ -177,36 +171,20 @@ func (enc *ConfigEncoding) unmarshalPropertyValue(key resource.PropertyKey, // UnmarshalProperties is copied from plugin.UnmarshalProperties substituting plugin.UnmarshalPropertyValue. func (enc *ConfigEncoding) UnmarshalProperties( - props *structpb.Struct, + props resource.PropertyMap, ) (resource.PropertyMap, error) { - opts := enc.unmarshalOpts() - result := make(resource.PropertyMap) // First sort the keys so we enumerate them in order (in case errors happen, we want determinism). - var keys []string - if props != nil { - for k := range props.Fields { - keys = append(keys, k) - } - sort.Strings(keys) - } + keys := props.StableKeys() // And now unmarshal every field it into the map. for _, key := range keys { - pk := resource.PropertyKey(key) - v, err := enc.unmarshalPropertyValue(pk, props.Fields[key]) + v, err := enc.unmarshalPropertyValue(key, props[key]) if err != nil { - return nil, err - } else if v != nil { - if opts.SkipNulls && v.IsNull() { - continue - } - if opts.SkipInternalKeys && resource.IsInternalPropertyKey(pk) { - continue - } - result[pk] = *v + return resource.PropertyMap{}, err } + result[key] = v } return result, nil diff --git a/provider/internal/deprecated/configencoding_test.go b/provider/internal/deprecated/configencoding_test.go index 1d2a8e2..b085414 100644 --- a/provider/internal/deprecated/configencoding_test.go +++ b/provider/internal/deprecated/configencoding_test.go @@ -16,23 +16,23 @@ package deprecated import ( "fmt" + "strconv" "testing" "github.com/stretchr/testify/assert" - structpb "google.golang.org/protobuf/types/known/structpb" + "github.com/stretchr/testify/require" "github.com/pulumi/pulumi/pkg/v3/codegen/schema" "github.com/pulumi/pulumi/sdk/v3/go/common/resource" - "github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin" ) func TestConfigEncoding(t *testing.T) { t.Parallel() type testCase struct { - ty schema.TypeSpec - v *structpb.Value - pv resource.PropertyValue + ty schema.TypeSpec + given resource.PropertyValue + want resource.PropertyValue } knownKey := "mykey" @@ -49,69 +49,64 @@ func TestConfigEncoding(t *testing.T) { ) } - makeValue := func(x any) *structpb.Value { - vv, err := structpb.NewValue(x) - assert.NoErrorf(t, err, "structpb.NewValue failed") - return vv - } - checkUnmarshal := func(t *testing.T, tc testCase) { enc := makeEnc(tc.ty) - pv, err := enc.unmarshalPropertyValue(resource.PropertyKey(knownKey), tc.v) - assert.NoError(t, err) - assert.NotNil(t, pv) - assert.Equal(t, tc.pv, *pv) + key := resource.PropertyKey(knownKey) + + actual, err := enc.unmarshalPropertyValue(key, tc.given) + require.NoError(t, err) + assert.Equal(t, tc.want, actual) } turnaroundTestCases := []testCase{ { schema.TypeSpec{Type: "boolean"}, - makeValue(`true`), + resource.NewPropertyValue(`true`), resource.NewBoolProperty(true), }, { schema.TypeSpec{Type: "boolean"}, - makeValue(`false`), + resource.NewPropertyValue(`false`), resource.NewBoolProperty(false), }, { schema.TypeSpec{Type: "integer"}, - makeValue(`0`), + resource.NewPropertyValue(`0`), resource.NewNumberProperty(0), }, { schema.TypeSpec{Type: "integer"}, - makeValue(`42`), + resource.NewPropertyValue(`42`), resource.NewNumberProperty(42), }, { schema.TypeSpec{Type: "number"}, - makeValue(`0`), + resource.NewPropertyValue(`0`), resource.NewNumberProperty(0.0), }, { schema.TypeSpec{Type: "number"}, - makeValue(`42.5`), + resource.NewPropertyValue(`42.5`), resource.NewNumberProperty(42.5), }, { schema.TypeSpec{Type: "string"}, - structpb.NewStringValue(""), + resource.NewStringProperty(""), resource.NewStringProperty(""), }, { schema.TypeSpec{Type: "string"}, - structpb.NewStringValue("hello"), + resource.NewStringProperty("hello"), resource.NewStringProperty("hello"), }, { schema.TypeSpec{Type: "array"}, - makeValue(`[]`), + resource.NewPropertyValue(`[]`), resource.NewArrayProperty([]resource.PropertyValue{}), }, { schema.TypeSpec{Type: "array"}, - makeValue(`["hello","there"]`), + resource.NewPropertyValue(`["hello","there"]`), resource.NewArrayProperty([]resource.PropertyValue{ resource.NewStringProperty("hello"), resource.NewStringProperty("there"), @@ -119,12 +114,12 @@ func TestConfigEncoding(t *testing.T) { }, { schema.TypeSpec{Type: "object"}, - makeValue(`{}`), + resource.NewPropertyValue(`{}`), resource.NewObjectProperty(resource.PropertyMap{}), }, { schema.TypeSpec{Type: "object"}, - makeValue(`{"key":"value"}`), + resource.NewPropertyValue(`{"key":"value"}`), resource.NewObjectProperty(resource.PropertyMap{ "key": resource.NewStringProperty("value"), }), @@ -135,7 +130,7 @@ func TestConfigEncoding(t *testing.T) { for i, tc := range turnaroundTestCases { tc := tc - t.Run(fmt.Sprintf("UnmarshalPropertyValue/%d", i), func(t *testing.T) { + t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() checkUnmarshal(t, tc) }) @@ -147,32 +142,32 @@ func TestConfigEncoding(t *testing.T) { cases := []testCase{ { schema.TypeSpec{Type: "boolean"}, - makeValue(""), + resource.NewPropertyValue(""), resource.NewBoolProperty(false), }, { schema.TypeSpec{Type: "number"}, - makeValue(""), + resource.NewPropertyValue(""), resource.NewNumberProperty(0.), }, { schema.TypeSpec{Type: "integer"}, - makeValue(""), + resource.NewPropertyValue(""), resource.NewNumberProperty(0), }, { schema.TypeSpec{Type: "string"}, - makeValue(""), + resource.NewPropertyValue(""), resource.NewStringProperty(""), }, { schema.TypeSpec{Type: "object"}, - makeValue(""), + resource.NewPropertyValue(""), resource.NewObjectProperty(make(resource.PropertyMap)), }, { schema.TypeSpec{Type: "array"}, - makeValue(""), + resource.NewPropertyValue(""), resource.NewArrayProperty([]resource.PropertyValue{}), }, } @@ -187,18 +182,18 @@ func TestConfigEncoding(t *testing.T) { }) t.Run("computed", func(t *testing.T) { - unk := makeValue(plugin.UnknownStringValue) + unk := resource.MakeComputed(resource.NewStringProperty("")) for i, tc := range turnaroundTestCases { tc := tc - t.Run(fmt.Sprintf("UnmarshalPropertyValue/%d", i), func(t *testing.T) { + t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() // Unknown sentinel unmarshals to a Computed with a type-appropriate zero value. checkUnmarshal(t, testCase{ - tc.ty, - unk, - resource.MakeComputed(makeEnc(tc.ty).zeroValue(tc.ty.Type)), + ty: tc.ty, + given: unk, + want: resource.MakeComputed(makeEnc(tc.ty).zeroValue(tc.ty.Type)), }) }) } @@ -215,46 +210,30 @@ func TestConfigEncoding(t *testing.T) { var secretCases []testCase - pbSecret := func(v *structpb.Value) *structpb.Value { - return structpb.NewStructValue(&structpb.Struct{Fields: map[string]*structpb.Value{ - "4dabf18193072939515e22adb298388d": makeValue("1b47061264138c4ac30d75fd1eb44270"), - "value": v, - }}) - } - for _, tc := range turnaroundTestCases { secretCases = append(secretCases, testCase{ - tc.ty, - pbSecret(tc.v), - resource.MakeSecret(tc.pv), + ty: tc.ty, + given: resource.MakeSecret(tc.given), + want: resource.MakeSecret(tc.want), }) } for i, tc := range secretCases { tc := tc - t.Run(fmt.Sprintf("secret/UnmarshalPropertyValue/%d", i), func(t *testing.T) { + t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() - - // Unmarshallin will remove secrts, so the expected value needs to be modified. - tc.pv = tc.pv.SecretValue().Element checkUnmarshal(t, tc) }) } - t.Run("tolerate secrets in Configure", func(t *testing.T) { - // This is a bit of a histirocal quirk: the engine may send secrets to Configure before - // receiving the response from Configure indicating that the provider does not want to receive - // secrets. These are simply ignored. The engine does not currently send secrets to CheckConfig. - // The engine does take care of making sure the secrets are stored as such in the statefile. - // - // Check here that unmarshalilng such values removes the secrets. + t.Run("nested secrets", func(t *testing.T) { checkUnmarshal(t, testCase{ schema.TypeSpec{Type: "object"}, - pbSecret(makeValue(`{"key":"val"}`)), - resource.NewObjectProperty(resource.PropertyMap{ + resource.MakeSecret(resource.NewPropertyValue(`{"key":"val"}`)), + resource.MakeSecret(resource.NewObjectProperty(resource.PropertyMap{ "key": resource.NewStringProperty("val"), - }), + })), }) }) }) @@ -262,7 +241,7 @@ func TestConfigEncoding(t *testing.T) { regressUnmarshalTestCases := []testCase{ { schema.TypeSpec{Type: "array"}, - makeValue(` + resource.NewPropertyValue(` [ { "address": "somewhere.org", @@ -276,7 +255,7 @@ func TestConfigEncoding(t *testing.T) { resource.NewArrayProperty([]resource.PropertyValue{ resource.NewObjectProperty(resource.PropertyMap{ "address": resource.NewStringProperty("somewhere.org"), - "password": resource.NewStringProperty("some-password"), + "password": resource.MakeSecret(resource.NewStringProperty("some-password")), "username": resource.NewStringProperty("some-user"), }), }), @@ -286,7 +265,7 @@ func TestConfigEncoding(t *testing.T) { t.Run("regress-unmarshal", func(t *testing.T) { for i, tc := range regressUnmarshalTestCases { tc := tc - t.Run(fmt.Sprintf("UnmarshalPropertyValue/%d", i), func(t *testing.T) { + t.Run(strconv.Itoa(i), func(t *testing.T) { t.Parallel() checkUnmarshal(t, tc) }) diff --git a/provider/internal/image.go b/provider/internal/image.go index 5b674d6..0002ec3 100644 --- a/provider/internal/image.go +++ b/provider/internal/image.go @@ -38,7 +38,6 @@ import ( provider "github.com/pulumi/pulumi-go-provider" "github.com/pulumi/pulumi-go-provider/infer" - "github.com/pulumi/pulumi/sdk/v3/go/common/diag" "github.com/pulumi/pulumi/sdk/v3/go/common/resource" "github.com/pulumi/pulumi/sdk/v3/go/pulumi" ) @@ -329,12 +328,10 @@ func (is *ImageState) Annotate(a infer.Annotator) { `)) } -// client produces a CLI client with scoped to this resource and layered on top -// of any host-level credentials. -func (i *Image) client(pctx provider.Context, state ImageState, args ImageArgs) (Client, error) { - ctx := context.Context(pctx) - - cfg := infer.GetConfig[Config](pctx) +// client produces a CLI client scoped to this resource and layered on top of +// any host-level credentials. +func (i *Image) client(ctx context.Context, state ImageState, args ImageArgs) (Client, error) { + cfg := infer.GetConfig[Config](ctx) if cli, ok := ctx.Value(_mockClientKey).(Client); ok { return cli, nil @@ -353,7 +350,7 @@ func (i *Image) client(pctx provider.Context, state ImageState, args ImageArgs) // Check validates ImageArgs, sets defaults, and ensures our client is // authenticated. func (i *Image) Check( - _ provider.Context, + _ context.Context, _ string, _ resource.PropertyMap, news resource.PropertyMap, @@ -491,7 +488,7 @@ func (b build) ShouldExec() bool { } func (ia ImageArgs) toBuild( - ctx provider.Context, + ctx context.Context, preview bool, ) (Build, error) { opts, err := ia.validate(preview) @@ -500,18 +497,15 @@ func (ia ImageArgs) toBuild( } if len(ia.Exports) == 0 && !ia.Push && !ia.Load { - ctx.Log(diag.Warning, - "No exports were specified so the build will only remain in the local build cache. "+ - "Use `push` to upload the image to a registry, or silence this warning with a `cacheonly` export.", - ) + provider.GetLogger(ctx).Warning( + "No exports were specified so the build will only remain in the local build cache. " + + "Use `push` to upload the image to a registry, or silence this warning with a `cacheonly` export.") } if len(opts.Platforms) > 1 && len(opts.CacheTo) > 0 { - ctx.Log( - diag.Warning, - "Caching doesn't work reliably with multi-platform builds (https://github.com/docker/buildx/discussions/1382). "+ - "Instead, perform one cached build per platform and create an Index to join them all together.", - ) + provider.GetLogger(ctx).Warning( + "Caching doesn't work reliably with multi-platform builds (https://github.com/docker/buildx/discussions/1382). " + + "Instead, perform one cached build per platform and create an Index to join them all together.") } return build{ @@ -667,7 +661,7 @@ func (ia *ImageArgs) validate(preview bool) (controllerapi.BuildOptions, error) // Create builds an image using buildkit. func (i *Image) Create( - ctx provider.Context, + ctx context.Context, name string, input ImageArgs, preview bool, @@ -716,7 +710,7 @@ func (i *Image) Create( return id, state, nil } if preview && !input.buildable() { - ctx.Log(diag.Warning, "Skipping preview build because some inputs are unknown.") + provider.GetLogger(ctx).Warning("Skipping preview build because some inputs are unknown.") return id, state, nil } @@ -754,7 +748,7 @@ func (i *Image) Create( // images built locally there is nothing to delete. We treat those cases as // updates and simply re-build the image without deleting anything. func (i *Image) Update( - ctx provider.Context, + ctx context.Context, name string, _ ImageState, input ImageArgs, @@ -767,7 +761,7 @@ func (i *Image) Update( // Read attempts to read manifests from an image's exports. An image without // exports will have no manifests. func (i *Image) Read( - ctx provider.Context, + ctx context.Context, name string, input ImageArgs, state ImageState, @@ -801,7 +795,7 @@ func (i *Image) Read( // Does a tag with this digest exist? descriptors, err := cli.Inspect(ctx, ref) if err != nil { - ctx.Log(diag.Warning, err.Error()) + provider.GetLogger(ctx).Warning(err.Error()) continue } @@ -830,7 +824,7 @@ func (i *Image) Read( // Delete deletes an Image. If the Image was already deleted out-of-band it is // treated as a success. func (i *Image) Delete( - ctx provider.Context, + ctx context.Context, _ string, state ImageState, ) error { @@ -861,9 +855,9 @@ func (i *Image) Delete( var multierr error for _, digested := range digests { - err = cli.Delete(context.Context(ctx), digested) + err = cli.Delete(ctx, digested) if errdefs.IsNotFound(err) { - ctx.Log(diag.Warning, digested+" not found") + provider.GetLogger(ctx).Warning(digested + " not found") continue // Nothing to do. } multierr = errors.Join(multierr, err) @@ -875,7 +869,7 @@ func (i *Image) Delete( // Diff re-implements most of the default diff behavior, with the exception of // ignoring "password" changes on registry inputs. func (*Image) Diff( - _ provider.Context, + _ context.Context, _ string, olds ImageState, news ImageArgs, diff --git a/provider/internal/image_test.go b/provider/internal/image_test.go index 606853a..e3fd21b 100644 --- a/provider/internal/image_test.go +++ b/provider/internal/image_test.go @@ -15,6 +15,7 @@ package internal import ( + "context" "errors" "fmt" "os" @@ -64,7 +65,7 @@ func TestImageLifecycle(t *testing.T) { c := NewMockClient(ctrl) c.EXPECT().BuildKitEnabled().Return(true, nil).AnyTimes() c.EXPECT().Build(gomock.Any(), gomock.AssignableToTypeOf(build{})).DoAndReturn( - func(_ provider.Context, b Build) (*client.SolveResponse, error) { + func(_ context.Context, b Build) (*client.SolveResponse, error) { assert.Equal(t, "testdata/noop/Dockerfile", b.BuildOptions().DockerfileName) return &client.SolveResponse{ ExporterResponse: map[string]string{ @@ -238,7 +239,7 @@ func TestImageLifecycle(t *testing.T) { c := NewMockClient(ctrl) c.EXPECT().BuildKitEnabled().Return(true, nil).AnyTimes() c.EXPECT().Build(gomock.Any(), gomock.AssignableToTypeOf(build{})).DoAndReturn( - func(_ provider.Context, b Build) (*client.SolveResponse, error) { + func(_ context.Context, b Build) (*client.SolveResponse, error) { assert.Equal(t, "testdata/noop/Dockerfile", b.BuildOptions().DockerfileName) return &client.SolveResponse{ ExporterResponse: map[string]string{"image.name": "test:latest"}, @@ -960,17 +961,14 @@ func TestBuildable(t *testing.T) { func TestToBuild(t *testing.T) { t.Parallel() - ctrl := gomock.NewController(t) - pctx := NewMockProviderContext(ctrl) - pctx.EXPECT().Log(gomock.Any(), gomock.Any()).AnyTimes() - max := Max + Max := Max ia := ImageArgs{ Tags: []string{"foo", "bar"}, Platforms: []Platform{"linux/amd64"}, Context: &BuildContext{Context: Context{Location: "testdata/noop"}}, CacheTo: []CacheTo{ - {GHA: &CacheToGitHubActions{CacheWithMode: CacheWithMode{&max}}}, + {GHA: &CacheToGitHubActions{CacheWithMode: CacheWithMode{&Max}}}, { Registry: &CacheToRegistry{ CacheFromRegistry: CacheFromRegistry{Ref: "docker.io/foo/bar"}, @@ -989,6 +987,6 @@ func TestToBuild(t *testing.T) { }, } - _, err := ia.toBuild(pctx, false) + _, err := ia.toBuild(context.Background(), false) assert.NoError(t, err) } diff --git a/provider/internal/index.go b/provider/internal/index.go index d424210..b0deb1a 100644 --- a/provider/internal/index.go +++ b/provider/internal/index.go @@ -15,6 +15,7 @@ package internal import ( + "context" "fmt" "reflect" "strings" @@ -24,7 +25,6 @@ import ( provider "github.com/pulumi/pulumi-go-provider" "github.com/pulumi/pulumi-go-provider/infer" - "github.com/pulumi/pulumi/sdk/v3/go/common/diag" "github.com/pulumi/pulumi/sdk/v3/go/common/resource" ) @@ -121,7 +121,7 @@ func (i *IndexState) Annotate(a infer.Annotator) { // Create is a passthrough to Update. func (i *Index) Create( - ctx provider.Context, + ctx context.Context, name string, input IndexArgs, preview bool, @@ -133,7 +133,7 @@ func (i *Index) Create( // Update performs `buildx imagetools create` to create a new OCI index / // manifest list. func (i *Index) Update( - ctx provider.Context, + ctx context.Context, name string, state IndexState, input IndexArgs, @@ -151,7 +151,7 @@ func (i *Index) Update( return state, nil } - ctx.Log(diag.Debug, fmt.Sprintf("creating index with tag %s and sources %s", input.Tag, input.Sources)) + provider.GetLogger(ctx).Debugf("creating index with tag %s and sources %s", input.Tag, input.Sources) err = cli.ManifestCreate(ctx, input.Push, input.Tag, input.Sources...) if err != nil { @@ -166,7 +166,7 @@ func (i *Index) Update( } func (i *Index) Read( - ctx provider.Context, + ctx context.Context, name string, input IndexArgs, state IndexState, @@ -175,7 +175,7 @@ func (i *Index) Read( state.Ref = input.Tag if !input.Push { - ctx.Log(diag.Debug, "skipping read because index was not pushed") + provider.GetLogger(ctx).Debug("skipping read because index was not pushed") return name, input, state, nil // Nothing to read. } @@ -184,7 +184,7 @@ func (i *Index) Read( return name, input, state, err } - ctx.Log(diag.Debug, "reading index with tag "+input.Tag) + provider.GetLogger(ctx).Debug("reading index with tag " + input.Tag) digest, err := cli.ManifestInspect(ctx, input.Tag) if err != nil && strings.Contains(err.Error(), "No such manifest:") && input.Push { @@ -211,7 +211,7 @@ func (i *Index) Read( // exist on the same registry. This is sufficient to handle the most common // cases for now. func (i *Index) Check( - _ provider.Context, + _ context.Context, _ string, _ resource.PropertyMap, news resource.PropertyMap, @@ -247,7 +247,7 @@ func (i *Index) Check( } // Delete attempts to delete the remote manifest. -func (i *Index) Delete(ctx provider.Context, _ string, state IndexState) error { +func (i *Index) Delete(ctx context.Context, _ string, state IndexState) error { if !state.Push { return nil // Nothing to delete. } @@ -271,7 +271,7 @@ func (i *Index) Delete(ctx provider.Context, _ string, state IndexState) error { // force `ignoreChanges`-style behavior on our registry password (which can // change all the time due to short-lived AWS credentials). func (i *Index) Diff( - _ provider.Context, + _ context.Context, _ string, olds IndexState, news IndexArgs, @@ -309,10 +309,10 @@ func (i *Index) Diff( }, nil } -// client produces a CLI client with scoped to this resource and layered on top -// of any host-level credentials. +// client produces a CLI client scoped to this resource and layered on top of +// any host-level credentials. func (i *Index) client( - ctx provider.Context, + ctx context.Context, _ IndexState, args IndexArgs, ) (Client, error) { diff --git a/provider/internal/metadata.json b/provider/internal/metadata.json deleted file mode 100644 index 9e26dfe..0000000 --- a/provider/internal/metadata.json +++ /dev/null @@ -1 +0,0 @@ -{} \ No newline at end of file diff --git a/provider/internal/mockclient_test.go b/provider/internal/mockclient_test.go index da357ff..60cb822 100644 --- a/provider/internal/mockclient_test.go +++ b/provider/internal/mockclient_test.go @@ -15,7 +15,6 @@ import ( pb "github.com/docker/buildx/controller/pb" client "github.com/moby/buildkit/client" session "github.com/moby/buildkit/session" - provider "github.com/pulumi/pulumi-go-provider" descriptor "github.com/regclient/regclient/types/descriptor" gomock "go.uber.org/mock/gomock" ) @@ -44,7 +43,7 @@ func (m *MockClient) EXPECT() *MockClientMockRecorder { } // Build mocks base method. -func (m *MockClient) Build(ctx provider.Context, b Build) (*client.SolveResponse, error) { +func (m *MockClient) Build(ctx context.Context, b Build) (*client.SolveResponse, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "Build", ctx, b) ret0, _ := ret[0].(*client.SolveResponse) @@ -71,13 +70,13 @@ func (c *ClientBuildCall) Return(arg0 *client.SolveResponse, arg1 error) *Client } // Do rewrite *gomock.Call.Do -func (c *ClientBuildCall) Do(f func(provider.Context, Build) (*client.SolveResponse, error)) *ClientBuildCall { +func (c *ClientBuildCall) Do(f func(context.Context, Build) (*client.SolveResponse, error)) *ClientBuildCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *ClientBuildCall) DoAndReturn(f func(provider.Context, Build) (*client.SolveResponse, error)) *ClientBuildCall { +func (c *ClientBuildCall) DoAndReturn(f func(context.Context, Build) (*client.SolveResponse, error)) *ClientBuildCall { c.Call = c.Call.DoAndReturn(f) return c } @@ -199,7 +198,7 @@ func (c *ClientInspectCall) DoAndReturn(f func(context.Context, string) ([]descr } // ManifestCreate mocks base method. -func (m *MockClient) ManifestCreate(ctx provider.Context, push bool, target string, refs ...string) error { +func (m *MockClient) ManifestCreate(ctx context.Context, push bool, target string, refs ...string) error { m.ctrl.T.Helper() varargs := []any{ctx, push, target} for _, a := range refs { @@ -230,19 +229,19 @@ func (c *ClientManifestCreateCall) Return(arg0 error) *ClientManifestCreateCall } // Do rewrite *gomock.Call.Do -func (c *ClientManifestCreateCall) Do(f func(provider.Context, bool, string, ...string) error) *ClientManifestCreateCall { +func (c *ClientManifestCreateCall) Do(f func(context.Context, bool, string, ...string) error) *ClientManifestCreateCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *ClientManifestCreateCall) DoAndReturn(f func(provider.Context, bool, string, ...string) error) *ClientManifestCreateCall { +func (c *ClientManifestCreateCall) DoAndReturn(f func(context.Context, bool, string, ...string) error) *ClientManifestCreateCall { c.Call = c.Call.DoAndReturn(f) return c } // ManifestDelete mocks base method. -func (m *MockClient) ManifestDelete(ctx provider.Context, target string) error { +func (m *MockClient) ManifestDelete(ctx context.Context, target string) error { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ManifestDelete", ctx, target) ret0, _ := ret[0].(error) @@ -268,19 +267,19 @@ func (c *ClientManifestDeleteCall) Return(arg0 error) *ClientManifestDeleteCall } // Do rewrite *gomock.Call.Do -func (c *ClientManifestDeleteCall) Do(f func(provider.Context, string) error) *ClientManifestDeleteCall { +func (c *ClientManifestDeleteCall) Do(f func(context.Context, string) error) *ClientManifestDeleteCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *ClientManifestDeleteCall) DoAndReturn(f func(provider.Context, string) error) *ClientManifestDeleteCall { +func (c *ClientManifestDeleteCall) DoAndReturn(f func(context.Context, string) error) *ClientManifestDeleteCall { c.Call = c.Call.DoAndReturn(f) return c } // ManifestInspect mocks base method. -func (m *MockClient) ManifestInspect(ctx provider.Context, target string) (string, error) { +func (m *MockClient) ManifestInspect(ctx context.Context, target string) (string, error) { m.ctrl.T.Helper() ret := m.ctrl.Call(m, "ManifestInspect", ctx, target) ret0, _ := ret[0].(string) @@ -307,13 +306,13 @@ func (c *ClientManifestInspectCall) Return(arg0 string, arg1 error) *ClientManif } // Do rewrite *gomock.Call.Do -func (c *ClientManifestInspectCall) Do(f func(provider.Context, string) (string, error)) *ClientManifestInspectCall { +func (c *ClientManifestInspectCall) Do(f func(context.Context, string) (string, error)) *ClientManifestInspectCall { c.Call = c.Call.Do(f) return c } // DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *ClientManifestInspectCall) DoAndReturn(f func(provider.Context, string) (string, error)) *ClientManifestInspectCall { +func (c *ClientManifestInspectCall) DoAndReturn(f func(context.Context, string) (string, error)) *ClientManifestInspectCall { c.Call = c.Call.DoAndReturn(f) return c } diff --git a/provider/internal/mockprovidercontext_test.go b/provider/internal/mockprovidercontext_test.go deleted file mode 100644 index 44b9983..0000000 --- a/provider/internal/mockprovidercontext_test.go +++ /dev/null @@ -1,386 +0,0 @@ -// Code generated by MockGen. DO NOT EDIT. -// Source: providercontext.go -// -// Generated by this command: -// -// mockgen -typed -package internal -source providercontext.go -destination mockprovidercontext_test.go --self_package github.com/pulumi/pulumi-docker/provider/v4/internal -// -// Package internal is a generated GoMock package. -package internal - -import ( - reflect "reflect" - time "time" - - provider "github.com/pulumi/pulumi-go-provider" - diag "github.com/pulumi/pulumi/sdk/v3/go/common/diag" - gomock "go.uber.org/mock/gomock" -) - -// MockProviderContext is a mock of ProviderContext interface. -type MockProviderContext struct { - ctrl *gomock.Controller - recorder *MockProviderContextMockRecorder -} - -// MockProviderContextMockRecorder is the mock recorder for MockProviderContext. -type MockProviderContextMockRecorder struct { - mock *MockProviderContext -} - -// NewMockProviderContext creates a new mock instance. -func NewMockProviderContext(ctrl *gomock.Controller) *MockProviderContext { - mock := &MockProviderContext{ctrl: ctrl} - mock.recorder = &MockProviderContextMockRecorder{mock} - return mock -} - -// EXPECT returns an object that allows the caller to indicate expected use. -func (m *MockProviderContext) EXPECT() *MockProviderContextMockRecorder { - return m.recorder -} - -// Deadline mocks base method. -func (m *MockProviderContext) Deadline() (time.Time, bool) { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Deadline") - ret0, _ := ret[0].(time.Time) - ret1, _ := ret[1].(bool) - return ret0, ret1 -} - -// Deadline indicates an expected call of Deadline. -func (mr *MockProviderContextMockRecorder) Deadline() *ProviderContextDeadlineCall { - mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Deadline", reflect.TypeOf((*MockProviderContext)(nil).Deadline)) - return &ProviderContextDeadlineCall{Call: call} -} - -// ProviderContextDeadlineCall wrap *gomock.Call -type ProviderContextDeadlineCall struct { - *gomock.Call -} - -// Return rewrite *gomock.Call.Return -func (c *ProviderContextDeadlineCall) Return(deadline time.Time, ok bool) *ProviderContextDeadlineCall { - c.Call = c.Call.Return(deadline, ok) - return c -} - -// Do rewrite *gomock.Call.Do -func (c *ProviderContextDeadlineCall) Do(f func() (time.Time, bool)) *ProviderContextDeadlineCall { - c.Call = c.Call.Do(f) - return c -} - -// DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *ProviderContextDeadlineCall) DoAndReturn(f func() (time.Time, bool)) *ProviderContextDeadlineCall { - c.Call = c.Call.DoAndReturn(f) - return c -} - -// Done mocks base method. -func (m *MockProviderContext) Done() <-chan struct{} { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Done") - ret0, _ := ret[0].(<-chan struct{}) - return ret0 -} - -// Done indicates an expected call of Done. -func (mr *MockProviderContextMockRecorder) Done() *ProviderContextDoneCall { - mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Done", reflect.TypeOf((*MockProviderContext)(nil).Done)) - return &ProviderContextDoneCall{Call: call} -} - -// ProviderContextDoneCall wrap *gomock.Call -type ProviderContextDoneCall struct { - *gomock.Call -} - -// Return rewrite *gomock.Call.Return -func (c *ProviderContextDoneCall) Return(arg0 <-chan struct{}) *ProviderContextDoneCall { - c.Call = c.Call.Return(arg0) - return c -} - -// Do rewrite *gomock.Call.Do -func (c *ProviderContextDoneCall) Do(f func() <-chan struct{}) *ProviderContextDoneCall { - c.Call = c.Call.Do(f) - return c -} - -// DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *ProviderContextDoneCall) DoAndReturn(f func() <-chan struct{}) *ProviderContextDoneCall { - c.Call = c.Call.DoAndReturn(f) - return c -} - -// Err mocks base method. -func (m *MockProviderContext) Err() error { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Err") - ret0, _ := ret[0].(error) - return ret0 -} - -// Err indicates an expected call of Err. -func (mr *MockProviderContextMockRecorder) Err() *ProviderContextErrCall { - mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Err", reflect.TypeOf((*MockProviderContext)(nil).Err)) - return &ProviderContextErrCall{Call: call} -} - -// ProviderContextErrCall wrap *gomock.Call -type ProviderContextErrCall struct { - *gomock.Call -} - -// Return rewrite *gomock.Call.Return -func (c *ProviderContextErrCall) Return(arg0 error) *ProviderContextErrCall { - c.Call = c.Call.Return(arg0) - return c -} - -// Do rewrite *gomock.Call.Do -func (c *ProviderContextErrCall) Do(f func() error) *ProviderContextErrCall { - c.Call = c.Call.Do(f) - return c -} - -// DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *ProviderContextErrCall) DoAndReturn(f func() error) *ProviderContextErrCall { - c.Call = c.Call.DoAndReturn(f) - return c -} - -// Log mocks base method. -func (m *MockProviderContext) Log(severity diag.Severity, msg string) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "Log", severity, msg) -} - -// Log indicates an expected call of Log. -func (mr *MockProviderContextMockRecorder) Log(severity, msg any) *ProviderContextLogCall { - mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Log", reflect.TypeOf((*MockProviderContext)(nil).Log), severity, msg) - return &ProviderContextLogCall{Call: call} -} - -// ProviderContextLogCall wrap *gomock.Call -type ProviderContextLogCall struct { - *gomock.Call -} - -// Return rewrite *gomock.Call.Return -func (c *ProviderContextLogCall) Return() *ProviderContextLogCall { - c.Call = c.Call.Return() - return c -} - -// Do rewrite *gomock.Call.Do -func (c *ProviderContextLogCall) Do(f func(diag.Severity, string)) *ProviderContextLogCall { - c.Call = c.Call.Do(f) - return c -} - -// DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *ProviderContextLogCall) DoAndReturn(f func(diag.Severity, string)) *ProviderContextLogCall { - c.Call = c.Call.DoAndReturn(f) - return c -} - -// LogStatus mocks base method. -func (m *MockProviderContext) LogStatus(severity diag.Severity, msg string) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "LogStatus", severity, msg) -} - -// LogStatus indicates an expected call of LogStatus. -func (mr *MockProviderContextMockRecorder) LogStatus(severity, msg any) *ProviderContextLogStatusCall { - mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LogStatus", reflect.TypeOf((*MockProviderContext)(nil).LogStatus), severity, msg) - return &ProviderContextLogStatusCall{Call: call} -} - -// ProviderContextLogStatusCall wrap *gomock.Call -type ProviderContextLogStatusCall struct { - *gomock.Call -} - -// Return rewrite *gomock.Call.Return -func (c *ProviderContextLogStatusCall) Return() *ProviderContextLogStatusCall { - c.Call = c.Call.Return() - return c -} - -// Do rewrite *gomock.Call.Do -func (c *ProviderContextLogStatusCall) Do(f func(diag.Severity, string)) *ProviderContextLogStatusCall { - c.Call = c.Call.Do(f) - return c -} - -// DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *ProviderContextLogStatusCall) DoAndReturn(f func(diag.Severity, string)) *ProviderContextLogStatusCall { - c.Call = c.Call.DoAndReturn(f) - return c -} - -// LogStatusf mocks base method. -func (m *MockProviderContext) LogStatusf(severity diag.Severity, msg string, args ...any) { - m.ctrl.T.Helper() - varargs := []any{severity, msg} - for _, a := range args { - varargs = append(varargs, a) - } - m.ctrl.Call(m, "LogStatusf", varargs...) -} - -// LogStatusf indicates an expected call of LogStatusf. -func (mr *MockProviderContextMockRecorder) LogStatusf(severity, msg any, args ...any) *ProviderContextLogStatusfCall { - mr.mock.ctrl.T.Helper() - varargs := append([]any{severity, msg}, args...) - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "LogStatusf", reflect.TypeOf((*MockProviderContext)(nil).LogStatusf), varargs...) - return &ProviderContextLogStatusfCall{Call: call} -} - -// ProviderContextLogStatusfCall wrap *gomock.Call -type ProviderContextLogStatusfCall struct { - *gomock.Call -} - -// Return rewrite *gomock.Call.Return -func (c *ProviderContextLogStatusfCall) Return() *ProviderContextLogStatusfCall { - c.Call = c.Call.Return() - return c -} - -// Do rewrite *gomock.Call.Do -func (c *ProviderContextLogStatusfCall) Do(f func(diag.Severity, string, ...any)) *ProviderContextLogStatusfCall { - c.Call = c.Call.Do(f) - return c -} - -// DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *ProviderContextLogStatusfCall) DoAndReturn(f func(diag.Severity, string, ...any)) *ProviderContextLogStatusfCall { - c.Call = c.Call.DoAndReturn(f) - return c -} - -// Logf mocks base method. -func (m *MockProviderContext) Logf(severity diag.Severity, msg string, args ...any) { - m.ctrl.T.Helper() - varargs := []any{severity, msg} - for _, a := range args { - varargs = append(varargs, a) - } - m.ctrl.Call(m, "Logf", varargs...) -} - -// Logf indicates an expected call of Logf. -func (mr *MockProviderContextMockRecorder) Logf(severity, msg any, args ...any) *ProviderContextLogfCall { - mr.mock.ctrl.T.Helper() - varargs := append([]any{severity, msg}, args...) - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Logf", reflect.TypeOf((*MockProviderContext)(nil).Logf), varargs...) - return &ProviderContextLogfCall{Call: call} -} - -// ProviderContextLogfCall wrap *gomock.Call -type ProviderContextLogfCall struct { - *gomock.Call -} - -// Return rewrite *gomock.Call.Return -func (c *ProviderContextLogfCall) Return() *ProviderContextLogfCall { - c.Call = c.Call.Return() - return c -} - -// Do rewrite *gomock.Call.Do -func (c *ProviderContextLogfCall) Do(f func(diag.Severity, string, ...any)) *ProviderContextLogfCall { - c.Call = c.Call.Do(f) - return c -} - -// DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *ProviderContextLogfCall) DoAndReturn(f func(diag.Severity, string, ...any)) *ProviderContextLogfCall { - c.Call = c.Call.DoAndReturn(f) - return c -} - -// RuntimeInformation mocks base method. -func (m *MockProviderContext) RuntimeInformation() provider.RunInfo { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "RuntimeInformation") - ret0, _ := ret[0].(provider.RunInfo) - return ret0 -} - -// RuntimeInformation indicates an expected call of RuntimeInformation. -func (mr *MockProviderContextMockRecorder) RuntimeInformation() *ProviderContextRuntimeInformationCall { - mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "RuntimeInformation", reflect.TypeOf((*MockProviderContext)(nil).RuntimeInformation)) - return &ProviderContextRuntimeInformationCall{Call: call} -} - -// ProviderContextRuntimeInformationCall wrap *gomock.Call -type ProviderContextRuntimeInformationCall struct { - *gomock.Call -} - -// Return rewrite *gomock.Call.Return -func (c *ProviderContextRuntimeInformationCall) Return(arg0 provider.RunInfo) *ProviderContextRuntimeInformationCall { - c.Call = c.Call.Return(arg0) - return c -} - -// Do rewrite *gomock.Call.Do -func (c *ProviderContextRuntimeInformationCall) Do(f func() provider.RunInfo) *ProviderContextRuntimeInformationCall { - c.Call = c.Call.Do(f) - return c -} - -// DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *ProviderContextRuntimeInformationCall) DoAndReturn(f func() provider.RunInfo) *ProviderContextRuntimeInformationCall { - c.Call = c.Call.DoAndReturn(f) - return c -} - -// Value mocks base method. -func (m *MockProviderContext) Value(key any) any { - m.ctrl.T.Helper() - ret := m.ctrl.Call(m, "Value", key) - ret0, _ := ret[0].(any) - return ret0 -} - -// Value indicates an expected call of Value. -func (mr *MockProviderContextMockRecorder) Value(key any) *ProviderContextValueCall { - mr.mock.ctrl.T.Helper() - call := mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Value", reflect.TypeOf((*MockProviderContext)(nil).Value), key) - return &ProviderContextValueCall{Call: call} -} - -// ProviderContextValueCall wrap *gomock.Call -type ProviderContextValueCall struct { - *gomock.Call -} - -// Return rewrite *gomock.Call.Return -func (c *ProviderContextValueCall) Return(arg0 any) *ProviderContextValueCall { - c.Call = c.Call.Return(arg0) - return c -} - -// Do rewrite *gomock.Call.Do -func (c *ProviderContextValueCall) Do(f func(any) any) *ProviderContextValueCall { - c.Call = c.Call.Do(f) - return c -} - -// DoAndReturn rewrite *gomock.Call.DoAndReturn -func (c *ProviderContextValueCall) DoAndReturn(f func(any) any) *ProviderContextValueCall { - c.Call = c.Call.DoAndReturn(f) - return c -} diff --git a/provider/internal/provider.go b/provider/internal/provider.go index bc44fa0..ade34f7 100644 --- a/provider/internal/provider.go +++ b/provider/internal/provider.go @@ -55,7 +55,7 @@ func (c *Config) Annotate(a infer.Annotator) { } // Configure validates and processes user-provided configuration values. -func (c *Config) Configure(_ provider.Context) error { +func (c *Config) Configure(_ context.Context) error { h, err := newHost(c) if err != nil { return fmt.Errorf("getting host: %w", err) diff --git a/provider/internal/provider_test.go b/provider/internal/provider_test.go index 2cdb9e4..480897f 100644 --- a/provider/internal/provider_test.go +++ b/provider/internal/provider_test.go @@ -59,7 +59,10 @@ func TestAnnotate(t *testing.T) { func TestSchema(t *testing.T) { t.Parallel() - Schema(context.Background(), "v4") + s := newServer(nil) + + _, err := s.GetSchema(provider.GetSchemaRequest{Version: 0}) + assert.NoError(t, err) } type annotator struct{} @@ -73,10 +76,10 @@ func newServer(client Client) integration.Server { // Inject a mock client if provided. if client != nil { - p = mwcontext.Wrap(p, func(ctx provider.Context) provider.Context { - return provider.CtxWithValue(ctx, _mockClientKey, client) + p = mwcontext.Wrap(p, func(ctx context.Context) context.Context { + return context.WithValue(ctx, _mockClientKey, client) }) } - return integration.NewServer("docker", semver.Version{Major: 4}, p) + return integration.NewServer("docker-build", semver.Version{Major: 0}, p) } diff --git a/provider/internal/providercontext.go b/provider/internal/providercontext.go deleted file mode 100644 index 2aa5aaf..0000000 --- a/provider/internal/providercontext.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2024, Pulumi Corporation. -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:generate go run go.uber.org/mock/mockgen -typed -package internal -source providercontext.go -destination mockprovidercontext_test.go --self_package github.com/pulumi/pulumi-docker/provider/v4/internal - -package internal - -import ( - provider "github.com/pulumi/pulumi-go-provider" -) - -// ProviderContext is a workaround for -// https://github.com/pulumi/pulumi-go-provider/issues/159 -type ProviderContext interface { - provider.Context -} diff --git a/provider/provider.go b/provider/provider.go index 4820e79..5d157aa 100644 --- a/provider/provider.go +++ b/provider/provider.go @@ -16,13 +16,13 @@ package provider import ( "context" - "fmt" + "encoding/json" "github.com/pulumi/pulumi-docker-build/provider/internal" "github.com/pulumi/pulumi-docker-build/provider/internal/deprecated" gp "github.com/pulumi/pulumi-go-provider" + "github.com/pulumi/pulumi/pkg/v3/codegen/schema" "github.com/pulumi/pulumi/pkg/v3/resource/provider" - "github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin" rpc "github.com/pulumi/pulumi/sdk/v3/proto/go" ) @@ -39,11 +39,7 @@ func Serve() error { // New creates a new provider. func New(host *provider.HostClient) (rpc.ResourceProviderServer, error) { - server, err := gp.RawServer(Name, Version, internal.NewBuildxProvider())(host) - if err != nil { - return nil, fmt.Errorf("building raw server: %w", err) - } - return &configurableProvider{ResourceProviderServer: server}, nil + return gp.RawServer(Name, Version, configurableProvider(internal.NewBuildxProvider()))(host) } // configurableProvider is a workaround for @@ -54,26 +50,26 @@ func New(host *provider.HostClient) (rpc.ResourceProviderServer, error) { // // If you find yourself in a position where you need to copy this -- STOP! // https://github.com/pulumi/pulumi/pull/15032 should be merged with this fix. -type configurableProvider struct { - rpc.ResourceProviderServer -} +func configurableProvider(p gp.Provider) gp.Provider { + configure := p.Configure -func (p configurableProvider) Configure( - ctx context.Context, - request *rpc.ConfigureRequest, -) (*rpc.ConfigureResponse, error) { - schema := internal.Schema(ctx, Version) - ce := deprecated.New(schema.Config) - buildxReq := request - if props, err := ce.UnmarshalProperties(request.Args); err == nil { - args, _ := plugin.MarshalProperties(props, plugin.MarshalOptions{ - Label: "config", - KeepUnknowns: true, - SkipNulls: true, - KeepSecrets: true, - RejectAssets: true, - }) - buildxReq.Args = args + p.Configure = func(ctx context.Context, req gp.ConfigureRequest) error { + r, err := p.GetSchema(ctx, gp.GetSchemaRequest{Version: 0}) + if err != nil { + return err + } + spec := schema.PackageSpec{} + err = json.Unmarshal([]byte(r.Schema), &spec) + if err != nil { + return err + } + + ce := deprecated.New(spec.Config) + if props, err := ce.UnmarshalProperties(req.Args); err == nil { + req.Args = props + } + return configure(ctx, req) } - return p.ResourceProviderServer.Configure(ctx, buildxReq) + + return p } diff --git a/provider/provider_test.go b/provider/provider_test.go index 0e18dcb..81e0d06 100644 --- a/provider/provider_test.go +++ b/provider/provider_test.go @@ -24,7 +24,10 @@ import ( emptypb "google.golang.org/protobuf/types/known/emptypb" "google.golang.org/protobuf/types/known/structpb" - pulumirpc "github.com/pulumi/pulumi/sdk/v3/proto/go" + "github.com/pulumi/pulumi-docker-build/provider/internal" + provider "github.com/pulumi/pulumi-go-provider" + "github.com/pulumi/pulumi-go-provider/integration" + "github.com/pulumi/pulumi/sdk/v3/go/common/resource/plugin" ) // TestConfigure checks backwards-compatibility with SDKs that still send @@ -34,20 +37,19 @@ import ( func TestConfigure(t *testing.T) { t.Parallel() - ctx := context.Background() - - p, err := New(nil) - require.NoError(t, err) + p := configurableProvider(internal.NewBuildxProvider()) args, err := structpb.NewStruct(map[string]any{ "registries": `[{"address": "docker.io"}]`, }) require.NoError(t, err) + argsMap, err := plugin.UnmarshalProperties(args, plugin.MarshalOptions{}) + require.NoError(t, err) - _, err = p.Configure(ctx, &pulumirpc.ConfigureRequest{ - Args: args, + s := integration.NewServer("docker-build", semver.Version{Major: 0}, p) + err = s.Configure(provider.ConfigureRequest{ + Args: argsMap, }) - assert.NoError(t, err) } diff --git a/sdk/go/dockerbuild/go.mod b/sdk/go/dockerbuild/go.mod index c11c095..fbab573 100644 --- a/sdk/go/dockerbuild/go.mod +++ b/sdk/go/dockerbuild/go.mod @@ -82,7 +82,7 @@ require ( golang.org/x/crypto v0.21.0 // indirect golang.org/x/exp v0.0.0-20240112132812-db7319d0e0e3 // indirect golang.org/x/mod v0.16.0 // indirect - golang.org/x/net v0.22.0 // indirect + golang.org/x/net v0.23.0 // indirect golang.org/x/sync v0.6.0 // indirect golang.org/x/sys v0.18.0 // indirect golang.org/x/term v0.18.0 // indirect diff --git a/sdk/go/dockerbuild/go.sum b/sdk/go/dockerbuild/go.sum index 5655367..b054305 100644 --- a/sdk/go/dockerbuild/go.sum +++ b/sdk/go/dockerbuild/go.sum @@ -236,8 +236,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc= -golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=