From 51744f3958c92483eca82ae93b11dff47de73579 Mon Sep 17 00:00:00 2001 From: Antoine Mercadal Date: Tue, 9 Jul 2019 12:02:26 -0700 Subject: [PATCH] new: removed deprecated package updatesync and magetask --- magetask/common.go | 391 ---------------------------------- magetask/doc.go | 13 -- magetask/libver.go | 114 ---------- magetask/templates.go | 89 -------- magetask/utils.go | 79 ------- updatesync/doc.go | 13 -- updatesync/updatesync.go | 83 -------- updatesync/updatesync_test.go | 189 ---------------- 8 files changed, 971 deletions(-) delete mode 100644 magetask/common.go delete mode 100644 magetask/doc.go delete mode 100644 magetask/libver.go delete mode 100644 magetask/templates.go delete mode 100644 magetask/utils.go delete mode 100644 updatesync/doc.go delete mode 100644 updatesync/updatesync.go delete mode 100644 updatesync/updatesync_test.go diff --git a/magetask/common.go b/magetask/common.go deleted file mode 100644 index fdeeb3d..0000000 --- a/magetask/common.go +++ /dev/null @@ -1,391 +0,0 @@ -// Copyright 2019 Aporeto Inc. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package magetask - -import ( - "fmt" - "io" - "io/ioutil" - "os" - "path" - "path/filepath" - "strings" - - "github.com/magefile/mage/sh" - "golang.org/x/sync/errgroup" -) - -var projectName string - -func init() { - - wd, err := os.Getwd() - if err != nil { - panic(err) - } - - projectName = path.Base(wd) -} - -// SetProjectName sets the name of the project. -func SetProjectName(name string) { - projectName = name -} - -// WriteVersion creates the version file if needed. -func WriteVersion() error { - - return WriteVersionIn("") -} - -// GetSemver gets the semantic version of the repository -func GetSemver() (sver string, err error) { - - if sver = os.Getenv("PROJECT_VERSION"); sver == "" { - return "", fmt.Errorf("unable to find project version") - } - - return -} - -// WriteVersionIn creates the version file if needed in the given folder. -func WriteVersionIn(out string) (err error) { - - projectSha := "" - projectVersion := "" - - if projectSha = os.Getenv("PROJECT_SHA"); projectSha == "" { - return fmt.Errorf("unable to find project SHA") - } - - projectVersion, err = GetSemver() - if err != nil { - return err - } - - if _, err := os.Stat("./Gopkg.toml"); err == nil { - if err := makeVersionFromDep("", out, projectVersion, projectSha); err != nil { - return err - } - } - - fmt.Println("complete: versions file generation") - return nil -} - -// Lint runs the linters. -func Lint() error { - - if err := run( - nil, - "gometalinter", - "--exclude", - "bindata.go", - "--exclude", - "vendor", - "--vendor", - "--disable-all", - "--enable", - "vet", - "--enable", - "vetshadow", - "--enable", - "golint", - "--enable", - "ineffassign", - "--enable", - "goconst", - "--enable", - "errcheck", - "--enable", - "varcheck", - "--enable", - "structcheck", - "--enable", - "gosimple", - "--enable", - "misspell", - "--enable", - "deadcode", - "--enable", - "staticcheck", - "--deadline", - "30m", - "--tests", - "./...", - ); err != nil { - return err - } - - fmt.Println("complete: linters") - return nil -} - -// Test runs unit tests. -func Test() error { - return TestWith(true, true) -} - -// Build builds the project for the current machine. -func Build() error { - - env := map[string]string{ - "CGO_ENABLED": "0", - } - - if err := run(env, "go", "build", "-a", "-installsuffix", "cgo"); err != nil { - return err - } - - fmt.Println("complete: default build") - return nil -} - -// BuildLinux builds the project for Linux. -func BuildLinux() error { - - env := map[string]string{ - "CGO_ENABLED": "0", - "GOOS": "linux", - "GOARCH": "amd64", - } - - if err := run(env, "go", "build", "-a", "-installsuffix", "cgo"); err != nil { - return err - } - - fmt.Println("complete: linux build") - return nil -} - -// BuildWindows builds the project for Windows. -func BuildWindows() error { - - env := map[string]string{ - "CGO_ENABLED": "0", - "GOOS": "windows", - "GOARCH": "amd64", - } - - if err := run(env, "go", "build", "-a", "-installsuffix", "cgo"); err != nil { - return err - } - - fmt.Println("complete: windows build") - return nil -} - -// BuildDarwin builds the project for macOS. -func BuildDarwin() error { - - env := map[string]string{ - "CGO_ENABLED": "0", - "GOOS": "darwin", - "GOARCH": "amd64", - } - - if err := run(env, "go", "build", "-a", "-installsuffix", "cgo"); err != nil { - return err - } - - fmt.Println("complete: darwin build") - return nil -} - -// BuildFor builds a a cli for the given platform. -func BuildFor(platform string, buildFunc func() error) error { - - if err := os.MkdirAll("./build/"+platform, 0755); err != nil { - return err - } - - if err := buildFunc(); err != nil { - return err - } - - return sh.Run("mv", projectName, "build/"+platform+"/"+projectName) -} - -// Package packages the project for docker build. -func Package() error { - - return PackageFrom(projectName) -} - -// PackageFrom packages the given binary for docker build -func PackageFrom(path string) error { - - if err := os.MkdirAll("docker/app", 0755); err != nil { - return err - } - - if err := run(nil, "cp", "-a", path, "docker/app"); err != nil { - return err - } - - fmt.Println("complete: docker packaging") - return nil -} - -// Container creates the docker container. -func Container() error { - - image := fmt.Sprintf("gcr.io/aporetodev/%s", projectName) - - if tag := os.Getenv("DOMINGO_DOCKER_TAG"); tag != "" { - image = image + ":" + tag - } - - if err := os.MkdirAll("docker/app", 0755); err != nil { - return err - } - - if err := os.Chdir("docker"); err != nil { - return err - } - - defer os.Chdir("..") // nolint - - out, err := sh.Output("docker", "build", "-t", image, ".") - if err != nil { - fmt.Println(out) - return err - } - - fmt.Println("complete: docker build", image) - return nil -} - -// PackageCACerts retrieves the package the CA for docker. -func PackageCACerts() error { - - if err := run(nil, "go", "get", "-u", "github.com/agl/extract-nss-root-certs"); err != nil { - return err - } - - if err := run(nil, "curl", "-s", "https://hg.mozilla.org/mozilla-central/raw-file/tip/security/nss/lib/ckfw/builtins/certdata.txt", "-o", "certdata.txt"); err != nil { - return err - } - - if err := os.MkdirAll("docker/app", 0755); err != nil { - return err - } - - out, err := sh.Output("extract-nss-root-certs") - if err != nil { - return nil - } - - if err := ioutil.WriteFile("docker/app/ca-certificates.pem", []byte(out), 0644); err != nil { - return err - } - - if err := os.Remove("certdata.txt"); err != nil { - return err - } - - fmt.Println("complete: ca packaging") - return nil -} - -func run(env map[string]string, cmd string, args ...string) error { - - out, err := sh.OutputWith(env, cmd, args...) - if out != "" { - fmt.Println(out) - } - - if err != nil { - return fmt.Errorf("unable to run command `%s %s`: %s", cmd, strings.Join(args, " "), err) - } - - return nil -} - -// collectCoverages collects all coverage reports. -func collectCoverages() error { - - f, err := os.OpenFile("coverage.txt", os.O_CREATE|os.O_RDWR, 0644) - defer f.Close() // nolint - if err != nil { - return err - } - - cfiles, err := filepath.Glob("*.cover") - if err != nil { - return err - } - - for _, cfile := range cfiles { - - cf, err := os.Open(cfile) - if err != nil { - return err - } - - defer cf.Close() // nolint - - if _, err := io.Copy(f, cf); err != nil { - return err - } - - os.Remove(cfile) // nolint - } - - return nil -} - -// getTestArgs provides arguments based on test options. -func getTestArgs(race bool, cover bool, p string) []string { - args := []string{"test"} - if race { - args = append(args, "-race") - } - if cover { - args = append(args, "-cover", "-coverprofile=cov-"+path.Base(p)+".cover", "-covermode=atomic") - } - return append(args, p) -} - -// TestWith runs unit tests without race. -func TestWith(race bool, cover bool) error { - - out, err := sh.Output("go", "list", "./...") - if err != nil { - return err - } - - var g errgroup.Group - - packages := strings.Split(out, "\n") - for _, p := range packages { - g.Go(func(p string) func() error { - return func() error { - args := getTestArgs(race, cover, p) - return run(nil, "go", args...) - } - }(p)) - } - - if err = g.Wait(); err != nil { - return err - } - - if cover { - if err := collectCoverages(); err != nil { - return err - } - } - - fmt.Println("complete: tests") - return nil -} diff --git a/magetask/doc.go b/magetask/doc.go deleted file mode 100644 index 5b39f03..0000000 --- a/magetask/doc.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2019 Aporeto Inc. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package magetask is deprecated and should not be used. -package magetask // import "go.aporeto.io/addedeffect/magetask" diff --git a/magetask/libver.go b/magetask/libver.go deleted file mode 100644 index 0133a1b..0000000 --- a/magetask/libver.go +++ /dev/null @@ -1,114 +0,0 @@ -// Copyright 2019 Aporeto Inc. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package magetask - -import ( - "fmt" - "os" - "path" - - "github.com/BurntSushi/toml" -) - -type constraint struct { - Name string - Revision string - Version string - Branch string -} - -type project struct { - Constraint []constraint - Override []constraint - Projects []constraint -} - -type versionTemplate struct { - ProjectVersion string - ProjectSha string - Libs map[string]string -} - -func parseProject(proj project) map[string]string { - - data := map[string]string{} - - // Apply constraint first - for _, c := range proj.Constraint { - if c.Version != "" { - data[c.Name] = c.Version - } else if c.Branch != "" { - data[c.Name] = c.Branch - } else if c.Revision != "" { - data[c.Name] = c.Revision - } - } - - // Then projects - for _, p := range proj.Projects { - if p.Version != "" { - data[p.Name] = p.Version - } else if p.Branch != "" { - data[p.Name] = p.Branch - } else if p.Revision != "" { - data[p.Name] = p.Revision - } - } - - // Then overrides - for _, o := range proj.Override { - if o.Version != "" { - data[o.Name] = o.Version - } else if o.Branch != "" { - data[o.Name] = o.Branch - } else if o.Revision != "" { - data[o.Name] = o.Revision - } - } - - return data -} - -func makeVersionFromDep(folder string, outFolder string, projectVersion string, projectSha string) error { - - if projectVersion == "" || projectSha == "" { - return fmt.Errorf("you must set both projectVersion=%s and projectSha=%s", projectVersion, projectSha) - } - - if folder == "" { - folder = "./" - } - if outFolder == "" { - outFolder = "./internal/versions" - } - - var proj project - - if _, err := os.Stat("./Gopkg.lock"); err == nil { - if _, err := toml.DecodeFile(path.Join(folder, "Gopkg.lock"), &proj); err != nil { - return err - } - } else { - if _, err := toml.DecodeFile(path.Join(folder, "Gopkg.toml"), &proj); err != nil { - return err - } - } - - return writeVersionsFile( - versionTemplate{ - ProjectVersion: projectVersion, - ProjectSha: projectSha, - Libs: parseProject(proj), - }, - outFolder, - ) -} diff --git a/magetask/templates.go b/magetask/templates.go deleted file mode 100644 index 38ef43d..0000000 --- a/magetask/templates.go +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright 2019 Aporeto Inc. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package magetask - -// NO SPACES IN HERE! USE TABS! -const versionFileTemplate = `package versions - -// This code is autogenerated by apolibver. Do not edit manually. - -import ( - "encoding/json" - "fmt" - - "go.uber.org/zap" - "go.uber.org/zap/zapcore" -) - -// Versions of the current project. -var ( - ProjectVersion = "{{.ProjectVersion}}" - ProjectSha = "{{.ProjectSha}}" -) - -// Versions of the various libraries used by the project. -var ( - {{- range $name, $version := .Libs }} - {{- if and $version (or (hasprefix $name "github.com/aporeto-inc/") (hasprefix $name "go.aporeto.io/")) }} - {{ varname $name }}Version = "{{ $version }}" - {{- end}} - {{- end}} -) - -// Fields returns a ready to dump zap.Fields containing all the versions used. -func Fields() []zapcore.Field { - - return []zapcore.Field{ - {{- range $name, $version := .Libs }} - {{- if and $version (or (hasprefix $name "github.com/aporeto-inc/") (hasprefix $name "go.aporeto.io/")) }} - zap.String("{{ short $name }}", {{ varname $name }}Version), - {{- end}} - {{- end}} - } -} - -// Map returns the version information as a map. -func Map() map[string]interface{} { - - return map[string]interface{}{ - "version": ProjectVersion, - "sha": ProjectSha[0:7], - "libs": map[string]string{ - {{- range $name, $version := .Libs }} - {{- if and $version (or (hasprefix $name "github.com/aporeto-inc/") (hasprefix $name "go.aporeto.io/")) }} - "{{ short $name }}": {{ varname $name }}Version, - {{- end}} - {{- end}} - }, - } -} - -// ToString returns the string version of versions -func ToString(prefix string) string { - - buffer := fmt.Sprintf("%s%32s : %s\n", prefix, "ProjectVersion", ProjectVersion) - buffer += fmt.Sprintf("%s%32s : %s\n", prefix, "ProjectSha", ProjectSha[0:7]) - buffer += fmt.Sprintf("%s%32s : %s\n", prefix, "Libraries", "") - {{- range $name, $version := .Libs }} - {{- if and $version (or (hasprefix $name "github.com/aporeto-inc/") (hasprefix $name "go.aporeto.io/")) }} - buffer += fmt.Sprintf("%s %32s : %s\n", prefix, "{{ short $name}}", {{ varname $name}}Version) - {{- end}} - {{- end}} - return buffer -} - -// JSON returns the version as a ready to send json data. -func JSON() ([]byte, error) { - - return json.MarshalIndent(Map(), "", " ") -} -` diff --git a/magetask/utils.go b/magetask/utils.go deleted file mode 100644 index 9188906..0000000 --- a/magetask/utils.go +++ /dev/null @@ -1,79 +0,0 @@ -// Copyright 2019 Aporeto Inc. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package magetask - -import ( - "bytes" - "fmt" - "html/template" - "os" - "path" - "strings" - - "golang.org/x/tools/imports" -) - -// writeVersionsFile writes the version file from the given templateData at the given path. -func writeVersionsFile(templateData versionTemplate, versionsFilePath string) error { - - t := template.Must(template.New("versions").Funcs(template.FuncMap{ - "cap": strings.Title, - "short": path.Base, - "hasprefix": strings.HasPrefix, - "varname": func(v string) string { - return strings.Title(path.Base(strings.Replace(v, "-", "", -1))) - }, - }).Parse(versionFileTemplate)) - - outFile := path.Join(versionsFilePath, "versions.go") - _, err := os.Stat(versionsFilePath) - if os.IsNotExist(err) { - if err = os.MkdirAll(versionsFilePath, 0744); err != nil { - panic(err) - } - } - - _, err = os.Stat(outFile) - if err == nil { - if err = os.Remove(outFile); err != nil { - panic(err) - } - } - - f, err := os.Create(outFile) - if err != nil { - panic(err) - } - defer f.Close() // nolint: errcheck - - buffer := &bytes.Buffer{} - if err = t.Execute(buffer, templateData); err != nil { - return err - } - - data, err := imports.Process(".", buffer.Bytes(), &imports.Options{ - TabWidth: 8, - TabIndent: true, - Comments: true, - Fragment: true, - }) - if err != nil { - fmt.Println(buffer.String()) - panic(err) - } - - if _, err = f.Write(data); err != nil { - return err - } - - return nil -} diff --git a/updatesync/doc.go b/updatesync/doc.go deleted file mode 100644 index ba9e621..0000000 --- a/updatesync/doc.go +++ /dev/null @@ -1,13 +0,0 @@ -// Copyright 2019 Aporeto Inc. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// Package updatesync is deprecated and should not be used. -package updatesync // import "go.aporeto.io/addedeffect/updatesync" diff --git a/updatesync/updatesync.go b/updatesync/updatesync.go deleted file mode 100644 index 1dfe0ee..0000000 --- a/updatesync/updatesync.go +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2019 Aporeto Inc. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package updatesync - -import ( - "time" - - "go.aporeto.io/elemental" - "go.aporeto.io/manipulate" -) - -// UpdateSync is an advanced function that allows to retry an failed update operation due to an -// updateTime mismatch (basically an update occurred between the time you got a copy of an object -// and the time you try to update it. -// -// It gets a manipulator and context to perform the updatea dnd also a function that returns an identifiable. -// This function must be used to apply the desired update. IT MUST NOT ALLOCATE A NEW OBJECT. -// For perf reasons, UpdateSync does not enforce that the return of your function must be a pointer. -// -// UpdateSync gets the Identifiable you want to update using your function and tries to update -// it. If it fails because of a desync, it will retrieve the latest copy of your object (modifying it) -// then will apply your function again (so you can reaply your desired changes) and try again until -// it succeeds or until the max number of tries is reached. -// -// Example: -// -// // If we have this object unit in memory -// o := &Object{ -// Name: "Hello World", -// Description: "This is the original description" -// } -// -// // Then if we want to change the description, even if an update happened, we do: -// err := UpdateSync(ctx.Background(), m, nil, func(obj elemental.Identifiable) { -// obj.(*Object).Description = "This is the description I want!" -// } -// -// Please keep in mind you have to be very careful with this function. You may still put the target object -// in a very weird state, if you override attributes that can be managed by a different source of truth. -func UpdateSync( - mctx manipulate.Context, - m manipulate.Manipulator, - obj elemental.Identifiable, - updateFunc func(elemental.Identifiable), -) error { - - deadline, hasDeadline := mctx.Context().Deadline() - - for { - - updateFunc(obj) - - err := m.Update(mctx, obj) - if err == nil { - return nil - } - - if hasDeadline && deadline.Before(time.Now()) { - return err - } - - // If the error is not a validation error for read only update time, we return the error. - if !elemental.IsValidationError(err, "Read Only Error", "updateTime") { - return err - } - - // Otherwise we retrieve the latest copy of the object. - if err = m.Retrieve(mctx, obj); err != nil { - return err - } - - // Then the loop will run again trying to update the object by applying the updateFunc on it. - } -} diff --git a/updatesync/updatesync_test.go b/updatesync/updatesync_test.go deleted file mode 100644 index 283ab41..0000000 --- a/updatesync/updatesync_test.go +++ /dev/null @@ -1,189 +0,0 @@ -// Copyright 2019 Aporeto Inc. -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// http://www.apache.org/licenses/LICENSE-2.0 -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package updatesync - -import ( - "context" - "fmt" - "net/http" - "testing" - "time" - - . "github.com/smartystreets/goconvey/convey" - "go.aporeto.io/elemental" - "go.aporeto.io/gaia" - "go.aporeto.io/manipulate" - "go.aporeto.io/manipulate/maniptest" -) - -func TestAPI_UpdateSync(t *testing.T) { - - Convey("Given I have a manipulator an object and an update func", t, func() { - - var synced int - m := maniptest.NewTestManipulator() - o := gaia.NewProcessingUnit() - o.Name = "name-original" - o.Description = "desc-original" - - uf := func(obj elemental.Identifiable) { - synced++ - obj.(*gaia.ProcessingUnit).Description = "synced!" - } - - Convey("When I update my object there is no sync needed", func() { - - m.MockUpdate(t, func(ctx manipulate.Context, object elemental.Identifiable) error { - return nil - }) - - err := UpdateSync(manipulate.NewContext(context.Background()), m, o, uf) - - Convey("Then err should be nil", func() { - So(err, ShouldBeNil) - }) - - Convey("Then obj should have been updated", func() { - So(o.Description, ShouldEqual, "synced!") - So(o.Name, ShouldEqual, "name-original") - }) - - Convey("Then the updateFunc should have been called once", func() { - So(synced, ShouldEqual, 1) - }) - }) - - Convey("When I update my object there is a sync needed", func() { - - m.MockUpdate(t, func(ctx manipulate.Context, object elemental.Identifiable) error { - object.(*gaia.ProcessingUnit).Name = fmt.Sprintf("sync%d", synced) - - if synced <= 3 { - e := elemental.NewError("Read Only Error", "bloob", "subject", http.StatusUnprocessableEntity) - e.Data = map[string]interface{}{"attribute": "updateTime"} - return e - } - - return nil - }) - - err := UpdateSync(manipulate.NewContext(context.Background()), m, o, uf) - - Convey("Then err should be nil", func() { - So(err, ShouldBeNil) - }) - - Convey("Then obj should have been updated", func() { - So(o.Name, ShouldEqual, "sync4") - So(o.Description, ShouldEqual, "synced!") - }) - - Convey("Then the updateFunc should have been called four times", func() { - So(synced, ShouldEqual, 4) - }) - }) - - Convey("When I update my object but there is an error right away", func() { - - m.MockUpdate(t, func(ctx manipulate.Context, object elemental.Identifiable) error { - return elemental.NewError("Not Read Only Error", "bloob", "subject", http.StatusInternalServerError) - }) - - err := UpdateSync(manipulate.NewContext(context.Background()), m, o, uf) - - Convey("Then err should not be nil", func() { - So(err, ShouldNotBeNil) - }) - - // TODO: that would be ideal, but this involves deep copy, - // and I'm not confident about it. - // Convey("Then obj should not have been updated", func() { - // So(o.Name, ShouldEqual, "name-original") - // So(o.Description, ShouldEqual, "desc-original") - // }) - - Convey("Then the updateFunc should have been called once", func() { - So(synced, ShouldEqual, 1) - }) - }) - - Convey("When I update my object there is a sync needed but the context is canceled", func() { - - m.MockUpdate(t, func(ctx manipulate.Context, object elemental.Identifiable) error { - e := elemental.NewError("Read Only Error", "bloob", "subject", http.StatusUnprocessableEntity) - e.Data = map[string]interface{}{"attribute": "updateTime"} - return e - }) - - ctx, cancel := context.WithTimeout(context.Background(), 300*time.Millisecond) - defer cancel() - - err := UpdateSync(manipulate.NewContext(ctx), m, o, uf) - - Convey("Then err should not be nil", func() { - So(err, ShouldNotBeNil) - So(err.Error(), ShouldEqual, "error 422 (subject): Read Only Error: bloob") - }) - - Convey("Then the updateFunc should have been called many times", func() { - So(synced, ShouldBeGreaterThan, 10) - }) - }) - - Convey("When I update my object there is a sync needed the manipulator returns an comm error", func() { - - m.MockUpdate(t, func(ctx manipulate.Context, object elemental.Identifiable) error { - return manipulate.NewErrCannotCommunicate("nope") - }) - - ctx, cancel := context.WithTimeout(context.Background(), 300*time.Millisecond) - defer cancel() - - err := UpdateSync(manipulate.NewContext(ctx), m, o, uf) - - Convey("Then err should not be nil", func() { - So(err, ShouldNotBeNil) - So(err.Error(), ShouldEqual, "Cannot communicate: nope") - }) - }) - - Convey("When I update my object there is a sync needed but the retrieve fails", func() { - - m.MockUpdate(t, func(ctx manipulate.Context, object elemental.Identifiable) error { - object.(*gaia.ProcessingUnit).Name = fmt.Sprintf("sync%d", synced) - - if synced <= 3 { - e := elemental.NewError("Read Only Error", "bloob", "subject", http.StatusUnprocessableEntity) - e.Data = map[string]interface{}{"attribute": "updateTime"} - return e - } - - return nil - }) - - m.MockRetrieve(t, func(ctx manipulate.Context, object elemental.Identifiable) error { - return fmt.Errorf("boom") - }) - - err := UpdateSync(manipulate.NewContext(context.Background()), m, o, uf) - - Convey("Then err should not be nil", func() { - So(err, ShouldNotBeNil) - So(err.Error(), ShouldEqual, "boom") - }) - - Convey("Then the updateFunc should have been called four times", func() { - So(synced, ShouldEqual, 1) - }) - }) - }) -}