Pārlūkot izejas kodu

Added aci e2e tests, not run in CI since requiring azure login.
Need a `docker rm` command to add nginx e2e test, and compose sample to follow

Guillaume Tardif 5 gadi atpakaļ
vecāks
revīzija
eb712ac75f
6 mainītis faili ar 265 papildinājumiem un 66 dzēšanām
  1. 2 0
      .golangci.yml
  2. 3 0
      Makefile
  3. 32 0
      azure/aci.go
  4. 151 0
      tests/aci-e2e/e2e-aci.go
  5. 38 66
      tests/e2e/e2e.go
  6. 39 0
      tests/framework/helper.go

+ 2 - 0
.golangci.yml

@@ -33,3 +33,5 @@ issues:
   # golangci hides some golint warnings (the warning about exported things
   # withtout documentation for example), this will make it show them anyway.
   exclude-use-default: false
+  exclude:
+    - should not use dot imports

+ 3 - 0
Makefile

@@ -44,6 +44,9 @@ cli: ## Compile the cli
 e2e-local: ## Run End to end local tests
 	go run ./tests/e2e/e2e.go
 
+e2e-aci: ## Run End to end ACI tests (requires azure login)
+	go run ./tests/aci-e2e/e2e-aci.go
+
 cross: ## Compile the CLI for linux, darwin and windows
 	@docker build . \
 	--output type=local,dest=./bin \

+ 32 - 0
azure/aci.go

@@ -10,6 +10,8 @@ import (
 	"strings"
 	"time"
 
+	"github.com/Azure/azure-sdk-for-go/profiles/2019-03-01/resources/mgmt/resources"
+	"github.com/Azure/azure-sdk-for-go/profiles/preview/preview/subscription/mgmt/subscription"
 	"github.com/Azure/azure-sdk-for-go/services/containerinstance/mgmt/2018-10-01/containerinstance"
 	"github.com/Azure/azure-sdk-for-go/services/keyvault/auth"
 	"github.com/Azure/go-autorest/autorest"
@@ -261,3 +263,33 @@ func getContainerClient(subscriptionID string) (containerinstance.ContainerClien
 	containerClient.Authorizer = auth
 	return containerClient, nil
 }
+
+func getSubscriptionsClient() subscription.SubscriptionsClient {
+	subc := subscription.NewSubscriptionsClient()
+	authorizer, _ := auth.NewAuthorizerFromCLI()
+	subc.Authorizer = authorizer
+	return subc
+}
+
+//GetGroupsClient ...
+func GetGroupsClient(subscriptionID string) resources.GroupsClient {
+	groupsClient := resources.NewGroupsClient(subscriptionID)
+	authorizer, _ := auth.NewAuthorizerFromCLI()
+	groupsClient.Authorizer = authorizer
+	return groupsClient
+}
+
+//GetSubscriptionID ...
+func GetSubscriptionID(ctx context.Context) (string, error) {
+	c := getSubscriptionsClient()
+	res, err := c.List(ctx)
+	if err != nil {
+		return "", err
+	}
+	subs := res.Values()
+	if len(subs) == 0 {
+		return "", errors.New("no subscriptions found")
+	}
+	sub := subs[0]
+	return *sub.SubscriptionID, nil
+}

+ 151 - 0
tests/aci-e2e/e2e-aci.go

@@ -0,0 +1,151 @@
+package main
+
+import (
+	"context"
+	"log"
+
+	"github.com/Azure/azure-sdk-for-go/profiles/2019-03-01/resources/mgmt/resources"
+	"github.com/docker/api/azure"
+	. "github.com/docker/api/tests/framework"
+	. "github.com/onsi/gomega"
+)
+
+const resourceGroupName = "resourceGroupTest"
+
+var location = "westeurope"
+
+const contextName = "acitest"
+
+func main() {
+	SetupTest()
+
+	It("ensures context command includes azure-login and aci-create", func() {
+		output := NewDockerCommand("context", "create", "--help").ExecOrDie()
+		Expect(output).To(ContainSubstring("docker context create CONTEXT BACKEND [OPTIONS] [flags]"))
+		Expect(output).To(ContainSubstring("--aci-location"))
+		Expect(output).To(ContainSubstring("--aci-subscription-id"))
+		Expect(output).To(ContainSubstring("--aci-resource-group"))
+	})
+
+	It("should be initialized with default context", func() {
+		NewCommand("docker", "context", "use", "default").ExecOrDie()
+		output := NewCommand("docker", "context", "ls").ExecOrDie()
+		Expect(output).To(Not(ContainSubstring(contextName)))
+		Expect(output).To(ContainSubstring("default *"))
+	})
+
+	It("creates a new aci context for tests", func() {
+		setupTestResourecGroup(resourceGroupName)
+		subscriptionID, err := azure.GetSubscriptionID(context.TODO())
+		Expect(err).To(BeNil())
+
+		NewDockerCommand("context", "create", contextName, "aci", "--aci-subscription-id", subscriptionID, "--aci-resource-group", resourceGroupName, "--aci-location", location).ExecOrDie()
+		//Expect(output).To(ContainSubstring("ACI context acitest created"))
+	})
+
+	defer deleteResourceGroup(resourceGroupName)
+
+	It("uses the aci context", func() {
+		currentContext := NewCommand("docker", "context", "use", contextName).ExecOrDie()
+		Expect(currentContext).To(ContainSubstring(contextName))
+		output := NewCommand("docker", "context", "ls").ExecOrDie()
+		Expect(output).To(ContainSubstring("acitest *"))
+	})
+
+	It("ensures no container is running initially", func() {
+		output := NewDockerCommand("ps").ExecOrDie()
+		Expect(len(Lines(output))).To(Equal(1))
+	})
+
+	/*
+		var nginxID string
+		It("runs nginx on port 80", func() {
+			NewDockerCommand("run", "nginx", "-p", "80:80").ExecOrDie()
+			output := NewDockerCommand("ps").ExecOrDie()
+			Lines := Lines(output)
+			Expect(len(Lines)).To(Equal(2))
+
+			containerFields := Columns(Lines[1])
+			nginxID = containerFields[0]
+			Expect(containerFields[1]).To(Equal("nginx"))
+			Expect(containerFields[2]).To(Equal("Running"))
+			exposedIP := containerFields[3]
+			Expect(exposedIP).To(ContainSubstring(":80->80/TCP"))
+
+			url := strings.ReplaceAll(exposedIP, "->80/TCP", "")
+			output = NewCommand("curl", url).ExecOrDie()
+			Expect(output).To(ContainSubstring("Welcome to nginx!"))
+		})
+
+		It("removes container nginx", func() {
+			output := NewDockerCommand("rm", nginxID).ExecOrDie()
+			Expect(Lines(output)[0]).To(Equal(nginxID))
+		})
+	*/
+
+	/*
+		It("deploys a compose app", func() {
+			output := NewDockerCommand("compose", "up", "-f", "./composefiles/aci_demo_ports_secrets_volumes/aci_demo_port.yaml", "-n", "acicompose").ExecOrDie()
+			Expect(output).To(ContainSubstring("Successfully deployed"))
+			output = NewDockerCommand("ps").ExecOrDie()
+			Lines := Lines(output)
+			Expect(len(Lines)).To(Equal(4))
+			var webChecked = false
+			for _, line := range Lines {
+				if strings.Contains(line, "acicompose_web") {
+					webChecked = true
+					containerFields := Columns(line)
+					exposedIP := containerFields[3]
+					Expect(exposedIP).To(ContainSubstring(":80->80/TCP"))
+
+					url := strings.ReplaceAll(exposedIP, "->80/TCP", "")
+					output = NewCommand("curl", url).ExecOrDie()
+					Expect(output).To(ContainSubstring("Docker Compose demo"))
+					output = NewCommand("curl", url+"/words/noun").ExecOrDie()
+					Expect(output).To(ContainSubstring("\"word\":"))
+				}
+			}
+			Expect(webChecked).To(BeTrue())
+		})
+
+		It("get logs from web service", func() {
+			output := NewDockerCommand("logs", "acicompose_web").ExecOrDie()
+			Expect(output).To(ContainSubstring("Calling http://127.0.0.1:8080/noun"))
+		})
+
+		It("shutdown compose app", func() {
+			NewDockerCommand("compose", "down", "-f", "./composefiles/aci_demo_ports_secrets_volumes/aci_demo_port.yaml", "-n", "acicompose").ExecOrDie()
+		})
+	*/
+	It("switches back to default context", func() {
+		output := NewCommand("docker", "context", "use", "default").ExecOrDie()
+		Expect(output).To(ContainSubstring("default"))
+	})
+
+	It("deletes test context", func() {
+		output := NewCommand("docker", "context", "rm", contextName).ExecOrDie()
+		Expect(output).To(ContainSubstring(contextName))
+	})
+}
+
+func setupTestResourecGroup(groupName string) {
+	log.Println("Creating resource group " + resourceGroupName)
+	ctx := context.TODO()
+	subscriptionID, err := azure.GetSubscriptionID(ctx)
+	Expect(err).To(BeNil())
+	gc := azure.GetGroupsClient(subscriptionID)
+	_, err = gc.CreateOrUpdate(ctx, groupName, resources.Group{
+		Location: &location,
+	})
+	Expect(err).To(BeNil())
+}
+
+func deleteResourceGroup(groupName string) {
+	log.Println("Deleting resource group " + resourceGroupName)
+	ctx := context.TODO()
+	subscriptionID, err := azure.GetSubscriptionID(ctx)
+	Expect(err).To(BeNil())
+	gc := azure.GetGroupsClient(subscriptionID)
+	_, err = gc.Delete(ctx, groupName)
+	Expect(err).To(BeNil())
+}

+ 38 - 66
tests/e2e/e2e.go

@@ -1,107 +1,79 @@
 package main
 
 import (
-	"log"
-	"strings"
 	"time"
-
-	"github.com/robpike/filter"
-
-	g "github.com/onsi/gomega"
-
-	f "github.com/docker/api/tests/framework"
+	. "github.com/docker/api/tests/framework"
+	. "github.com/onsi/gomega"
 )
 
 func main() {
-	setup()
+	SetupTest()
 
 	It("ensures context command includes azure-login and aci-create", func() {
-		output := f.NewDockerCommand("context", "create", "--help").ExecOrDie()
-		g.Expect(output).To(g.ContainSubstring("docker context create CONTEXT BACKEND [OPTIONS] [flags]"))
-		g.Expect(output).To(g.ContainSubstring("--aci-location"))
-		g.Expect(output).To(g.ContainSubstring("--aci-subscription-id"))
-		g.Expect(output).To(g.ContainSubstring("--aci-resource-group"))
+		output := NewDockerCommand("context", "create", "--help").ExecOrDie()
+		Expect(output).To(ContainSubstring("docker context create CONTEXT BACKEND [OPTIONS] [flags]"))
+		Expect(output).To(ContainSubstring("--aci-location"))
+		Expect(output).To(ContainSubstring("--aci-subscription-id"))
+		Expect(output).To(ContainSubstring("--aci-resource-group"))
 	})
 
 	It("should be initialized with default context", func() {
-		f.NewCommand("docker", "context", "use", "default").ExecOrDie()
-		output := f.NewCommand("docker", "context", "ls").ExecOrDie()
-		g.Expect(output).To(g.ContainSubstring("default *"))
+		NewCommand("docker", "context", "use", "default").ExecOrDie()
+		output := NewCommand("docker", "context", "ls").ExecOrDie()
+		Expect(output).To(ContainSubstring("default *"))
 	})
 
 	It("should list all legacy commands", func() {
-		output := f.NewDockerCommand("--help").ExecOrDie()
-		g.Expect(output).To(g.ContainSubstring("swarm"))
+		output := NewDockerCommand("--help").ExecOrDie()
+		Expect(output).To(ContainSubstring("swarm"))
 	})
 
 	It("should execute legacy commands", func() {
-		output, _ := f.NewDockerCommand("swarm", "join").Exec()
-		g.Expect(output).To(g.ContainSubstring("\"docker swarm join\" requires exactly 1 argument."))
+		output, _ := NewDockerCommand("swarm", "join").Exec()
+		Expect(output).To(ContainSubstring("\"docker swarm join\" requires exactly 1 argument."))
 	})
 
 	It("should run local container in less than 2 secs", func() {
-		f.NewDockerCommand("pull", "hello-world").ExecOrDie()
-		output := f.NewDockerCommand("run", "hello-world").WithTimeout(time.NewTimer(2 * time.Second).C).ExecOrDie()
-		g.Expect(output).To(g.ContainSubstring("Hello from Docker!"))
+		NewDockerCommand("pull", "hello-world").ExecOrDie()
+		output := NewDockerCommand("run", "hello-world").WithTimeout(time.NewTimer(2 * time.Second).C).ExecOrDie()
+		Expect(output).To(ContainSubstring("Hello from Docker!"))
 	})
 
 	It("should list local container", func() {
-		output := f.NewDockerCommand("ps", "-a").ExecOrDie()
-		g.Expect(output).To(g.ContainSubstring("hello-world"))
+		output := NewDockerCommand("ps", "-a").ExecOrDie()
+		Expect(output).To(ContainSubstring("hello-world"))
 	})
 
 	It("creates a new test context to hardcoded example backend", func() {
-		f.NewDockerCommand("context", "create", "test-example", "example").ExecOrDie()
-		//g.Expect(output).To(g.ContainSubstring("test-example context acitest created"))
+		NewDockerCommand("context", "create", "test-example", "example").ExecOrDie()
+		//Expect(output).To(ContainSubstring("test-example context acitest created"))
 	})
-	defer f.NewCommand("docker", "context", "rm", "test-example", "-f").ExecOrDie()
+	defer NewCommand("docker", "context", "rm", "test-example", "-f").ExecOrDie()
 
 	It("uses the test context", func() {
-		currentContext := f.NewCommand("docker", "context", "use", "test-example").ExecOrDie()
-		g.Expect(currentContext).To(g.ContainSubstring("test-example"))
-		output := f.NewCommand("docker", "context", "ls").ExecOrDie()
-		g.Expect(output).To(g.ContainSubstring("test-example *"))
+		currentContext := NewCommand("docker", "context", "use", "test-example").ExecOrDie()
+		Expect(currentContext).To(ContainSubstring("test-example"))
+		output := NewCommand("docker", "context", "ls").ExecOrDie()
+		Expect(output).To(ContainSubstring("test-example *"))
 	})
 
 	It("can run ps command", func() {
-		output := f.NewDockerCommand("ps").ExecOrDie()
-		lines := lines(output)
-		g.Expect(len(lines)).To(g.Equal(3))
-		g.Expect(lines[2]).To(g.ContainSubstring("1234  alpine"))
+		output := NewDockerCommand("ps").ExecOrDie()
+		lines := Lines(output)
+		Expect(len(lines)).To(Equal(3))
+		Expect(lines[2]).To(ContainSubstring("1234  alpine"))
 	})
 
 	It("can run quiet ps command", func() {
-		output := f.NewDockerCommand("ps", "-q").ExecOrDie()
-		lines := lines(output)
-		g.Expect(len(lines)).To(g.Equal(2))
-		g.Expect(lines[0]).To(g.Equal("id"))
-		g.Expect(lines[1]).To(g.Equal("1234"))
+		output := NewDockerCommand("ps", "-q").ExecOrDie()
+		lines := Lines(output)
+		Expect(len(lines)).To(Equal(2))
+		Expect(lines[0]).To(Equal("id"))
+		Expect(lines[1]).To(Equal("1234"))
 	})
 
 	It("can run 'run' command", func() {
-		output := f.NewDockerCommand("run", "nginx", "-p", "80:80").ExecOrDie()
-		g.Expect(output).To(g.ContainSubstring("Running container \"nginx\" with name"))
+		output := NewDockerCommand("run", "nginx", "-p", "80:80").ExecOrDie()
+		Expect(output).To(ContainSubstring("Running container \"nginx\" with name"))
 	})
 }
-
-func nonEmptyString(s string) bool {
-	return strings.TrimSpace(s) != ""
-}
-
-func lines(output string) []string {
-	return filter.Choose(strings.Split(output, "\n"), nonEmptyString).([]string)
-}
-
-// It runs func
-func It(description string, test func()) {
-	test()
-	log.Print("Passed: ", description)
-}
-
-func gomegaFailHandler(message string, callerSkip ...int) {
-	log.Fatal(message)
-}
-
-func setup() {
-	g.RegisterFailHandler(gomegaFailHandler)
-}

+ 39 - 0
tests/framework/helper.go

@@ -0,0 +1,39 @@
+package framework
+
+import (
+	"log"
+	"strings"
+
+	"github.com/robpike/filter"
+
+	"github.com/onsi/gomega"
+)
+
+func nonEmptyString(s string) bool {
+	return strings.TrimSpace(s) != ""
+}
+
+//Lines get lines from a raw string
+func Lines(output string) []string {
+	return filter.Choose(strings.Split(output, "\n"), nonEmptyString).([]string)
+}
+
+//Columns get columns from a line
+func Columns(line string) []string {
+	return filter.Choose(strings.Split(line, " "), nonEmptyString).([]string)
+}
+
+// It runs func
+func It(description string, test func()) {
+	test()
+	log.Print("Passed: ", description)
+}
+
+func gomegaFailHandler(message string, callerSkip ...int) {
+	log.Fatal(message)
+}
+
+//SetupTest Init gomega fail handler
+func SetupTest() {
+	gomega.RegisterFailHandler(gomegaFailHandler)
+}