Adding a flag to specify sending of registry auth
Signed-off-by: Nishant Totla <nishanttotla@gmail.com>
This commit is contained in:
parent
af5df117a8
commit
538bac39d7
7 changed files with 59 additions and 41 deletions
|
@ -149,8 +149,8 @@ func (cli *DockerCli) ConfigureAuth(flUser, flPassword, serverAddress string, is
|
||||||
return authconfig, nil
|
return authconfig, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ResolveAuthConfigFromImage retrieves that AuthConfig using the image string
|
// resolveAuthConfigFromImage retrieves that AuthConfig using the image string
|
||||||
func (cli *DockerCli) ResolveAuthConfigFromImage(ctx context.Context, image string) (types.AuthConfig, error) {
|
func (cli *DockerCli) resolveAuthConfigFromImage(ctx context.Context, image string) (types.AuthConfig, error) {
|
||||||
registryRef, err := reference.ParseNamed(image)
|
registryRef, err := reference.ParseNamed(image)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return types.AuthConfig{}, err
|
return types.AuthConfig{}, err
|
||||||
|
@ -166,7 +166,7 @@ func (cli *DockerCli) ResolveAuthConfigFromImage(ctx context.Context, image stri
|
||||||
// RetrieveAuthTokenFromImage retrieves an encoded auth token given a complete image
|
// RetrieveAuthTokenFromImage retrieves an encoded auth token given a complete image
|
||||||
func (cli *DockerCli) RetrieveAuthTokenFromImage(ctx context.Context, image string) (string, error) {
|
func (cli *DockerCli) RetrieveAuthTokenFromImage(ctx context.Context, image string) (string, error) {
|
||||||
// Retrieve encoded auth token from the image reference
|
// Retrieve encoded auth token from the image reference
|
||||||
authConfig, err := cli.ResolveAuthConfigFromImage(ctx, image)
|
authConfig, err := cli.resolveAuthConfigFromImage(ctx, image)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ func newCreateCommand(dockerCli *client.DockerCli) *cobra.Command {
|
||||||
|
|
||||||
func runCreate(dockerCli *client.DockerCli, opts *serviceOptions) error {
|
func runCreate(dockerCli *client.DockerCli, opts *serviceOptions) error {
|
||||||
apiClient := dockerCli.Client()
|
apiClient := dockerCli.Client()
|
||||||
|
headers := map[string][]string{}
|
||||||
|
|
||||||
service, err := opts.ToService()
|
service, err := opts.ToService()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -40,14 +41,15 @@ func runCreate(dockerCli *client.DockerCli, opts *serviceOptions) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
// Retrieve encoded auth token from the image reference
|
|
||||||
encodedAuth, err := dockerCli.RetrieveAuthTokenFromImage(ctx, opts.image)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
headers := map[string][]string{
|
// only send auth if flag was set
|
||||||
"X-Registry-Auth": {encodedAuth},
|
if opts.registryAuth {
|
||||||
|
// Retrieve encoded auth token from the image reference
|
||||||
|
encodedAuth, err := dockerCli.RetrieveAuthTokenFromImage(ctx, opts.image)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
headers["X-Registry-Auth"] = []string{encodedAuth}
|
||||||
}
|
}
|
||||||
|
|
||||||
response, err := apiClient.ServiceCreate(ctx, service, headers)
|
response, err := apiClient.ServiceCreate(ctx, service, headers)
|
||||||
|
|
|
@ -373,6 +373,8 @@ type serviceOptions struct {
|
||||||
update updateOptions
|
update updateOptions
|
||||||
networks []string
|
networks []string
|
||||||
endpoint endpointOptions
|
endpoint endpointOptions
|
||||||
|
|
||||||
|
registryAuth bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func newServiceOptions() *serviceOptions {
|
func newServiceOptions() *serviceOptions {
|
||||||
|
@ -436,7 +438,7 @@ func (opts *serviceOptions) ToService() (swarm.ServiceSpec, error) {
|
||||||
return service, nil
|
return service, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// addServiceFlags adds all flags that are common to both `create` and `update.
|
// addServiceFlags adds all flags that are common to both `create` and `update`.
|
||||||
// Any flags that are not common are added separately in the individual command
|
// Any flags that are not common are added separately in the individual command
|
||||||
func addServiceFlags(cmd *cobra.Command, opts *serviceOptions) {
|
func addServiceFlags(cmd *cobra.Command, opts *serviceOptions) {
|
||||||
flags := cmd.Flags()
|
flags := cmd.Flags()
|
||||||
|
@ -469,6 +471,8 @@ func addServiceFlags(cmd *cobra.Command, opts *serviceOptions) {
|
||||||
flags.StringSliceVar(&opts.networks, flagNetwork, []string{}, "Network attachments")
|
flags.StringSliceVar(&opts.networks, flagNetwork, []string{}, "Network attachments")
|
||||||
flags.StringVar(&opts.endpoint.mode, flagEndpointMode, "", "Endpoint mode(Valid values: vip, dnsrr)")
|
flags.StringVar(&opts.endpoint.mode, flagEndpointMode, "", "Endpoint mode(Valid values: vip, dnsrr)")
|
||||||
flags.VarP(&opts.endpoint.ports, flagPublish, "p", "Publish a port as a node port")
|
flags.VarP(&opts.endpoint.ports, flagPublish, "p", "Publish a port as a node port")
|
||||||
|
|
||||||
|
flags.BoolVar(&opts.registryAuth, flagRegistryAuth, false, "Send registry authentication details to Swarm agents")
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -493,4 +497,5 @@ const (
|
||||||
flagUpdateDelay = "update-delay"
|
flagUpdateDelay = "update-delay"
|
||||||
flagUpdateParallelism = "update-parallelism"
|
flagUpdateParallelism = "update-parallelism"
|
||||||
flagUser = "user"
|
flagUser = "user"
|
||||||
|
flagRegistryAuth = "registry-auth"
|
||||||
)
|
)
|
||||||
|
|
|
@ -60,7 +60,6 @@ func runScale(dockerCli *client.DockerCli, args []string) error {
|
||||||
func runServiceScale(dockerCli *client.DockerCli, serviceID string, scale string) error {
|
func runServiceScale(dockerCli *client.DockerCli, serviceID string, scale string) error {
|
||||||
client := dockerCli.Client()
|
client := dockerCli.Client()
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
headers := map[string][]string{}
|
|
||||||
|
|
||||||
service, _, err := client.ServiceInspectWithRaw(ctx, serviceID)
|
service, _, err := client.ServiceInspectWithRaw(ctx, serviceID)
|
||||||
|
|
||||||
|
@ -68,17 +67,6 @@ func runServiceScale(dockerCli *client.DockerCli, serviceID string, scale string
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(nishanttotla): Is this the best way to get the image?
|
|
||||||
image := service.Spec.TaskTemplate.ContainerSpec.Image
|
|
||||||
if image != "" {
|
|
||||||
// Retrieve encoded auth token from the image reference
|
|
||||||
encodedAuth, err := dockerCli.RetrieveAuthTokenFromImage(ctx, image)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
headers["X-Registry-Auth"] = []string{encodedAuth}
|
|
||||||
}
|
|
||||||
|
|
||||||
serviceMode := &service.Spec.Mode
|
serviceMode := &service.Spec.Mode
|
||||||
if serviceMode.Replicated == nil {
|
if serviceMode.Replicated == nil {
|
||||||
return fmt.Errorf("scale can only be used with replicated mode")
|
return fmt.Errorf("scale can only be used with replicated mode")
|
||||||
|
@ -89,7 +77,7 @@ func runServiceScale(dockerCli *client.DockerCli, serviceID string, scale string
|
||||||
}
|
}
|
||||||
serviceMode.Replicated.Replicas = &uintScale
|
serviceMode.Replicated.Replicas = &uintScale
|
||||||
|
|
||||||
err = client.ServiceUpdate(ctx, service.ID, service.Version, service.Spec, headers)
|
err = client.ServiceUpdate(ctx, service.ID, service.Version, service.Spec, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,21 +41,6 @@ func runUpdate(dockerCli *client.DockerCli, flags *pflag.FlagSet, serviceID stri
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
headers := map[string][]string{}
|
headers := map[string][]string{}
|
||||||
|
|
||||||
// TODO(nishanttotla): Is this the best way to get the new image?
|
|
||||||
image, err := flags.GetString("image")
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if image != "" {
|
|
||||||
// Retrieve encoded auth token from the image reference
|
|
||||||
// only do this if a new image has been provided as part of the udpate
|
|
||||||
encodedAuth, err := dockerCli.RetrieveAuthTokenFromImage(ctx, image)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
headers["X-Registry-Auth"] = []string{encodedAuth}
|
|
||||||
}
|
|
||||||
|
|
||||||
service, _, err := apiClient.ServiceInspectWithRaw(ctx, serviceID)
|
service, _, err := apiClient.ServiceInspectWithRaw(ctx, serviceID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -66,6 +51,22 @@ func runUpdate(dockerCli *client.DockerCli, flags *pflag.FlagSet, serviceID stri
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// only send auth if flag was set
|
||||||
|
sendAuth, err := flags.GetBool(flagRegistryAuth)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if sendAuth {
|
||||||
|
// Retrieve encoded auth token from the image reference
|
||||||
|
// This would be the old image if it didn't change in this update
|
||||||
|
image := service.Spec.TaskTemplate.ContainerSpec.Image
|
||||||
|
encodedAuth, err := dockerCli.RetrieveAuthTokenFromImage(ctx, image)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
headers["X-Registry-Auth"] = []string{encodedAuth}
|
||||||
|
}
|
||||||
|
|
||||||
err = apiClient.ServiceUpdate(ctx, service.ID, service.Version, service.Spec, headers)
|
err = apiClient.ServiceUpdate(ctx, service.ID, service.Version, service.Spec, headers)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -107,6 +107,7 @@ func (sr *swarmRouter) createService(ctx context.Context, w http.ResponseWriter,
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get returns "" if the header does not exist
|
||||||
encodedAuth := r.Header.Get("X-Registry-Auth")
|
encodedAuth := r.Header.Get("X-Registry-Auth")
|
||||||
|
|
||||||
id, err := sr.backend.CreateService(service, encodedAuth)
|
id, err := sr.backend.CreateService(service, encodedAuth)
|
||||||
|
@ -132,6 +133,7 @@ func (sr *swarmRouter) updateService(ctx context.Context, w http.ResponseWriter,
|
||||||
return fmt.Errorf("Invalid service version '%s': %s", rawVersion, err.Error())
|
return fmt.Errorf("Invalid service version '%s': %s", rawVersion, err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get returns "" if the header does not exist
|
||||||
encodedAuth := r.Header.Get("X-Registry-Auth")
|
encodedAuth := r.Header.Get("X-Registry-Auth")
|
||||||
|
|
||||||
if err := sr.backend.UpdateService(vars["id"], version, service, encodedAuth); err != nil {
|
if err := sr.backend.UpdateService(vars["id"], version, service, encodedAuth); err != nil {
|
||||||
|
|
|
@ -689,7 +689,11 @@ func (c *Cluster) CreateService(s types.ServiceSpec, encodedAuth string) (string
|
||||||
}
|
}
|
||||||
|
|
||||||
if encodedAuth != "" {
|
if encodedAuth != "" {
|
||||||
serviceSpec.Task.Runtime.(*swarmapi.TaskSpec_Container).Container.PullOptions = &swarmapi.ContainerSpec_PullOptions{RegistryAuth: encodedAuth}
|
ctnr := serviceSpec.Task.GetContainer()
|
||||||
|
if ctnr == nil {
|
||||||
|
return "", fmt.Errorf("service does not use container tasks")
|
||||||
|
}
|
||||||
|
ctnr.PullOptions = &swarmapi.ContainerSpec_PullOptions{RegistryAuth: encodedAuth}
|
||||||
}
|
}
|
||||||
|
|
||||||
r, err := c.client.CreateService(ctx, &swarmapi.CreateServiceRequest{Spec: &serviceSpec})
|
r, err := c.client.CreateService(ctx, &swarmapi.CreateServiceRequest{Spec: &serviceSpec})
|
||||||
|
@ -731,7 +735,23 @@ func (c *Cluster) UpdateService(serviceID string, version uint64, spec types.Ser
|
||||||
}
|
}
|
||||||
|
|
||||||
if encodedAuth != "" {
|
if encodedAuth != "" {
|
||||||
serviceSpec.Task.Runtime.(*swarmapi.TaskSpec_Container).Container.PullOptions = &swarmapi.ContainerSpec_PullOptions{RegistryAuth: encodedAuth}
|
ctnr := serviceSpec.Task.GetContainer()
|
||||||
|
if ctnr == nil {
|
||||||
|
return fmt.Errorf("service does not use container tasks")
|
||||||
|
}
|
||||||
|
ctnr.PullOptions = &swarmapi.ContainerSpec_PullOptions{RegistryAuth: encodedAuth}
|
||||||
|
} else {
|
||||||
|
// this is needed because if the encodedAuth isn't being updated then we
|
||||||
|
// shouldn't lose it, and continue to use the one that was already present
|
||||||
|
currentService, err := getService(c.getRequestContext(), c.client, serviceID)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
ctnr := currentService.Spec.Task.GetContainer()
|
||||||
|
if ctnr == nil {
|
||||||
|
return fmt.Errorf("service does not use container tasks")
|
||||||
|
}
|
||||||
|
serviceSpec.Task.GetContainer().PullOptions = ctnr.PullOptions
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = c.client.UpdateService(
|
_, err = c.client.UpdateService(
|
||||||
|
|
Loading…
Reference in a new issue