Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use Docker credentials file to log in to registry #461

Merged
merged 5 commits into from
Jan 20, 2023
Merged
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
4 changes: 1 addition & 3 deletions provider/cmd/pulumi-resource-docker/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -3161,9 +3161,7 @@
},
"type": "object",
"required": [
"server",
"username",
"password"
"server"
]
}
},
Expand Down
36 changes: 29 additions & 7 deletions provider/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -175,15 +175,37 @@ func (p *dockerNativeProvider) dockerBuild(ctx context.Context,
if err != nil {
return "", nil, err
}
// Quick and dirty auth; we can also preconfigure the client itself I believe
// TODO: use auth pattern as above to use default auth
var authConfig = types.AuthConfig{
Username: img.Registry.Username,
Password: img.Registry.Password,
ServerAddress: img.Registry.Server,

// authentication for registry push
// we check if the user set creds in the Pulumi program, and use those preferentially
var pushAuthConfig types.AuthConfig

if img.Registry.Username != "" && img.Registry.Password != "" {
pushAuthConfig.Username = img.Registry.Username
pushAuthConfig.Password = img.Registry.Password
pushAuthConfig.ServerAddress = img.Registry.Server
} else {
Comment on lines +183 to +187
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it valid to pass a username without a password or vice versa? If not, do we warn?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

either is valid - neither field is required per the schema. If either field is empty, we default to the host credentials. 🤔 warning might make sense because using host credentials isn't as obvious. 👍

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"valid" was perhaps the wrong word to use. What I should have said, and what I meant, was "does it ever make sense for the user to set a username without a password or vice versa."

My goal is to make sure that if the user does something that doesn't make sense, we will let them know.

// send warning if user is attempting to use in-program credentials
if img.Registry.Username == "" && img.Registry.Password != "" {
msg := "username was not set, although password was; using host credentials file"
err = p.host.LogStatus(ctx, "warning", urn, msg)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My understanding is that LogStatus is a transient message, but I think a permanent message would be appropriate here. We want the warning to be discoverable by the user after the program has been run.

Suggested change
err = p.host.LogStatus(ctx, "warning", urn, msg)
err = p.host.Log(ctx, "warning", urn, msg)

if err != nil {
return "", nil, err
}
}
if img.Registry.Password == "" && img.Registry.Username != "" {
msg := "password was not set, although username was; using host credentials file"
err = p.host.LogStatus(ctx, "warning", urn, msg)
if err != nil {
return "", nil, err
}
}
// we push to the server declared in the program, using our auth configs from image build.
// if the program does not have a server declared, we will let the docker client error
pushAuthConfig = authConfigs[img.Registry.Server]
}

authConfigBytes, err := json.Marshal(authConfig)
authConfigBytes, err := json.Marshal(pushAuthConfig)

if err != nil {
return "", nil, errors.Wrap(err, "Error parsing authConfig")
Expand Down
2 changes: 1 addition & 1 deletion provider/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ func Provider() tfbridge.ProviderInfo {
Secret: true,
},
},
Required: []string{"server", "username", "password"},
Required: []string{"server"},
},
},
dockerResource(dockerMod, "DockerBuild").String(): {
Expand Down
6 changes: 3 additions & 3 deletions sdk/dotnet/Inputs/RegistryArgs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace Pulumi.Docker.Inputs
/// </summary>
public sealed class RegistryArgs : global::Pulumi.ResourceArgs
{
[Input("password", required: true)]
[Input("password")]
private Input<string>? _password;

/// <summary>
Expand All @@ -40,8 +40,8 @@ public Input<string>? Password
/// <summary>
/// The username to authenticate to the registry
/// </summary>
[Input("username", required: true)]
public Input<string> Username { get; set; } = null!;
[Input("username")]
public Input<string>? Username { get; set; }

public RegistryArgs()
{
Expand Down
20 changes: 10 additions & 10 deletions sdk/go/docker/pulumiTypes.go

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

24 changes: 12 additions & 12 deletions sdk/java/src/main/java/com/pulumi/docker/inputs/RegistryArgs.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import com.pulumi.core.annotations.Import;
import java.lang.String;
import java.util.Objects;
import java.util.Optional;
import javax.annotation.Nullable;


/**
Expand All @@ -21,15 +23,15 @@ public final class RegistryArgs extends com.pulumi.resources.ResourceArgs {
* The password to authenticate to the registry
*
*/
@Import(name="password", required=true)
private Output<String> password;
@Import(name="password")
private @Nullable Output<String> password;

/**
* @return The password to authenticate to the registry
*
*/
public Output<String> password() {
return this.password;
public Optional<Output<String>> password() {
return Optional.ofNullable(this.password);
}

/**
Expand All @@ -51,15 +53,15 @@ public Output<String> server() {
* The username to authenticate to the registry
*
*/
@Import(name="username", required=true)
private Output<String> username;
@Import(name="username")
private @Nullable Output<String> username;

/**
* @return The username to authenticate to the registry
*
*/
public Output<String> username() {
return this.username;
public Optional<Output<String>> username() {
return Optional.ofNullable(this.username);
}

private RegistryArgs() {}
Expand Down Expand Up @@ -94,7 +96,7 @@ public Builder(RegistryArgs defaults) {
* @return builder
*
*/
public Builder password(Output<String> password) {
public Builder password(@Nullable Output<String> password) {
$.password = password;
return this;
}
Expand Down Expand Up @@ -136,7 +138,7 @@ public Builder server(String server) {
* @return builder
*
*/
public Builder username(Output<String> username) {
public Builder username(@Nullable Output<String> username) {
$.username = username;
return this;
}
Expand All @@ -152,9 +154,7 @@ public Builder username(String username) {
}

public RegistryArgs build() {
$.password = Objects.requireNonNull($.password, "expected parameter 'password' to be non-null");
$.server = Objects.requireNonNull($.server, "expected parameter 'server' to be non-null");
$.username = Objects.requireNonNull($.username, "expected parameter 'username' to be non-null");
return $;
}
}
Expand Down
4 changes: 2 additions & 2 deletions sdk/nodejs/types/input.ts
Original file line number Diff line number Diff line change
Expand Up @@ -380,15 +380,15 @@ export interface Registry {
/**
* The password to authenticate to the registry
*/
password: pulumi.Input<string>;
password?: pulumi.Input<string>;
/**
* The URL of the Docker registry server
*/
server: pulumi.Input<string>;
/**
* The username to authenticate to the registry
*/
username: pulumi.Input<string>;
username?: pulumi.Input<string>;
}

export interface RegistryImageBuild {
Expand Down
40 changes: 21 additions & 19 deletions sdk/python/pulumi_docker/_inputs.py
Original file line number Diff line number Diff line change
Expand Up @@ -4196,30 +4196,20 @@ def target(self, value: Optional[pulumi.Input[str]]):
@pulumi.input_type
class RegistryArgs:
def __init__(__self__, *,
password: pulumi.Input[str],
server: pulumi.Input[str],
username: pulumi.Input[str]):
password: Optional[pulumi.Input[str]] = None,
username: Optional[pulumi.Input[str]] = None):
"""
Describes a Docker container registry
:param pulumi.Input[str] password: The password to authenticate to the registry
:param pulumi.Input[str] server: The URL of the Docker registry server
:param pulumi.Input[str] password: The password to authenticate to the registry
:param pulumi.Input[str] username: The username to authenticate to the registry
"""
pulumi.set(__self__, "password", password)
pulumi.set(__self__, "server", server)
pulumi.set(__self__, "username", username)

@property
@pulumi.getter
def password(self) -> pulumi.Input[str]:
"""
The password to authenticate to the registry
"""
return pulumi.get(self, "password")

@password.setter
def password(self, value: pulumi.Input[str]):
pulumi.set(self, "password", value)
if password is not None:
pulumi.set(__self__, "password", password)
if username is not None:
pulumi.set(__self__, "username", username)

@property
@pulumi.getter
Expand All @@ -4235,14 +4225,26 @@ def server(self, value: pulumi.Input[str]):

@property
@pulumi.getter
def username(self) -> pulumi.Input[str]:
def password(self) -> Optional[pulumi.Input[str]]:
"""
The password to authenticate to the registry
"""
return pulumi.get(self, "password")

@password.setter
def password(self, value: Optional[pulumi.Input[str]]):
pulumi.set(self, "password", value)

@property
@pulumi.getter
def username(self) -> Optional[pulumi.Input[str]]:
"""
The username to authenticate to the registry
"""
return pulumi.get(self, "username")

@username.setter
def username(self, value: pulumi.Input[str]):
def username(self, value: Optional[pulumi.Input[str]]):
pulumi.set(self, "username", value)