Forráskód Böngészése

Adding compatible platforms to service spec

Signed-off-by: Nishant Totla <nishanttotla@gmail.com>
Nishant Totla 8 éve
szülő
commit
587d07cca8
3 módosított fájl, 75 hozzáadás és 0 törlés
  1. 19 0
      client/service_create.go
  2. 54 0
      client/service_create_test.go
  3. 2 0
      client/service_update.go

+ 19 - 0
client/service_create.go

@@ -6,6 +6,7 @@ import (
 
 	"github.com/docker/distribution/reference"
 	"github.com/docker/docker/api/types"
+	registrytypes "github.com/docker/docker/api/types/registry"
 	"github.com/docker/docker/api/types/swarm"
 	"github.com/opencontainers/go-digest"
 	"golang.org/x/net/context"
@@ -33,6 +34,8 @@ func (cli *Client) ServiceCreate(ctx context.Context, service swarm.ServiceSpec,
 			if img != "" {
 				service.TaskTemplate.ContainerSpec.Image = img
 			}
+			// add platforms that are compatible with the service
+			service.TaskTemplate.Placement = updateServicePlatforms(service.TaskTemplate.Placement, distributionInspect)
 		}
 	}
 	var response types.ServiceCreateResponse
@@ -71,6 +74,22 @@ func imageWithDigestString(image string, dgst digest.Digest) string {
 	return ""
 }
 
+// updateServicePlatforms updates the Platforms in swarm.Placement to list
+// all compatible platforms for the service, as found in distributionInspect
+// and returns a pointer to the new or updated swarm.Placement struct
+func updateServicePlatforms(placement *swarm.Placement, distributionInspect registrytypes.DistributionInspect) *swarm.Placement {
+	if placement == nil {
+		placement = &swarm.Placement{}
+	}
+	for _, p := range distributionInspect.Platforms {
+		placement.Platforms = append(placement.Platforms, swarm.Platform{
+			Architecture: p.Architecture,
+			OS:           p.OS,
+		})
+	}
+	return placement
+}
+
 // digestWarning constructs a formatted warning string using the
 // image name that could not be pinned by digest. The formatting
 // is hardcoded, but could me made smarter in the future

+ 54 - 0
client/service_create_test.go

@@ -10,7 +10,9 @@ import (
 	"testing"
 
 	"github.com/docker/docker/api/types"
+	registrytypes "github.com/docker/docker/api/types/registry"
 	"github.com/docker/docker/api/types/swarm"
+	"github.com/opencontainers/image-spec/specs-go/v1"
 	"golang.org/x/net/context"
 )
 
@@ -55,3 +57,55 @@ func TestServiceCreate(t *testing.T) {
 		t.Fatalf("expected `service_id`, got %s", r.ID)
 	}
 }
+
+func TestServiceCreateCompatiblePlatforms(t *testing.T) {
+	var platforms []v1.Platform
+	client := &Client{
+		client: newMockClient(func(req *http.Request) (*http.Response, error) {
+			if strings.HasPrefix(req.URL.Path, "/services/create") {
+				// platforms should have been resolved by now
+				if len(platforms) != 1 || platforms[0].Architecture != "amd64" || platforms[0].OS != "linux" {
+					return nil, fmt.Errorf("incorrect platform information")
+				}
+				b, err := json.Marshal(types.ServiceCreateResponse{
+					ID: "service_" + platforms[0].Architecture,
+				})
+				if err != nil {
+					return nil, err
+				}
+				return &http.Response{
+					StatusCode: http.StatusOK,
+					Body:       ioutil.NopCloser(bytes.NewReader(b)),
+				}, nil
+			} else if strings.HasPrefix(req.URL.Path, "/distribution/") {
+				platforms = []v1.Platform{
+					{
+						Architecture: "amd64",
+						OS:           "linux",
+					},
+				}
+				b, err := json.Marshal(registrytypes.DistributionInspect{
+					Descriptor: v1.Descriptor{},
+					Platforms:  platforms,
+				})
+				if err != nil {
+					return nil, err
+				}
+				return &http.Response{
+					StatusCode: http.StatusOK,
+					Body:       ioutil.NopCloser(bytes.NewReader(b)),
+				}, nil
+			} else {
+				return nil, fmt.Errorf("unexpected URL '%s'", req.URL.Path)
+			}
+		}),
+	}
+
+	r, err := client.ServiceCreate(context.Background(), swarm.ServiceSpec{}, types.ServiceCreateOptions{QueryRegistry: true})
+	if err != nil {
+		t.Fatal(err)
+	}
+	if r.ID != "service_amd64" {
+		t.Fatalf("expected `service_amd64`, got %s", r.ID)
+	}
+}

+ 2 - 0
client/service_update.go

@@ -46,6 +46,8 @@ func (cli *Client) ServiceUpdate(ctx context.Context, serviceID string, version
 			if img != "" {
 				service.TaskTemplate.ContainerSpec.Image = img
 			}
+			// add platforms that are compatible with the service
+			service.TaskTemplate.Placement = updateServicePlatforms(service.TaskTemplate.Placement, distributionInspect)
 		}
 	}