浏览代码

Allow compose updates without having to delete the stack every time.
Update will “typically” keep the same IP, but this isn’t guaranteed by azure
(ACI has limitations on what can be updated, but this does not apply to us for the moment : https://docs.microsoft.com/en-us/azure/container-instances/container-instances-update#properties-that-require-container-delete)
For the moment I check in the test that the IP is keep the same

Guillaume Tardif 5 年之前
父节点
当前提交
f403307edf
共有 3 个文件被更改,包括 56 次插入8 次删除
  1. 8 0
      azure/aci.go
  2. 1 1
      azure/backend.go
  3. 47 7
      tests/aci-e2e/e2e-aci_test.go

+ 8 - 0
azure/aci.go

@@ -43,6 +43,14 @@ func createACIContainers(ctx context.Context, aciContext store.AciContext, group
 		return fmt.Errorf("container group %q already exists", *groupDefinition.Name)
 	}
 
+	return createOrUpdateACIContainers(ctx, aciContext, groupDefinition)
+}
+
+func createOrUpdateACIContainers(ctx context.Context, aciContext store.AciContext, groupDefinition containerinstance.ContainerGroup) error {
+	containerGroupsClient, err := getContainerGroupsClient(aciContext.SubscriptionID)
+	if err != nil {
+		return errors.Wrapf(err, "cannot get container group client")
+	}
 	future, err := containerGroupsClient.CreateOrUpdate(
 		ctx,
 		aciContext.ResourceGroup,

+ 1 - 1
azure/backend.go

@@ -283,7 +283,7 @@ func (cs *aciComposeService) Up(ctx context.Context, opts compose.ProjectOptions
 	if err != nil {
 		return err
 	}
-	return createACIContainers(ctx, cs.ctx, groupDefinition)
+	return createOrUpdateACIContainers(ctx, cs.ctx, groupDefinition)
 }
 
 func (cs *aciComposeService) Down(ctx context.Context, opts compose.ProjectOptions) error {

+ 47 - 7
tests/aci-e2e/e2e-aci_test.go

@@ -3,7 +3,9 @@ package main
 import (
 	"context"
 	"fmt"
+	"io/ioutil"
 	"net/url"
+	"os"
 	"strings"
 	"testing"
 
@@ -122,8 +124,11 @@ func (s *E2eACISuite) TestACIBackend() {
 		Expect(Lines(output)[0]).To(Equal(testContainerName))
 	})
 
+	var exposedURL string
+	const composeFile = "../composefiles/aci-demo/aci_demo_port.yaml"
+	const serverContainer = "acidemo_web"
 	It("deploys a compose app", func() {
-		s.NewDockerCommand("compose", "up", "-f", "../composefiles/aci-demo/aci_demo_port.yaml", "--project-name", "acidemo").ExecOrDie()
+		s.NewDockerCommand("compose", "up", "-f", composeFile, "--project-name", "acidemo").ExecOrDie()
 		// Expect(output).To(ContainSubstring("Successfully deployed"))
 		output := s.NewDockerCommand("ps").ExecOrDie()
 		Lines := Lines(output)
@@ -132,16 +137,16 @@ func (s *E2eACISuite) TestACIBackend() {
 
 		for _, line := range Lines[1:] {
 			Expect(line).To(ContainSubstring("Running"))
-			if strings.Contains(line, "acidemo_web") {
+			if strings.Contains(line, serverContainer) {
 				webChecked = true
 				containerFields := Columns(line)
 				exposedIP := containerFields[3]
 				Expect(exposedIP).To(ContainSubstring(":80->80/tcp"))
 
-				url := strings.ReplaceAll(exposedIP, "->80/tcp", "")
-				output = s.NewCommand("curl", url).ExecOrDie()
+				exposedURL = strings.ReplaceAll(exposedIP, "->80/tcp", "")
+				output = s.NewCommand("curl", exposedURL).ExecOrDie()
 				Expect(output).To(ContainSubstring("Docker Compose demo"))
-				output = s.NewCommand("curl", url+"/words/noun").ExecOrDie()
+				output = s.NewCommand("curl", exposedURL+"/words/noun").ExecOrDie()
 				Expect(output).To(ContainSubstring("\"word\":"))
 			}
 		}
@@ -150,12 +155,47 @@ func (s *E2eACISuite) TestACIBackend() {
 	})
 
 	It("get logs from web service", func() {
-		output := s.NewDockerCommand("logs", "acidemo_web").ExecOrDie()
+		output := s.NewDockerCommand("logs", serverContainer).ExecOrDie()
 		Expect(output).To(ContainSubstring("Listening on port 80"))
 	})
 
+	It("updates a compose app", func() {
+		input, err := ioutil.ReadFile(composeFile)
+		Expect(err).To(BeNil())
+		modifiedInput := strings.Replace(string(input), "web:", "webserver:", 1)
+		modifiedComposeFile := strings.Replace(composeFile, ".yaml", "-modified.yaml", 1)
+		err = ioutil.WriteFile(modifiedComposeFile, []byte(modifiedInput), 0644)
+		Expect(err).To(BeNil())
+		defer func() {
+			err := os.Remove(modifiedComposeFile)
+			Expect(err).To(BeNil())
+		}()
+
+		s.NewDockerCommand("compose", "up", "-f", modifiedComposeFile, "--project-name", "acidemo").ExecOrDie()
+		// Expect(output).To(ContainSubstring("Successfully deployed"))
+		output := s.NewDockerCommand("ps").ExecOrDie()
+		Lines := Lines(output)
+		Expect(len(Lines)).To(Equal(4))
+		webChecked := false
+
+		for _, line := range Lines[1:] {
+			Expect(line).To(ContainSubstring("Running"))
+			if strings.Contains(line, serverContainer+"server") {
+				webChecked = true
+				containerFields := Columns(line)
+				exposedIP := containerFields[3]
+				Expect(exposedIP).To(ContainSubstring(":80->80/tcp"))
+
+				url := strings.ReplaceAll(exposedIP, "->80/tcp", "")
+				Expect(exposedURL).To(Equal(url))
+			}
+		}
+
+		Expect(webChecked).To(BeTrue())
+	})
+
 	It("shutdown compose app", func() {
-		s.NewDockerCommand("compose", "down", "-f", "../composefiles/aci-demo/aci_demo_port.yaml", "--project-name", "acidemo").ExecOrDie()
+		s.NewDockerCommand("compose", "down", "-f", composeFile, "--project-name", "acidemo").ExecOrDie()
 	})
 	It("switches back to default context", func() {
 		output := s.NewCommand("docker", "context", "use", "default").ExecOrDie()