Example #1
0
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)
}
Example #2
0
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)
}
Example #3
0
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())
			}
		}
	}
}
Example #4
0
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)
}
Example #5
0
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)
}
Example #6
0
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)
	}
}
Example #7
0
// 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
}
Example #8
0
// 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
}
Example #9
0
// 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,
	}
}
Example #10
0
// 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
}
Example #11
0
// 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
}
Example #12
0
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)
	}
}
Example #13
0
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)
	}
}
Example #14
0
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)
	}
}
Example #15
0
// 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
}
Example #16
0
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)
}
Example #17
0
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)
}
Example #18
0
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)
}
Example #19
0
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)
}
Example #20
0
// 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)
}
Example #21
0
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)
}