From e323be8f556364650046fd75db23e19d2470a3e5 Mon Sep 17 00:00:00 2001 From: Manuel Vogel Date: Fri, 31 May 2019 15:08:32 +0200 Subject: [PATCH] Fixes for flaky tests (#154) * adds delay for fetching auth config * refactor registry auth retrieval. adds retry if not found * reactivates full build in script and travis --- docker/resource_docker_service_funcs.go | 44 +++++++++++++---------- docker/resource_docker_service_test.go | 46 ++++++++++++------------- scripts/runAccTests.sh | 2 +- 3 files changed, 50 insertions(+), 42 deletions(-) diff --git a/docker/resource_docker_service_funcs.go b/docker/resource_docker_service_funcs.go index 7e95a16d..4abc334a 100644 --- a/docker/resource_docker_service_funcs.go +++ b/docker/resource_docker_service_funcs.go @@ -58,16 +58,7 @@ func resourceDockerServiceCreate(d *schema.ResourceData, meta interface{}) error } serviceOptions := types.ServiceCreateOptions{} - auth := types.AuthConfig{} - if v, ok := d.GetOk("auth"); ok { - auth = authToServiceAuth(v.(map[string]interface{})) - } else { - authConfigs := meta.(*ProviderConfig).AuthConfigs.Configs - log.Printf("[DEBUG] Getting configs from '%v'", authConfigs) - auth = fromRegistryAuth(d.Get("task_spec.0.container_spec.0.image").(string), authConfigs) - } - - marshalledAuth, _ := json.Marshal(auth) // https://docs.docker.com/engine/api/v1.37/#section/Versioning + marshalledAuth := retrieveAndMarshalAuth(d, meta, "create") serviceOptions.EncodedRegistryAuth = base64.URLEncoding.EncodeToString(marshalledAuth) serviceOptions.QueryRegistry = true log.Printf("[DEBUG] Passing registry auth '%s'", serviceOptions.EncodedRegistryAuth) @@ -162,17 +153,11 @@ func resourceDockerServiceUpdate(d *schema.ResourceData, meta interface{}) error } updateOptions := types.ServiceUpdateOptions{} - auth := types.AuthConfig{} - if v, ok := d.GetOk("auth"); ok { - auth = authToServiceAuth(v.(map[string]interface{})) - } else { - auth = fromRegistryAuth(d.Get("task_spec.0.container_spec.0.image").(string), meta.(*ProviderConfig).AuthConfigs.Configs) - } - encodedJSON, err := json.Marshal(auth) + marshalledAuth := retrieveAndMarshalAuth(d, meta, "update") if err != nil { return fmt.Errorf("error creating auth config: %s", err) } - updateOptions.EncodedRegistryAuth = base64.URLEncoding.EncodeToString(encodedJSON) + updateOptions.EncodedRegistryAuth = base64.URLEncoding.EncodeToString(marshalledAuth) updateResponse, err := client.ServiceUpdate(context.Background(), d.Id(), service.Version, serviceSpec, updateOptions) if err != nil { @@ -1302,6 +1287,29 @@ func fromRegistryAuth(image string, authConfigs map[string]types.AuthConfig) typ return types.AuthConfig{} } +// retrieveAndMarshalAuth retrieves and marshals the service registry auth +func retrieveAndMarshalAuth(d *schema.ResourceData, meta interface{}, stageType string) []byte { + auth := types.AuthConfig{} + if v, ok := d.GetOk("auth"); ok { + auth = authToServiceAuth(v.(map[string]interface{})) + } else { + authConfigs := meta.(*ProviderConfig).AuthConfigs.Configs + if len(authConfigs) == 0 { + log.Printf("[DEBUG] AuthConfigs empty on %s. Wait 3s and try again", stageType) + // sometimes the dockerconfig is read succesfully from disk but the + // call to create/update the service is faster. So we delay to prevent the + // passing of an empty auth configuration in this case + <-time.After(3 * time.Second) + authConfigs = meta.(*ProviderConfig).AuthConfigs.Configs + } + log.Printf("[DEBUG] Getting configs from '%v'", authConfigs) + auth = fromRegistryAuth(d.Get("task_spec.0.container_spec.0.image").(string), authConfigs) + } + + marshalledAuth, _ := json.Marshal(auth) // https://docs.docker.com/engine/api/v1.37/#section/Versioning + return marshalledAuth +} + // stringSetToPlacementPrefs maps a string set to PlacementPreference func stringSetToPlacementPrefs(stringSet *schema.Set) []swarm.PlacementPreference { ret := []swarm.PlacementPreference{} diff --git a/docker/resource_docker_service_test.go b/docker/resource_docker_service_test.go index 80fe24d8..749f58b5 100644 --- a/docker/resource_docker_service_test.go +++ b/docker/resource_docker_service_test.go @@ -685,7 +685,7 @@ func TestAccDockerService_ConflictingGlobalModeAndConverge(t *testing.T) { // Converging tests func TestAccDockerService_privateImageConverge(t *testing.T) { registry := "127.0.0.1:15000" - image := "127.0.0.1:15000/tftest-service" + image := "127.0.0.1:15000/tftest-service:v1" resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, @@ -723,7 +723,7 @@ func TestAccDockerService_privateImageConverge(t *testing.T) { Check: resource.ComposeTestCheckFunc( resource.TestMatchResourceAttr("docker_service.bar", "id", serviceIDRegex), resource.TestCheckResourceAttr("docker_service.bar", "name", "tftest-service-bar"), - resource.TestMatchResourceAttr("docker_service.bar", "task_spec.0.container_spec.0.image", regexp.MustCompile(`127.0.0.1:15000/tftest-service:latest@sha256.*`)), + resource.TestMatchResourceAttr("docker_service.bar", "task_spec.0.container_spec.0.image", regexp.MustCompile(`127.0.0.1:15000/tftest-service:v1@sha256.*`)), ), }, }, @@ -854,11 +854,11 @@ func TestAccDockerService_updateMultiplePropertiesConverge(t *testing.T) { resource.TestCheckResourceAttr("docker_service.foo", "name", "tftest-fnf-service-up-crihiadr"), resource.TestMatchResourceAttr("docker_service.foo", "task_spec.0.container_spec.0.image", regexp.MustCompile(`127.0.0.1:15000/tftest-service:v1@sha256.*`)), resource.TestCheckResourceAttr("docker_service.foo", "mode.0.replicated.0.replicas", strconv.Itoa(replicas)), - resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.parallelism", "1"), - resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.delay", "1s"), - resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.failure_action", "pause"), - resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.monitor", "1s"), - resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.max_failure_ratio", "0.1"), + resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.parallelism", "2"), + resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.delay", "3s"), + resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.failure_action", "continue"), + resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.monitor", "3s"), + resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.max_failure_ratio", "0.5"), resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.order", "start-first"), resource.TestCheckResourceAttr("docker_service.foo", "endpoint_spec.0.ports.#", "1"), resource.TestCheckResourceAttr("docker_service.foo", "endpoint_spec.0.ports.3541714906.target_port", "8080"), @@ -900,11 +900,11 @@ func TestAccDockerService_updateMultiplePropertiesConverge(t *testing.T) { resource.TestCheckResourceAttr("docker_service.foo", "name", "tftest-fnf-service-up-crihiadr"), resource.TestMatchResourceAttr("docker_service.foo", "task_spec.0.container_spec.0.image", regexp.MustCompile(`127.0.0.1:15000/tftest-service:v2.*`)), resource.TestCheckResourceAttr("docker_service.foo", "mode.0.replicated.0.replicas", strconv.Itoa(replicas2)), - resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.parallelism", "1"), - resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.delay", "1s"), - resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.failure_action", "pause"), - resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.monitor", "1s"), - resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.max_failure_ratio", "0.1"), + resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.parallelism", "2"), + resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.delay", "3s"), + resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.failure_action", "continue"), + resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.monitor", "3s"), + resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.max_failure_ratio", "0.5"), resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.order", "start-first"), resource.TestCheckResourceAttr("docker_service.foo", "endpoint_spec.0.ports.#", "2"), resource.TestCheckResourceAttr("docker_service.foo", "endpoint_spec.0.ports.3541714906.target_port", "8080"), @@ -948,11 +948,11 @@ func TestAccDockerService_updateMultiplePropertiesConverge(t *testing.T) { resource.TestCheckResourceAttr("docker_service.foo", "name", "tftest-fnf-service-up-crihiadr"), resource.TestMatchResourceAttr("docker_service.foo", "task_spec.0.container_spec.0.image", regexp.MustCompile(`127.0.0.1:15000/tftest-service:v2.*`)), resource.TestCheckResourceAttr("docker_service.foo", "mode.0.replicated.0.replicas", strconv.Itoa(replicas3)), - resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.parallelism", "1"), - resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.delay", "1s"), - resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.failure_action", "pause"), - resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.monitor", "1s"), - resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.max_failure_ratio", "0.1"), + resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.parallelism", "2"), + resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.delay", "3s"), + resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.failure_action", "continue"), + resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.monitor", "3s"), + resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.max_failure_ratio", "0.5"), resource.TestCheckResourceAttr("docker_service.foo", "update_config.0.order", "start-first"), resource.TestCheckResourceAttr("docker_service.foo", "endpoint_spec.0.ports.#", "2"), resource.TestCheckResourceAttr("docker_service.foo", "endpoint_spec.0.ports.3541714906.target_port", "8080"), @@ -1251,11 +1251,11 @@ resource "docker_service" "foo" { } update_config { - parallelism = 1 - delay = "1s" - failure_action = "pause" - monitor = "1s" - max_failure_ratio = "0.1" + parallelism = 2 + delay = "3s" + failure_action = "continue" + monitor = "3s" + max_failure_ratio = "0.5" order = "start-first" } @@ -1267,7 +1267,7 @@ resource "docker_service" "foo" { converge_config { delay = "7s" - timeout = "3m" + timeout = "2m" } } ` diff --git a/scripts/runAccTests.sh b/scripts/runAccTests.sh index 4629fd6d..8e53b468 100755 --- a/scripts/runAccTests.sh +++ b/scripts/runAccTests.sh @@ -52,7 +52,7 @@ run() { TF_ACC=1 go test ./docker -v -timeout 120m # for a single test comment the previous line and uncomment the next line - #TF_LOG=INFO TF_ACC=1 go test -v ./docker -run ^TestAccDockerImage_data_private_config_file$ -timeout 360s + #TF_LOG=DEBUG TF_ACC=1 go test -v ./docker -run ^TestAccDockerService_updateMultiplePropertiesConverge$ -timeout 360s # keep the return value for the scripts to fail and clean properly return $?