Signed-off-by: Nishant Totla <nishanttotla@gmail.com>
| ... | ... |
@@ -19,8 +19,8 @@ type Backend interface {
|
| 19 | 19 |
|
| 20 | 20 |
GetServices(basictypes.ServiceListOptions) ([]types.Service, error) |
| 21 | 21 |
GetService(idOrName string, insertDefaults bool) (types.Service, error) |
| 22 |
- CreateService(types.ServiceSpec, string) (*basictypes.ServiceCreateResponse, error) |
|
| 23 |
- UpdateService(string, uint64, types.ServiceSpec, basictypes.ServiceUpdateOptions) (*basictypes.ServiceUpdateResponse, error) |
|
| 22 |
+ CreateService(types.ServiceSpec, string, bool) (*basictypes.ServiceCreateResponse, error) |
|
| 23 |
+ UpdateService(string, uint64, types.ServiceSpec, basictypes.ServiceUpdateOptions, bool) (*basictypes.ServiceUpdateResponse, error) |
|
| 24 | 24 |
RemoveService(string) error |
| 25 | 25 |
|
| 26 | 26 |
ServiceLogs(context.Context, *backend.LogSelector, *basictypes.ContainerLogsOptions) (<-chan *backend.LogMessage, error) |
| ... | ... |
@@ -13,6 +13,7 @@ import ( |
| 13 | 13 |
"github.com/docker/docker/api/types/backend" |
| 14 | 14 |
"github.com/docker/docker/api/types/filters" |
| 15 | 15 |
types "github.com/docker/docker/api/types/swarm" |
| 16 |
+ "github.com/docker/docker/api/types/versions" |
|
| 16 | 17 |
"golang.org/x/net/context" |
| 17 | 18 |
) |
| 18 | 19 |
|
| ... | ... |
@@ -178,8 +179,13 @@ func (sr *swarmRouter) createService(ctx context.Context, w http.ResponseWriter, |
| 178 | 178 |
|
| 179 | 179 |
// Get returns "" if the header does not exist |
| 180 | 180 |
encodedAuth := r.Header.Get("X-Registry-Auth")
|
| 181 |
+ cliVersion := r.Header.Get("version")
|
|
| 182 |
+ queryRegistry := false |
|
| 183 |
+ if cliVersion != "" && versions.LessThan(cliVersion, "1.30") {
|
|
| 184 |
+ queryRegistry = true |
|
| 185 |
+ } |
|
| 181 | 186 |
|
| 182 |
- resp, err := sr.backend.CreateService(service, encodedAuth) |
|
| 187 |
+ resp, err := sr.backend.CreateService(service, encodedAuth, queryRegistry) |
|
| 183 | 188 |
if err != nil {
|
| 184 | 189 |
logrus.Errorf("Error creating service %s: %v", service.Name, err)
|
| 185 | 190 |
return err |
| ... | ... |
@@ -207,8 +213,13 @@ func (sr *swarmRouter) updateService(ctx context.Context, w http.ResponseWriter, |
| 207 | 207 |
flags.EncodedRegistryAuth = r.Header.Get("X-Registry-Auth")
|
| 208 | 208 |
flags.RegistryAuthFrom = r.URL.Query().Get("registryAuthFrom")
|
| 209 | 209 |
flags.Rollback = r.URL.Query().Get("rollback")
|
| 210 |
+ cliVersion := r.Header.Get("version")
|
|
| 211 |
+ queryRegistry := false |
|
| 212 |
+ if cliVersion != "" && versions.LessThan(cliVersion, "1.30") {
|
|
| 213 |
+ queryRegistry = true |
|
| 214 |
+ } |
|
| 210 | 215 |
|
| 211 |
- resp, err := sr.backend.UpdateService(vars["id"], version, service, flags) |
|
| 216 |
+ resp, err := sr.backend.UpdateService(vars["id"], version, service, flags, queryRegistry) |
|
| 212 | 217 |
if err != nil {
|
| 213 | 218 |
logrus.Errorf("Error updating service %s: %v", vars["id"], err)
|
| 214 | 219 |
return err |
| ... | ... |
@@ -13,15 +13,14 @@ import ( |
| 13 | 13 |
|
| 14 | 14 |
// ServiceCreate creates a new Service. |
| 15 | 15 |
func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec, options types.ServiceCreateOptions) (types.ServiceCreateResponse, error) {
|
| 16 |
- var ( |
|
| 17 |
- headers map[string][]string |
|
| 18 |
- distErr error |
|
| 19 |
- ) |
|
| 16 |
+ var distErr error |
|
| 17 |
+ |
|
| 18 |
+ headers := map[string][]string{
|
|
| 19 |
+ "version": {cli.version},
|
|
| 20 |
+ } |
|
| 20 | 21 |
|
| 21 | 22 |
if options.EncodedRegistryAuth != "" {
|
| 22 |
- headers = map[string][]string{
|
|
| 23 |
- "X-Registry-Auth": {options.EncodedRegistryAuth},
|
|
| 24 |
- } |
|
| 23 |
+ headers["X-Registry-Auth"] = []string{options.EncodedRegistryAuth}
|
|
| 25 | 24 |
} |
| 26 | 25 |
|
| 27 | 26 |
// Contact the registry to retrieve digest and platform information |
| ... | ... |
@@ -13,15 +13,16 @@ import ( |
| 13 | 13 |
// ServiceUpdate updates a Service. |
| 14 | 14 |
func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version swarm.Version, service swarm.ServiceSpec, options types.ServiceUpdateOptions) (types.ServiceUpdateResponse, error) {
|
| 15 | 15 |
var ( |
| 16 |
- headers map[string][]string |
|
| 17 | 16 |
query = url.Values{}
|
| 18 | 17 |
distErr error |
| 19 | 18 |
) |
| 20 | 19 |
|
| 20 |
+ headers := map[string][]string{
|
|
| 21 |
+ "version": {cli.version},
|
|
| 22 |
+ } |
|
| 23 |
+ |
|
| 21 | 24 |
if options.EncodedRegistryAuth != "" {
|
| 22 |
- headers = map[string][]string{
|
|
| 23 |
- "X-Registry-Auth": {options.EncodedRegistryAuth},
|
|
| 24 |
- } |
|
| 25 |
+ headers["X-Registry-Auth"] = []string{options.EncodedRegistryAuth}
|
|
| 25 | 26 |
} |
| 26 | 27 |
|
| 27 | 28 |
if options.RegistryAuthFrom != "" {
|
| ... | ... |
@@ -117,7 +117,7 @@ func (c *Cluster) GetService(input string, insertDefaults bool) (types.Service, |
| 117 | 117 |
} |
| 118 | 118 |
|
| 119 | 119 |
// CreateService creates a new service in a managed swarm cluster. |
| 120 |
-func (c *Cluster) CreateService(s types.ServiceSpec, encodedAuth string) (*apitypes.ServiceCreateResponse, error) {
|
|
| 120 |
+func (c *Cluster) CreateService(s types.ServiceSpec, encodedAuth string, queryRegistry bool) (*apitypes.ServiceCreateResponse, error) {
|
|
| 121 | 121 |
var resp *apitypes.ServiceCreateResponse |
| 122 | 122 |
err := c.lockedManagerAction(func(ctx context.Context, state nodeState) error {
|
| 123 | 123 |
err := c.populateNetworkID(ctx, state.controlClient, &s) |
| ... | ... |
@@ -151,8 +151,11 @@ func (c *Cluster) CreateService(s types.ServiceSpec, encodedAuth string) (*apity |
| 151 | 151 |
} |
| 152 | 152 |
} |
| 153 | 153 |
|
| 154 |
- // pin image by digest |
|
| 155 |
- if os.Getenv("DOCKER_SERVICE_PREFER_OFFLINE_IMAGE") != "1" {
|
|
| 154 |
+ // pin image by digest for API versions < 1.30 |
|
| 155 |
+ // TODO(nishanttotla): The check on "DOCKER_SERVICE_PREFER_OFFLINE_IMAGE" |
|
| 156 |
+ // should be removed in the future. Since integration tests only use the |
|
| 157 |
+ // latest API version, so this is no longer required. |
|
| 158 |
+ if os.Getenv("DOCKER_SERVICE_PREFER_OFFLINE_IMAGE") != "1" && queryRegistry {
|
|
| 156 | 159 |
digestImage, err := c.imageWithDigestString(ctx, ctnr.Image, authConfig) |
| 157 | 160 |
if err != nil {
|
| 158 | 161 |
logrus.Warnf("unable to pin image %s to digest: %s", ctnr.Image, err.Error())
|
| ... | ... |
@@ -193,7 +196,7 @@ func (c *Cluster) CreateService(s types.ServiceSpec, encodedAuth string) (*apity |
| 193 | 193 |
} |
| 194 | 194 |
|
| 195 | 195 |
// UpdateService updates existing service to match new properties. |
| 196 |
-func (c *Cluster) UpdateService(serviceIDOrName string, version uint64, spec types.ServiceSpec, flags apitypes.ServiceUpdateOptions) (*apitypes.ServiceUpdateResponse, error) {
|
|
| 196 |
+func (c *Cluster) UpdateService(serviceIDOrName string, version uint64, spec types.ServiceSpec, flags apitypes.ServiceUpdateOptions, queryRegistry bool) (*apitypes.ServiceUpdateResponse, error) {
|
|
| 197 | 197 |
var resp *apitypes.ServiceUpdateResponse |
| 198 | 198 |
|
| 199 | 199 |
err := c.lockedManagerAction(func(ctx context.Context, state nodeState) error {
|
| ... | ... |
@@ -256,8 +259,11 @@ func (c *Cluster) UpdateService(serviceIDOrName string, version uint64, spec typ |
| 256 | 256 |
|
| 257 | 257 |
resp = &apitypes.ServiceUpdateResponse{}
|
| 258 | 258 |
|
| 259 |
- // pin image by digest |
|
| 260 |
- if os.Getenv("DOCKER_SERVICE_PREFER_OFFLINE_IMAGE") != "1" {
|
|
| 259 |
+ // pin image by digest for API versions < 1.30 |
|
| 260 |
+ // TODO(nishanttotla): The check on "DOCKER_SERVICE_PREFER_OFFLINE_IMAGE" |
|
| 261 |
+ // should be removed in the future. Since integration tests only use the |
|
| 262 |
+ // latest API version, so this is no longer required. |
|
| 263 |
+ if os.Getenv("DOCKER_SERVICE_PREFER_OFFLINE_IMAGE") != "1" && queryRegistry {
|
|
| 261 | 264 |
digestImage, err := c.imageWithDigestString(ctx, newCtnr.Image, authConfig) |
| 262 | 265 |
if err != nil {
|
| 263 | 266 |
logrus.Warnf("unable to pin image %s to digest: %s", newCtnr.Image, err.Error())
|