func TestDeployment(t *testing.T) { e := empiretest.NewEmpire(t) s := new(mockScheduler) s.image = make(chan string, 1) e.Scheduler = s c, sv := NewTestClient(t, e) defer sv.Close() var d events.Deployment d.Repository.FullName = "remind101/acme-inc" d.Deployment.ID = 1234 d.Deployment.Ref = "master" d.Deployment.Sha = "827fecd2d36ebeaa2fd05aa8ef3eed1e56a8cd57" d.Deployment.Task = "deployment" d.Deployment.Environment = "test" d.Deployment.Description = "Deploying" d.Deployment.Creator.Login = "******" resp, err := c.Trigger("deployment", &d) assert.NoError(t, err) raw, err := ioutil.ReadAll(resp.Body) assert.NoError(t, err) assert.Equal(t, 202, resp.StatusCode) assert.Equal(t, "Ok\n", string(raw)) assert.Equal(t, "remind101/acme-inc:827fecd2d36ebeaa2fd05aa8ef3eed1e56a8cd57", <-s.image) }
func TestEmpire_Deploy_ImageNotFound(t *testing.T) { e := empiretest.NewEmpire(t) s := new(mockScheduler) e.Scheduler = s e.ExtractProcfile = func(ctx context.Context, img image.Image, w io.Writer) (procfile.Procfile, error) { return nil, errors.New("image not found") } // Deploying an image to an app that doesn't exist will create a new // app. _, err := e.Deploy(context.Background(), empire.DeploymentsCreateOpts{ User: &empire.User{Name: "ejholmes"}, Output: ioutil.Discard, Image: image.Image{Repository: "remind101/acme-inc"}, }) assert.Error(t, err) // If there's an error deploying, then the transaction should be rolled // backed and no apps should exist. apps, err := e.Apps(empire.AppsQuery{}) assert.NoError(t, err) assert.Equal(t, 0, len(apps)) s.AssertExpectations(t) }
func run(t testing.TB, commands []Command) { e := empiretest.NewEmpire(t) s := empiretest.NewServer(t, e) defer s.Close() token, err := e.AccessTokensCreate(&empire.AccessToken{ User: &empire.User{Name: "fake", GitHubToken: "token"}, }) if err != nil { t.Fatal(err) } for _, cmd := range commands { got := cli(t, token.Token, s.URL, cmd.Command) if want, ok := cmd.Output.(string); ok { if want != "" { want = want + "\n" } if got != want { t.Fatalf("%q != %q", got, want) } } else if regex, ok := cmd.Output.(*regexp.Regexp); ok { if !regex.MatchString(got) { t.Fatalf("%q != %q", got, regex.String()) } } } }
func TestEmpire_Deploy(t *testing.T) { e := empiretest.NewEmpire(t) s := new(mockScheduler) e.Scheduler = s user := &empire.User{Name: "ejholmes"} app, err := e.Create(context.Background(), empire.CreateOpts{ User: user, Name: "acme-inc", }) assert.NoError(t, err) hostPort, containerPort := int64(9000), int64(8080) img := image.Image{Repository: "remind101/acme-inc"} s.On("Submit", &scheduler.App{ ID: app.ID, Name: "acme-inc", Processes: []*scheduler.Process{ { Type: "web", Image: img, Command: "./bin/web", Exposure: scheduler.ExposePrivate, Ports: []scheduler.PortMap{ {Host: &hostPort, Container: &containerPort}, }, Instances: 1, MemoryLimit: 536870912, CPUShares: 256, SSLCert: "", Env: map[string]string{ "EMPIRE_APPID": app.ID, "EMPIRE_APPNAME": "acme-inc", "EMPIRE_PROCESS": "web", "EMPIRE_RELEASE": "v1", "SOURCE": "acme-inc.web.v1", "PORT": "8080", "EMPIRE_CREATED_AT": "2015-01-01T01:01:01Z", }, Labels: map[string]string{ "empire.app.name": "acme-inc", "empire.app.id": app.ID, "empire.app.process": "web", "empire.app.release": "v1", }, }, }, }).Return(nil) _, err = e.Deploy(context.Background(), empire.DeploymentsCreateOpts{ App: app, User: user, Output: ioutil.Discard, Image: img, }) assert.NoError(t, err) s.AssertExpectations(t) }
func TestEmpire_Deploy_Concurrent(t *testing.T) { e := empiretest.NewEmpire(t) s := new(mockScheduler) e.Scheduler = scheduler.NewFakeScheduler() e.ExtractProcfile = func(ctx context.Context, img image.Image, w io.Writer) (procfile.Procfile, error) { return nil, nil } user := &empire.User{Name: "ejholmes"} // Create the first release for this app. r, err := e.Deploy(context.Background(), empire.DeploymentsCreateOpts{ User: user, Output: ioutil.Discard, Image: image.Image{Repository: "remind101/acme-inc"}, }) assert.NoError(t, err) assert.Equal(t, 1, r.Version) // We'll use the procfile extractor to synchronize two concurrent // deployments. v2Started, v3Started := make(chan struct{}), make(chan struct{}) e.ExtractProcfile = func(ctx context.Context, img image.Image, w io.Writer) (procfile.Procfile, error) { switch img.Tag { case "v2": close(v2Started) <-v3Started case "v3": close(v3Started) } return nil, nil } v2Done := make(chan struct{}) go func() { r, err = e.Deploy(context.Background(), empire.DeploymentsCreateOpts{ User: user, Output: ioutil.Discard, Image: image.Image{Repository: "remind101/acme-inc", Tag: "v2"}, }) assert.NoError(t, err) assert.Equal(t, 2, r.Version) close(v2Done) }() <-v2Started r, err = e.Deploy(context.Background(), empire.DeploymentsCreateOpts{ User: user, Output: ioutil.Discard, Image: image.Image{Repository: "remind101/acme-inc", Tag: "v3"}, }) assert.NoError(t, err) assert.Equal(t, 3, r.Version) <-v2Done s.AssertExpectations(t) }
func TestPing(t *testing.T) { e := empiretest.NewEmpire(t) c, s := NewTestClient(t, e) defer s.Close() if _, err := c.Ping(hooker.DefaultPing); err != nil { t.Fatal(err) } }
// NewTestClient will return a new heroku.Client that's configured to interact // with a instance of the empire HTTP server. func NewTestClient(t testing.TB) (*hooker.Client, *httptest.Server) { e := empiretest.NewEmpire(t) s := empiretest.NewServer(t, e) c := hooker.NewClient(nil) c.URL = s.URL c.Secret = "abcd" return c, s }
// NewTestClient will return a new heroku.Client that's configured to interact // with a instance of the empire HTTP server. func NewTestClient(t testing.TB) (*heroku.Client, *httptest.Server) { e := empiretest.NewEmpire(t) s := empiretest.NewServer(t, e) c := &heroku.Client{ Username: "", Password: "", } c.URL = s.URL return c, s }
// newClient will return a new heroku.Client that's configured to interact // with a instance of the empire HTTP server. func newClient(t testing.TB) *client { e := empiretest.NewEmpire(t) s := empiretest.NewServer(t, e) c := hooker.NewClient(nil) c.URL = s.URL c.Secret = "abcd" return &client{ Server: s, Client: c, } }
// NewTestClient will return a new heroku.Client that's configured to interact // with a instance of the empire HTTP server. func NewTestClient(t testing.TB) (*heroku.Client, *empiretest.Server) { e := empiretest.NewEmpire(t) s := empiretest.NewTestServer(t, e, server.Options{ Authenticator: auth.Anyone(&empire.User{Name: "fake"}), }) c := &heroku.Client{ Username: "", Password: "", } c.URL = s.URL return c, s }
// NewTestClient will return a new heroku.Client that's configured to interact // with a instance of the empire HTTP server. func NewTestClient(t testing.TB) (*heroku.Client, *httptest.Server) { e := empiretest.NewEmpire(t) s := empiretest.NewServer(t, e) token, err := e.AccessTokensCreate(&empire.AccessToken{ User: &empire.User{Name: "fake", GitHubToken: "token"}, }) if err != nil { t.Fatal(err) } c := &heroku.Client{ Username: "", Password: token.Token, } c.URL = s.URL return c, s }
func TestLogin(t *testing.T) { e := empiretest.NewEmpire(t) s := empiretest.NewServer(t, e) defer s.Close() input := "fake\nbar\n" cmd := NewCmd(s.URL, "login") cmd.Stdin = strings.NewReader(input) out, err := cmd.CombinedOutput() if err != nil { t.Fatal(err) } if got, want := string(out), "Enter email: Logged in.\n"; got != want { t.Fatalf("%q", got) } }
func TestLoginUnauthorized(t *testing.T) { e := empiretest.NewEmpire(t) s := empiretest.NewServer(t, e) defer s.Close() input := "foo\nbar\n" cmd := NewCmd(s.URL, "login") cmd.Stdin = strings.NewReader(input) out, err := cmd.CombinedOutput() if err == nil { t.Fatal("Expected an error") } if got, want := string(out), "Enter email: error: Request not authenticated, API token is missing, invalid or expired Log in with `emp login`.\n"; got != want { t.Fatalf("%q", got) } }
func TestLoginTwoFactor(t *testing.T) { e := empiretest.NewEmpire(t) s := httptest.NewServer(server.New(e, server.Options{ Authenticator: auth.StaticAuthenticator("twofactor", "bar", "code", &empire.User{Name: "fake"}), })) defer s.Close() input := "twofactor\nbar\ncode\n" cmd := NewCmd(s.URL, "login") cmd.Stdin = strings.NewReader(input) out, err := cmd.CombinedOutput() if err != nil { t.Fatal(err) } if got, want := string(out), "Enter email: Enter two-factor auth code: Logged in.\n"; got != want { t.Fatalf("%q", got) } }
// NewTestClient will return a new heroku.Client that's configured to interact // with a instance of the empire HTTP server. func NewTestClient(t testing.TB) (*heroku.Client, *empiretest.Server) { e := empiretest.NewEmpire(t) s := empiretest.NewServer(t, e) s.Heroku.Auth = &auth.Auth{ Strategies: auth.Strategies{ { Name: auth.StrategyUsernamePassword, Authenticator: auth.Anyone(&empire.User{Name: "fake"}), }, }, } s.Start() c := &heroku.Client{ Username: "", Password: "", } c.URL = s.URL() return c, s }
func TestEmpire_CertsAttach(t *testing.T) { e := empiretest.NewEmpire(t) s := new(mockScheduler) e.Scheduler = s user := &empire.User{Name: "ejholmes"} app, err := e.Create(context.Background(), empire.CreateOpts{ User: user, Name: "acme-inc", }) assert.NoError(t, err) cert := "serverCertificate" err = e.CertsAttach(context.Background(), empire.CertsAttachOpts{ App: app, Cert: cert, }) assert.NoError(t, err) app, err = e.AppsFind(empire.AppsQuery{ID: &app.ID}) assert.NoError(t, err) assert.Equal(t, empire.Certs{"web": "serverCertificate"}, app.Certs) cert = "otherCertificate" err = e.CertsAttach(context.Background(), empire.CertsAttachOpts{ App: app, Cert: cert, Process: "http", }) assert.NoError(t, err) app, err = e.AppsFind(empire.AppsQuery{ID: &app.ID}) assert.NoError(t, err) assert.Equal(t, empire.Certs{"web": "serverCertificate", "http": "otherCertificate"}, app.Certs) s.AssertExpectations(t) }
func TestEmpire_AccessTokens(t *testing.T) { e := empiretest.NewEmpire(t) token := &empire.AccessToken{ User: &empire.User{Name: "ejholmes"}, } _, err := e.AccessTokensCreate(token) assert.NoError(t, err) token, err = e.AccessTokensFind(token.Token) assert.NoError(t, err) assert.NotNil(t, token) assert.Equal(t, "ejholmes", token.User.Name) token, err = e.AccessTokensFind("invalid") assert.NoError(t, err) assert.Nil(t, token) token = &empire.AccessToken{ User: &empire.User{Name: ""}, } _, err = e.AccessTokensCreate(token) assert.Equal(t, empire.ErrUserName, err) }
func TestEmpire_Run_WithAllowCommandProcfile(t *testing.T) { e := empiretest.NewEmpire(t) e.AllowedCommands = empire.AllowCommandProcfile user := &empire.User{Name: "ejholmes"} app, err := e.Create(context.Background(), empire.CreateOpts{ User: user, Name: "acme-inc", }) assert.NoError(t, err) img := image.Image{Repository: "remind101/acme-inc"} _, err = e.Deploy(context.Background(), empire.DeployOpts{ App: app, User: user, Output: empire.NewDeploymentStream(ioutil.Discard), Image: img, }) assert.NoError(t, err) s := new(mockScheduler) e.Scheduler = s err = e.Run(context.Background(), empire.RunOpts{ User: user, App: app, Command: empire.MustParseCommand("bundle exec rake db:migrate"), // Detached Process Output: nil, Input: nil, Env: map[string]string{ "TERM": "xterm", }, }) assert.IsType(t, &empire.CommandNotAllowedError{}, err) s.On("Run", &scheduler.App{ ID: app.ID, Name: "acme-inc", Release: "v1", Env: map[string]string{ "EMPIRE_APPID": app.ID, "EMPIRE_APPNAME": "acme-inc", "EMPIRE_RELEASE": "v1", }, Labels: map[string]string{ "empire.app.id": app.ID, "empire.app.name": "acme-inc", "empire.app.release": "v1", }, }, &scheduler.Process{ Type: "rake", Image: img, Command: []string{"bundle", "exec", "rake", "db:migrate"}, Instances: 1, MemoryLimit: 536870912, CPUShares: 256, Nproc: 256, Env: map[string]string{ "EMPIRE_PROCESS": "rake", "EMPIRE_PROCESS_SCALE": "1", "SOURCE": "acme-inc.rake.v1", "TERM": "xterm", }, Labels: map[string]string{ "empire.app.process": "rake", "empire.user": "******", }, }, nil, nil).Return(nil) err = e.Run(context.Background(), empire.RunOpts{ User: user, App: app, Command: empire.MustParseCommand("rake db:migrate"), // Detached Process Output: nil, Input: nil, Env: map[string]string{ "TERM": "xterm", }, }) assert.NoError(t, err) s.AssertExpectations(t) }
func TestEmpire_Set(t *testing.T) { e := empiretest.NewEmpire(t) s := new(mockScheduler) e.Scheduler = s e.ProcfileExtractor = empiretest.ExtractProcfile(procfile.ExtendedProcfile{ "web": procfile.Process{ Command: []string{"./bin/web"}, }, }) user := &empire.User{Name: "ejholmes"} // Create an app app, err := e.Create(context.Background(), empire.CreateOpts{ User: user, Name: "acme-inc", }) assert.NoError(t, err) // Add some environment variables to it. prod := "production" _, err = e.Set(context.Background(), empire.SetOpts{ User: user, App: app, Vars: empire.Vars{ "RAILS_ENV": &prod, }, }) assert.NoError(t, err) // Deploy a new image to the app. img := image.Image{Repository: "remind101/acme-inc"} s.On("Submit", &scheduler.App{ ID: app.ID, Name: "acme-inc", Release: "v1", Env: map[string]string{ "EMPIRE_APPID": app.ID, "EMPIRE_APPNAME": "acme-inc", "EMPIRE_RELEASE": "v1", "RAILS_ENV": "production", }, Labels: map[string]string{ "empire.app.name": "acme-inc", "empire.app.id": app.ID, "empire.app.release": "v1", }, Processes: []*scheduler.Process{ { Type: "web", Image: img, Command: []string{"./bin/web"}, Exposure: &scheduler.Exposure{ Type: &scheduler.HTTPExposure{}, }, Instances: 1, MemoryLimit: 536870912, CPUShares: 256, Nproc: 256, Env: map[string]string{ "EMPIRE_PROCESS": "web", "EMPIRE_PROCESS_SCALE": "1", "SOURCE": "acme-inc.web.v1", }, Labels: map[string]string{ "empire.app.process": "web", }, }, }, }).Once().Return(nil) _, err = e.Deploy(context.Background(), empire.DeployOpts{ App: app, User: user, Output: empire.NewDeploymentStream(ioutil.Discard), Image: img, }) assert.NoError(t, err) // Remove the environment variable s.On("Submit", &scheduler.App{ ID: app.ID, Name: "acme-inc", Release: "v2", Env: map[string]string{ "EMPIRE_APPID": app.ID, "EMPIRE_APPNAME": "acme-inc", "EMPIRE_RELEASE": "v2", }, Labels: map[string]string{ "empire.app.name": "acme-inc", "empire.app.id": app.ID, "empire.app.release": "v2", }, Processes: []*scheduler.Process{ { Type: "web", Image: img, Command: []string{"./bin/web"}, Exposure: &scheduler.Exposure{ Type: &scheduler.HTTPExposure{}, }, Instances: 1, MemoryLimit: 536870912, CPUShares: 256, Nproc: 256, Env: map[string]string{ "EMPIRE_PROCESS": "web", "EMPIRE_PROCESS_SCALE": "1", "SOURCE": "acme-inc.web.v2", }, Labels: map[string]string{ "empire.app.process": "web", }, }, }, }).Once().Return(nil) _, err = e.Set(context.Background(), empire.SetOpts{ User: user, App: app, Vars: empire.Vars{ "RAILS_ENV": nil, }, }) assert.NoError(t, err) s.AssertExpectations(t) }
// newCLI returns a new CLI instance. func newCLI(t testing.TB) *CLI { e := empiretest.NewEmpire(t) s := empiretest.NewServer(t, e) return newCLIWithServer(t, s) }
func TestEmpire_Deploy(t *testing.T) { e := empiretest.NewEmpire(t) s := new(mockScheduler) e.Scheduler = s user := &empire.User{Name: "ejholmes"} app, err := e.Create(context.Background(), empire.CreateOpts{ User: user, Name: "acme-inc", }) assert.NoError(t, err) img := image.Image{Repository: "remind101/acme-inc"} s.On("Submit", &scheduler.App{ ID: app.ID, Name: "acme-inc", Release: "v1", Env: map[string]string{ "EMPIRE_APPID": app.ID, "EMPIRE_APPNAME": "acme-inc", "EMPIRE_RELEASE": "v1", }, Labels: map[string]string{ "empire.app.name": "acme-inc", "empire.app.id": app.ID, "empire.app.release": "v1", }, Processes: []*scheduler.Process{ { Type: "scheduled", Image: img, Command: []string{"./bin/scheduled"}, Schedule: scheduler.CRONSchedule("* * * * * *"), Instances: 0, MemoryLimit: 536870912, CPUShares: 256, Nproc: 256, Env: map[string]string{ "EMPIRE_PROCESS": "scheduled", "EMPIRE_PROCESS_SCALE": "0", "SOURCE": "acme-inc.scheduled.v1", }, Labels: map[string]string{ "empire.app.process": "scheduled", }, }, { Type: "web", Image: img, Command: []string{"./bin/web"}, Exposure: &scheduler.Exposure{ Type: &scheduler.HTTPExposure{}, }, Instances: 1, MemoryLimit: 536870912, CPUShares: 256, Nproc: 256, Env: map[string]string{ "EMPIRE_PROCESS": "web", "EMPIRE_PROCESS_SCALE": "1", "SOURCE": "acme-inc.web.v1", }, Labels: map[string]string{ "empire.app.process": "web", }, }, { Type: "worker", Image: img, Command: []string{"./bin/worker"}, Instances: 0, MemoryLimit: 536870912, CPUShares: 256, Nproc: 256, Env: map[string]string{ "EMPIRE_PROCESS": "worker", "EMPIRE_PROCESS_SCALE": "0", "SOURCE": "acme-inc.worker.v1", }, Labels: map[string]string{ "empire.app.process": "worker", }, }, }, }).Return(nil) _, err = e.Deploy(context.Background(), empire.DeployOpts{ App: app, User: user, Output: empire.NewDeploymentStream(ioutil.Discard), Image: img, }) assert.NoError(t, err) s.AssertExpectations(t) }