Change --no-resolve-image flag to --resolve-image string flag

Signed-off-by: Nishant Totla <nishanttotla@gmail.com>
This commit is contained in:
Nishant Totla 2017-06-02 16:21:41 -07:00
parent 9f1bea2657
commit f790e839fc
No known key found for this signature in database
GPG Key ID: 7EA5781C9B3D0C19
4 changed files with 37 additions and 21 deletions

View File

@ -15,14 +15,17 @@ import (
const ( const (
defaultNetworkDriver = "overlay" defaultNetworkDriver = "overlay"
resolveImageAlways = "always"
resolveImageChanged = "changed"
resolveImageNever = "never"
) )
type deployOptions struct { type deployOptions struct {
bundlefile string bundlefile string
composefile string composefile string
namespace string namespace string
resolveImage string
sendRegistryAuth bool sendRegistryAuth bool
noResolveImage bool
prune bool prune bool
} }
@ -46,17 +49,17 @@ func newDeployCommand(dockerCli command.Cli) *cobra.Command {
addRegistryAuthFlag(&opts.sendRegistryAuth, flags) addRegistryAuthFlag(&opts.sendRegistryAuth, flags)
flags.BoolVar(&opts.prune, "prune", false, "Prune services that are no longer referenced") flags.BoolVar(&opts.prune, "prune", false, "Prune services that are no longer referenced")
flags.SetAnnotation("prune", "version", []string{"1.27"}) flags.SetAnnotation("prune", "version", []string{"1.27"})
flags.BoolVar(&opts.noResolveImage, "no-resolve-image", false, "Do not query the registry to resolve image digest and supported platforms") flags.StringVar(&opts.resolveImage, "resolve-image", resolveImageAlways,
flags.SetAnnotation("no-resolve-image", "version", []string{"1.30"}) `Query the registry to resolve image digest and supported platforms ("`+resolveImageAlways+`"|"`+resolveImageChanged+`"|"`+resolveImageNever+`")`)
flags.SetAnnotation("resolve-image", "version", []string{"1.30"})
return cmd return cmd
} }
func runDeploy(dockerCli command.Cli, opts deployOptions) error { func runDeploy(dockerCli command.Cli, opts deployOptions) error {
ctx := context.Background() ctx := context.Background()
// image resolution should not happen for clients older than v1.30 if err := validateResolveImageFlag(dockerCli, &opts); err != nil {
if versions.LessThan(dockerCli.Client().ClientVersion(), "1.30") { return err
opts.noResolveImage = true
} }
switch { switch {
@ -71,6 +74,20 @@ func runDeploy(dockerCli command.Cli, opts deployOptions) error {
} }
} }
// validateResolveImageFlag validates the opts.resolveImage command line option
// and also turns image resolution off if the version is older than 1.30
func validateResolveImageFlag(dockerCli command.Cli, opts *deployOptions) error {
if opts.resolveImage != resolveImageAlways && opts.resolveImage != resolveImageChanged && opts.resolveImage != resolveImageNever {
return errors.Errorf("Invalid option %s for flag --resolve-image", opts.resolveImage)
}
// client side image resolution should not be done when the supported
// server version is older than 1.30
if versions.LessThan(dockerCli.Client().ClientVersion(), "1.30") {
opts.resolveImage = resolveImageNever
}
return nil
}
// checkDaemonIsSwarmManager does an Info API call to verify that the daemon is // checkDaemonIsSwarmManager does an Info API call to verify that the daemon is
// a swarm manager. This is necessary because we must create networks before we // a swarm manager. This is necessary because we must create networks before we
// create services, but the API call for creating a network does not return a // create services, but the API call for creating a network does not return a

View File

@ -87,5 +87,5 @@ func deployBundle(ctx context.Context, dockerCli command.Cli, opts deployOptions
if err := createNetworks(ctx, dockerCli, namespace, networks); err != nil { if err := createNetworks(ctx, dockerCli, namespace, networks); err != nil {
return err return err
} }
return deployServices(ctx, dockerCli, services, namespace, opts.sendRegistryAuth, opts.noResolveImage) return deployServices(ctx, dockerCli, services, namespace, opts.sendRegistryAuth, opts.resolveImage)
} }

View File

@ -92,7 +92,7 @@ func deployCompose(ctx context.Context, dockerCli command.Cli, opts deployOption
if err != nil { if err != nil {
return err return err
} }
return deployServices(ctx, dockerCli, services, namespace, opts.sendRegistryAuth, opts.noResolveImage) return deployServices(ctx, dockerCli, services, namespace, opts.sendRegistryAuth, opts.resolveImage)
} }
func getServicesDeclaredNetworks(serviceConfigs []composetypes.ServiceConfig) map[string]struct{} { func getServicesDeclaredNetworks(serviceConfigs []composetypes.ServiceConfig) map[string]struct{} {
@ -283,7 +283,7 @@ func deployServices(
services map[string]swarm.ServiceSpec, services map[string]swarm.ServiceSpec,
namespace convert.Namespace, namespace convert.Namespace,
sendAuth bool, sendAuth bool,
noResolveImage bool, resolveImage string,
) error { ) error {
apiClient := dockerCli.Client() apiClient := dockerCli.Client()
out := dockerCli.Out() out := dockerCli.Out()
@ -316,10 +316,8 @@ func deployServices(
updateOpts := types.ServiceUpdateOptions{EncodedRegistryAuth: encodedAuth} updateOpts := types.ServiceUpdateOptions{EncodedRegistryAuth: encodedAuth}
if image != service.Spec.Labels["com.docker.stack.image"] { if resolveImage == resolveImageAlways || (resolveImage == resolveImageChanged && image != service.Spec.Labels[convert.LabelImage]) {
if !noResolveImage { updateOpts.QueryRegistry = true
updateOpts.QueryRegistry = true
}
} }
response, err := apiClient.ServiceUpdate( response, err := apiClient.ServiceUpdate(
@ -342,7 +340,7 @@ func deployServices(
createOpts := types.ServiceCreateOptions{EncodedRegistryAuth: encodedAuth} createOpts := types.ServiceCreateOptions{EncodedRegistryAuth: encodedAuth}
// query registry if flag disabling it was not set // query registry if flag disabling it was not set
if !noResolveImage { if resolveImage == resolveImageAlways || resolveImage == resolveImageChanged {
createOpts.QueryRegistry = true createOpts.QueryRegistry = true
} }

View File

@ -17,7 +17,11 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
const defaultNetwork = "default" const (
defaultNetwork = "default"
// LabelImage is the label used to store image name provided in the compose file
LabelImage = "com.docker.stack.image"
)
// Services from compose-file types to engine API types // Services from compose-file types to engine API types
func Services( func Services(
@ -45,12 +49,6 @@ func Services(
if err != nil { if err != nil {
return nil, errors.Wrapf(err, "service %s", service.Name) return nil, errors.Wrapf(err, "service %s", service.Name)
} }
// add an image label to serviceSpec
if serviceSpec.Labels == nil {
serviceSpec.Labels = make(map[string]string)
}
serviceSpec.Labels["com.docker.stack.image"] = service.Image
result[service.Name] = serviceSpec result[service.Name] = serviceSpec
} }
@ -163,6 +161,9 @@ func convertService(
UpdateConfig: convertUpdateConfig(service.Deploy.UpdateConfig), UpdateConfig: convertUpdateConfig(service.Deploy.UpdateConfig),
} }
// add an image label to serviceSpec
serviceSpec.Labels[LabelImage] = service.Image
// ServiceSpec.Networks is deprecated and should not have been used by // ServiceSpec.Networks is deprecated and should not have been used by
// this package. It is possible to update TaskTemplate.Networks, but it // this package. It is possible to update TaskTemplate.Networks, but it
// is not possible to update ServiceSpec.Networks. Unfortunately, we // is not possible to update ServiceSpec.Networks. Unfortunately, we