Skip to content

Commit

Permalink
internal fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
blampe committed Jan 23, 2024
1 parent e513612 commit 36630df
Show file tree
Hide file tree
Showing 24 changed files with 799 additions and 55 deletions.
16 changes: 15 additions & 1 deletion provider/cmd/pulumi-resource-docker/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@
"architecture"
]
},
"docker:buildx/image:ProviderRegistryAuth": {
"docker:buildx/image:RegistryAuth": {
"properties": {
"address": {
"type": "string",
Expand Down Expand Up @@ -2159,6 +2159,13 @@
"type": "boolean",
"description": "\nAlways attempt to pull all referenced images"
},
"registries": {
"type": "array",
"items": {
"$ref": "#/types/docker:buildx/image:RegistryAuth"
},
"description": "\nLogins for registry outputs"
},
"tags": {
"type": "array",
"items": {
Expand Down Expand Up @@ -2220,6 +2227,13 @@
"type": "boolean",
"description": "\nAlways attempt to pull all referenced images"
},
"registries": {
"type": "array",
"items": {
"$ref": "#/types/docker:buildx/image:RegistryAuth"
},
"description": "\nLogins for registry outputs"
},
"tags": {
"type": "array",
"items": {
Expand Down
6 changes: 3 additions & 3 deletions provider/internal/buildx.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ import (
var (
_ infer.CustomConfigure = (*Config)(nil)
_ infer.Annotated = (infer.Annotated)((*Config)(nil))
_ infer.Annotated = (infer.Annotated)((*properties.ProviderRegistryAuth)(nil))
_ infer.Annotated = (infer.Annotated)((*properties.RegistryAuth)(nil))
)

// Config configures the buildx provider.
type Config struct {
Host string `pulumi:"host,optional"`
RegistryAuth []properties.ProviderRegistryAuth `pulumi:"registryAuth,optional"`
Host string `pulumi:"host,optional"`
RegistryAuth []properties.RegistryAuth `pulumi:"registryAuth,optional"`

client Client
}
Expand Down
24 changes: 16 additions & 8 deletions provider/internal/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,19 @@ import (

// Client handles all our Docker API calls.
type Client interface {
Auth(ctx context.Context, creds properties.ProviderRegistryAuth) error
Auth(ctx context.Context, creds properties.RegistryAuth) error
Build(ctx context.Context, opts controllerapi.BuildOptions) (*client.SolveResponse, error)
BuildKitEnabled() (bool, error)
Inspect(ctx context.Context, id string) ([]manifesttypes.ImageManifest, error)
Delete(ctx context.Context, id string) ([]types.ImageDeleteResponseItem, error)
}

var _ Client = (*docker)(nil)

type docker struct {
cli *command.DockerCli
}

var _ Client = (*docker)(nil)

func newDockerClient() (*docker, error) {
cli, err := command.NewDockerCli(
command.WithCombinedStreams(os.Stdout),
Expand All @@ -52,7 +52,7 @@ func newDockerClient() (*docker, error) {
return &docker{cli: cli}, err
}

func (d *docker) Auth(ctx context.Context, creds properties.ProviderRegistryAuth) error {
func (d *docker) Auth(_ context.Context, creds properties.RegistryAuth) error {
cfg := d.cli.ConfigFile()

// Special handling for legacy DockerHub domains. The OCI-compliant
Expand All @@ -69,7 +69,16 @@ func (d *docker) Auth(ctx context.Context, creds properties.ProviderRegistryAuth
Password: creds.Password,
}

err := cfg.GetCredentialsStore(creds.Address).Store(auth)
// Workaround for https://github.com/docker/docker-credential-helpers/issues/37.
all, err := cfg.GetAllCredentials()
if err != nil {
return fmt.Errorf("getting credentials: %w", err)
}
if _, ok := all[creds.Address]; ok {
return nil // Already logged in.
}

err = cfg.GetCredentialsStore(creds.Address).Store(auth)
if err != nil {
return fmt.Errorf("storing auth: %w", err)
}
Expand All @@ -79,14 +88,13 @@ func (d *docker) Auth(ctx context.Context, creds properties.ProviderRegistryAuth
// Build performs a buildkit build.
func (d *docker) Build(
ctx context.Context,
in controllerapi.BuildOptions,
opts controllerapi.BuildOptions,
) (*client.SolveResponse, error) {
printer, err := progress.NewPrinter(ctx, os.Stdout, progressui.PlainMode)
if err != nil {
return nil, fmt.Errorf("creating printer: %w", err)
}

solve, res, err := cbuild.RunBuild(ctx, d.cli, in, d.cli.In(), printer, true)
solve, res, err := cbuild.RunBuild(ctx, d.cli, opts, d.cli.In(), printer, true)
if res != nil {
res.Done()
}
Expand Down
9 changes: 7 additions & 2 deletions provider/internal/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,14 @@ func TestAuth(t *testing.T) {
user = u
}
password := os.Getenv("DOCKER_HUB_PASSWORD")
host := "pulumi.com" // Fake host -- we don't actually hit it.

err = d.Auth(context.Background(), properties.ProviderRegistryAuth{
Address: "docker.io",
t.Cleanup(func() {
_ = d.cli.ConfigFile().GetCredentialsStore(host).Erase(host)
})

err = d.Auth(context.Background(), properties.RegistryAuth{
Address: host,
Username: user,
Password: password,
})
Expand Down
40 changes: 30 additions & 10 deletions provider/internal/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,15 +46,16 @@ func (i *Image) Annotate(a infer.Annotator) {

// ImageArgs instantiates a new Image.
type ImageArgs struct {
BuildArgs map[string]string `pulumi:"buildArgs,optional"`
CacheFrom []string `pulumi:"cacheFrom,optional"`
CacheTo []string `pulumi:"cacheTo,optional"`
Context string `pulumi:"context,optional"`
Exports []string `pulumi:"exports,optional"`
File string `pulumi:"file,optional"`
Platforms []string `pulumi:"platforms,optional"`
Pull bool `pulumi:"pull,optional"`
Tags []string `pulumi:"tags"`
BuildArgs map[string]string `pulumi:"buildArgs,optional"`
CacheFrom []string `pulumi:"cacheFrom,optional"`
CacheTo []string `pulumi:"cacheTo,optional"`
Context string `pulumi:"context,optional"`
Exports []string `pulumi:"exports,optional"`
File string `pulumi:"file,optional"`
Platforms []string `pulumi:"platforms,optional"`
Pull bool `pulumi:"pull,optional"`
Registries []properties.RegistryAuth `pulumi:"registries,optional"`
Tags []string `pulumi:"tags"`
}

// Annotate describes inputs to the Image resource.
Expand Down Expand Up @@ -93,6 +94,9 @@ func (ia *ImageArgs) Annotate(a infer.Annotator) {
Name and optionally a tag (format: "name:tag"). If outputting to a
registry, the name should include the fully qualified registry address.`,
))
a.Describe(&ia.Registries, dedent.String(`
Logins for registry outputs`,
))

a.SetDefault(&ia.File, "Dockerfile")
}
Expand All @@ -112,7 +116,7 @@ func (is *ImageState) Annotate(a infer.Annotator) {
// Check validates ImageArgs, sets defaults, and ensures our client is
// authenticated.
func (*Image) Check(
_ provider.Context,
ctx provider.Context,
_ string,
_ resource.PropertyMap,
news resource.PropertyMap,
Expand Down Expand Up @@ -140,6 +144,16 @@ func (*Image) Check(
}
}

// Check is called before every operation except Read, so this ensures
// we're authenticated in almost all cases.
cfg := infer.GetConfig[Config](ctx)
for _, reg := range args.Registries {
if err = cfg.client.Auth(ctx, reg); err != nil {
failures = append(failures,
provider.CheckFailure{Property: "registries", Reason: fmt.Sprintf("unable to authenticate: %s", err.Error())})
}
}

return args, failures, err
}

Expand Down Expand Up @@ -268,7 +282,13 @@ func (*Image) Read(
return id, input, state, err
}

// Ensure we're authenticated.
cfg := infer.GetConfig[Config](ctx)
for _, reg := range input.Registries {
if err = cfg.client.Auth(ctx, reg); err != nil {
return id, input, state, err
}
}

manifests := []properties.Manifest{}
for _, export := range opts.Exports {
Expand Down
10 changes: 10 additions & 0 deletions provider/internal/image_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ func TestLifecycle(t *testing.T) {
client: func(t *testing.T) Client {
ctrl := gomock.NewController(t)
c := mock.NewMockClient(ctrl)
c.EXPECT().Auth(gomock.Any(), gomock.Any()).Return(nil).AnyTimes()
gomock.InOrder(
c.EXPECT().BuildKitEnabled().Return(true, nil), // Preview.
c.EXPECT().BuildKitEnabled().Return(true, nil), // Create.
Expand Down Expand Up @@ -80,6 +81,15 @@ func TestLifecycle(t *testing.T) {
"exports": resource.NewArrayProperty(
[]resource.PropertyValue{resource.NewStringProperty("type=registry")},
),
"registries": resource.NewArrayProperty(
[]resource.PropertyValue{
resource.NewObjectProperty(resource.PropertyMap{
"address": resource.NewStringProperty("fakeaddress"),
"username": resource.NewStringProperty("fakeuser"),
"password": resource.NewStringProperty("fakepass"),
}),
},
),
},
}
},
Expand Down
2 changes: 1 addition & 1 deletion provider/internal/mock/client.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions provider/internal/properties/properties.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@ func (m *Manifest) Annotate(a infer.Annotator) {
a.Describe(&m.Ref, "The manifest's ref")
}

type ProviderRegistryAuth struct {
type RegistryAuth struct {
Address string `pulumi:"address"`
Password string `pulumi:"password,optional" provider:"secret"`
Username string `pulumi:"username,optional"`
}

func (ra *ProviderRegistryAuth) Annotate(a infer.Annotator) {
func (ra *RegistryAuth) Annotate(a infer.Annotator) {
a.Describe(&ra.Address, `The registry's address (e.g. "docker.io")`)
a.Describe(&ra.Username, `Username for the registry`)
a.Describe(&ra.Password, `Password or token for the registry`)
Expand Down
20 changes: 20 additions & 0 deletions sdk/dotnet/Buildx/Image.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

48 changes: 48 additions & 0 deletions sdk/dotnet/Buildx/Inputs/RegistryAuthArgs.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

42 changes: 42 additions & 0 deletions sdk/dotnet/Buildx/Outputs/RegistryAuth.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 36630df

Please sign in to comment.