func TestInvokeRectifyDryruns(t *testing.T) { assert := assert.New(t) require := require.New(t) testDryRun := func(which string) (sous.Deployer, sous.Registry) { exe := justCommand(t, []string{`sous`, `rectify`, `-dry-run`, which, `-repo`, `github.com/somewhere`}) assert.Len(exe.Args, 0) require.IsType(&SousRectify{}, exe.Cmd) rect := exe.Cmd.(*SousRectify) // currently no easy way to tell if the deploy client is live or dummy return nil, rect.Resolver.Registry } _, r := testDryRun("both") assert.IsType(&sous.DummyRegistry{}, r) _, r = testDryRun("none") assert.IsType(&docker.NameCache{}, r) _, r = testDryRun("scheduler") assert.IsType(&docker.NameCache{}, r) _, r = testDryRun("registry") assert.IsType(&sous.DummyRegistry{}, r) }
func TestInvokeManifestSet(t *testing.T) { assert := assert.New(t) require := require.New(t) exe := justCommand(t, []string{`sous`, `manifest`, `set`, `-repo`, `github.com/opentable/sous`}) assert.NotNil(exe) maniSet, good := exe.Cmd.(*SousManifestSet) require.True(good) assert.NotNil(maniSet.StateWriter) }
func TestInvokeMetadataSet(t *testing.T) { assert := assert.New(t) require := require.New(t) exe := justCommand(t, []string{`sous`, `metadata`, `set`, `-repo`, `github.com/opentable/sous`, `BuildBranch`, `master`}) assert.NotNil(exe) metaSet, good := exe.Cmd.(*SousMetadataSet) require.True(good) assert.NotNil(metaSet.State) }
func TestInvokeDeploy(t *testing.T) { assert := assert.New(t) require := require.New(t) exe := justCommand(t, []string{`sous`, `deploy`, `-cluster`, `ci-sf`, `-tag`, `1.2.3`}) assert.NotNil(exe) assert.Len(exe.Args, 0) deploy, good := exe.Cmd.(*SousDeploy) require.True(good) assert.Equal(deploy.DeployFilterFlags.Cluster, `ci-sf`) assert.Equal(deploy.DeployFilterFlags.Tag, `1.2.3`) }
func TestGitReadState(t *testing.T) { require := require.New(t) gsm := NewGitStateManager(NewDiskStateManager("testdata/in")) actual, err := gsm.ReadState() require.NoError(err) expected := exampleState() sameYAML(t, actual, expected) }
/* usage: sous <command> sous is a tool to help speed up the build/test/deploy cycle at your organisation subcommands: build build your project config view and edit sous configuration context show the current build context deploy initialise a new sous project help get help with sous init initialise a new sous project query build your project rectify force Sous to make the deployment match the contents of the local state directory version print the version of sous options: -d debug: output detailed logs of internal operations -q quiet: output only essential error messages -s silent: silence all non-essential output -v loud: output extra info, including all shell commands */ func TestInvokeBareSous(t *testing.T) { assert := assert.New(t) require := require.New(t) log.SetFlags(log.Flags() | log.Lshortfile) c, exe, _, _ := prepareCommand(t, []string{`sous`}) assert.Len(exe.Args, 0) var r cmdr.Result c.InvokeWithoutPrinting([]string{"sous", "help"}) require.NotPanics(func() { r = c.InvokeWithoutPrinting([]string{"sous", "help"}) }) assert.IsType(cmdr.SuccessResult{}, r) }
func TestHandlesManifestGetNotKnown(t *testing.T) { assert := assert.New(t) require := require.New(t) q, err := url.ParseQuery("repo=gh") require.NoError(err) th := &GETManifestHandler{ State: sous.NewState(), QueryValues: &QueryValues{q}, } _, status := th.Exchange() assert.Equal(404, status) }
func TestBuildDeployRequest(t *testing.T) { assert := assert.New(t) require := require.New(t) di := "dockerImage" rID := "reqID" env := sous.Env{"test": "yes"} rez := sous.Resources{"cpus": "0.1"} vols := sous.Volumes{&sous.Volume{}} dr, err := buildDeployRequest(di, env, rez, rID, vols) require.NoError(err) assert.NotNil(dr) assert.Equal(dr.Deploy.RequestId, rID) }
func TestInvokeWithUnknownFlags(t *testing.T) { log.SetFlags(log.Flags() | log.Lshortfile) assert := assert.New(t) require := require.New(t) stdin := &bytes.Buffer{} stdout := &bytes.Buffer{} stderr := &bytes.Buffer{} s := &Sous{Version: semv.MustParse(`1.2.3`)} c, err := NewSousCLI(s, stdin, stdout, stderr) require.NoError(err) c.Invoke([]string{`sous`, `-cobblers`}) assert.Regexp(`flag provided but not defined`, stderr.String()) }
func prepareCommand(t *testing.T, cl []string) (*CLI, *cmdr.PreparedExecution, fmt.Stringer, fmt.Stringer) { require := require.New(t) stdin := &bytes.Buffer{} stdout := &bytes.Buffer{} stderr := &bytes.Buffer{} s := &Sous{Version: semv.MustParse(`1.2.3`)} c, err := NewSousCLI(s, stdin, stdout, stderr) require.NoError(err) exe, err := c.Prepare(cl) require.NoError(err) return c, exe, stdout, stderr }
func TestInvokeRectifyWithoutFilterFlags(t *testing.T) { assert := assert.New(t) require := require.New(t) _, exe, _, _ := prepareCommand(t, []string{`sous`, `rectify`}) assert.Len(exe.Args, 0) require.IsType(&SousRectify{}, exe.Cmd) rect := exe.Cmd.(*SousRectify) assert.NotNil(rect.Config) assert.NotNil(rect.GDM) require.NotNil(rect.SourceFlags) assert.Equal(rect.SourceFlags.All, false) require.NotNil(rect.Resolver.ResolveFilter) assert.Equal(rect.Resolver.ResolveFilter.All(), true) }
func TestGitPushes(t *testing.T) { require := require.New(t) gsm, dsm := setupManagers(t) expected, err := gsm.ReadState() require.NoError(err) expected.Manifests.Add(&sous.Manifest{Source: sous.SourceLocation{Repo: "github.com/opentable/brandnew"}}) require.NoError(gsm.WriteState(expected)) expected, err = gsm.ReadState() require.NoError(err) runScript(t, `git reset --hard`, `testdata/origin`) //in order to reflect the change actual, err := dsm.ReadState() require.NoError(err) sameYAML(t, actual, expected) }
func TestHandlesManifestGet(t *testing.T) { assert := assert.New(t) require := require.New(t) q, err := url.ParseQuery("repo=gh") require.NoError(err) state := sous.NewState() state.Manifests.Add(&sous.Manifest{Source: sous.SourceLocation{Repo: "gh"}}) th := &GETManifestHandler{ State: state, QueryValues: &QueryValues{q}, } _, status := th.Exchange() assert.Equal(status, 200) }
func TestInvokeRectifyWithDebugFlags(t *testing.T) { assert := assert.New(t) require := require.New(t) _, exe, _, stderr := prepareCommand(t, []string{`sous`, `rectify`, `-d`, `-v`, `-all`}) assert.Len(exe.Args, 0) require.IsType(&SousRectify{}, exe.Cmd) rect := exe.Cmd.(*SousRectify) assert.NotNil(rect.Config) assert.NotNil(rect.GDM) require.NotNil(rect.SourceFlags) assert.Equal(rect.SourceFlags.All, true) assert.Regexp(`Verbose debugging`, stderr.String()) assert.Regexp(`Regular debugging`, stderr.String()) }
func TestHandlesManifestPut(t *testing.T) { assert := assert.New(t) require := require.New(t) q, err := url.ParseQuery("repo=gh") require.NoError(err) state := sous.NewState() state.Manifests.Add(&sous.Manifest{ Source: sous.SourceLocation{Repo: "gh"}, Kind: sous.ManifestKindService, }) writer := graph.StateWriter{StateWriter: &sous.DummyStateManager{State: state}} manifest := &sous.Manifest{ Source: sous.SourceLocation{Repo: "gh"}, Owners: []string{"sam", "judson"}, Kind: sous.ManifestKindService, } buf := &bytes.Buffer{} enc := json.NewEncoder(buf) enc.Encode(manifest) req, err := http.NewRequest("PUT", "", buf) require.NoError(err) th := &PUTManifestHandler{ Request: req, StateWriter: writer, State: state, QueryValues: &QueryValues{q}, } data, status := th.Exchange() assert.Equal(status, 200) require.IsType(&sous.Manifest{}, data) assert.Len(data.(*sous.Manifest).Owners, 2) assert.Equal(data.(*sous.Manifest).Owners[1], "judson") changed, found := state.Manifests.Get(sous.ManifestID{Source: sous.SourceLocation{Repo: "gh"}}) require.True(found) assert.Len(changed.Owners, 2) assert.Equal(changed.Owners[1], "judson") }
func TestGitWriteState(t *testing.T) { require := require.New(t) s := exampleState() if err := os.RemoveAll("testdata/out"); err != nil { t.Fatal(err) } gsm := NewGitStateManager(NewDiskStateManager("testdata/out")) require.NoError(gsm.WriteState(s)) d := exec.Command("diff", "-r", "testdata/in", "testdata/out") out, err := d.CombinedOutput() if err != nil { t.Log("Output not as expected:") t.Log(string(out)) t.Fatal("") } }
func TestGitPulls(t *testing.T) { require := require.New(t) gsm, dsm := setupManagers(t) actual, err := gsm.ReadState() require.NoError(err) expected := exampleState() sameYAML(t, actual, expected) expected.Manifests.Add(&sous.Manifest{Source: sous.SourceLocation{Repo: "github.com/opentable/brandnew"}}) dsm.WriteState(expected) expected, err = dsm.ReadState() require.NoError(err) runScript(t, `git add . git commit -m ""`, `testdata/origin`) actual, err = gsm.ReadState() require.NoError(err) sameYAML(t, actual, expected) }
func sameYAML(t *testing.T, actual *sous.State, expected *sous.State) { assert := assert.New(t) require := require.New(t) actualManifests := actual.Manifests.Snapshot() expectedManifests := expected.Manifests.Snapshot() assert.Len(actualManifests, len(expectedManifests)) for mid, manifest := range expectedManifests { actual := *actualManifests[mid] assert.Contains(actualManifests, mid) if !assert.Equal(actual, *manifest) { _, differences := actual.Diff(manifest) t.Logf("DIFFERENCES (%q): %#v", mid, differences) } } actualYAML, err := yaml.Marshal(actual) require.NoError(err) expectedYAML, err := yaml.Marshal(expected) require.NoError(err) assert.Equal(actualYAML, expectedYAML) }
func TestRecordAdvisories(t *testing.T) { assert := assert.New(t) require := require.New(t) dc := docker_registry.NewDummyClient() host := "docker.repo.io" base := "ot/wackadoo" nc := NewNameCache(host, dc, inMemoryDB("advisories")) v := "1.2.3" sv := sous.MustNewSourceID("https://github.com/opentable/wackadoo", "nested/there", v) digest := "sha256:012345678901234567890123456789AB012345678901234567890123456789AB" cn := base + "@" + digest qs := []sous.Quality{{Name: "ephemeral_tag", Kind: "advisory"}} err := nc.Insert(sv, cn, digest, qs) assert.NoError(err) arty, err := nc.GetArtifact(sv) assert.NoError(err) require.NotNil(arty) require.Len(arty.Qualities, 1) assert.Equal(arty.Qualities[0].Name, `ephemeral_tag`) }
func TestRealDiffConcentration(t *testing.T) { log.SetFlags(log.Flags() | log.Lshortfile) assert := assert.New(t) require := require.New(t) intended := NewDeployments() existing := NewDeployments() defs := Defs{Clusters: map[string]*Cluster{"test": &Cluster{}}} makeDepl := func(repo, verstr string, num int) *Deployment { version := semv.MustParse(verstr) cl := defs.Clusters["test"] owners := OwnerSet{} owners.Add("judson") return &Deployment{ SourceID: SourceID{ Location: SourceLocation{ Repo: repo, }, Version: version, }, Cluster: cl, ClusterName: "test", DeployConfig: DeployConfig{ NumInstances: num, Env: map[string]string{}, Resources: map[string]string{ "cpu": ".1", "memory": "100", "ports": "1", }, }, Owners: owners, } } repoOne := "github.com/opentable/one" repoTwo := "github.com/opentable/two" repoThree := "github.com/opentable/three" repoFour := "github.com/opentable/four" repoFive := "github.com/opentable/five" existing.MustAdd(makeDepl(repoOne, "111.1.1", 1)) //remove //intended: gone existing.MustAdd(makeDepl(repoTwo, "1.0.0", 1)) //same intended.MustAdd(makeDepl(repoTwo, "1.0.0", 1)) //same // existing: doesn't yet intended.MustAdd(makeDepl(repoFour, "1.0.0", 1)) //create existing.MustAdd(makeDepl(repoThree, "1.0.0", 1)) //changed intended.MustAdd(makeDepl(repoThree, "1.0.0", 2)) //changed existing.MustAdd(makeDepl(repoFive, "1.0.0", 1)) //changed intended.MustAdd(makeDepl(repoFive, "2.0.0", 1)) //changed dc := existing.Diff(intended).Concentrate(defs) ds, err := dc.collect() require.NoError(err) if assert.Len(ds.Gone.Snapshot(), 1, "Should have one deleted item.") { it, _ := ds.Gone.Any(func(*Manifest) bool { return true }) assert.Equal(string(it.Source.Repo), repoOne) } if assert.Len(ds.Same.Snapshot(), 1, "Should have one unchanged item.") { it, _ := ds.Same.Any(func(*Manifest) bool { return true }) assert.Equal(string(it.Source.Repo), repoTwo) } if assert.Len(ds.Changed, 2, "Should have two modified items.") { chNum, chVer := ds.Changed[0], ds.Changed[1] if repoThree == chVer.name.Source.Repo { chNum, chVer = chVer, chNum } assert.Equal(repoThree, string(chNum.name.Source.Repo)) assert.Equal(repoThree, string(chNum.Prior.Source.Repo)) assert.Equal(repoThree, string(chNum.Post.Source.Repo)) log.Printf("%+v", chNum) log.Printf("%+v", chNum.Prior) log.Printf("%+v", chNum.Post) assert.Equal(chNum.Prior.Deployments["test"].NumInstances, 1) assert.Equal(chNum.Post.Deployments["test"].NumInstances, 2) assert.Equal(repoFive, string(chVer.name.Source.Repo)) assert.Equal(repoFive, string(chVer.Prior.Source.Repo)) assert.Equal(repoFive, string(chVer.Post.Source.Repo)) ver1 := semv.MustParse("1.0.0") ver2 := semv.MustParse("2.0.0") assert.Equal(ver1, chVer.Prior.Deployments["test"].Version) assert.Equal(ver2, chVer.Post.Deployments["test"].Version) } if assert.Equal(ds.New.Len(), 1, "Should have one added item.") { it, _ := ds.New.Any(func(*Manifest) bool { return true }) assert.Equal(string(it.Source.Repo), repoFour) } }