Пример #1
0
func processSchedule(name string, p Process) scheduler.Schedule {
	if p.Cron != nil {
		return scheduler.CRONSchedule(*p.Cron)
	}

	return nil
}
Пример #2
0
func TestScheduleExpression(t *testing.T) {
	tests := []struct {
		schedule   scheduler.Schedule
		expression string
	}{
		{scheduler.CRONSchedule("0 12 * * ? *"), "cron(0 12 * * ? *)"},
		{5 * time.Minute, "rate(5 minutes)"},
		{1 * time.Minute, "rate(1 minute)"},
		{24 * time.Hour, "rate(1440 minutes)"},
	}

	for _, tt := range tests {
		expression := scheduleExpression(tt.schedule)
		assert.Equal(t, tt.expression, expression)
	}
}
Пример #3
0
func TestEmpireTemplate(t *testing.T) {
	tests := []struct {
		file string
		app  *scheduler.App
	}{
		{
			"basic.json",
			&scheduler.App{
				ID:      "1234",
				Release: "v1",
				Name:    "acme-inc",
				Env: map[string]string{
					// These should get re-sorted in
					// alphabetical order.
					"C": "foo",
					"A": "foobar",
					"B": "bar",
				},
				Processes: []*scheduler.Process{
					{
						Type:    "web",
						Image:   image.Image{Repository: "remind101/acme-inc", Tag: "latest"},
						Command: []string{"./bin/web"},
						Exposure: &scheduler.Exposure{
							Type: &scheduler.HTTPExposure{},
						},
						Labels: map[string]string{
							"empire.app.process": "web",
						},
						MemoryLimit: 128 * bytesize.MB,
						CPUShares:   256,
						Instances:   1,
						Nproc:       256,
					},
					{
						Type:    "worker",
						Image:   image.Image{Repository: "remind101/acme-inc", Tag: "latest"},
						Command: []string{"./bin/worker"},
						Labels: map[string]string{
							"empire.app.process": "worker",
						},
						Env: map[string]string{
							"FOO": "BAR",
						},
					},
				},
			},
		},

		{
			"https.json",
			&scheduler.App{
				ID:      "1234",
				Release: "v1",
				Name:    "acme-inc",
				Processes: []*scheduler.Process{
					{
						Type:    "web",
						Command: []string{"./bin/web"},
						Exposure: &scheduler.Exposure{
							Type: &scheduler.HTTPSExposure{
								Cert: "arn:aws:iam::012345678901:server-certificate/AcmeIncDotCom",
							},
						},
					},
					{
						Type:    "api",
						Command: []string{"./bin/api"},
						Exposure: &scheduler.Exposure{
							Type: &scheduler.HTTPSExposure{
								Cert: "AcmeIncDotCom", // Simple cert format.
							},
						},
					},
				},
			},
		},

		{
			"custom.json",
			&scheduler.App{
				ID:      "1234",
				Release: "v1",
				Name:    "acme-inc",
				Env: map[string]string{
					"ECS_TASK_DEFINITION": "custom",
				},
				Processes: []*scheduler.Process{
					{
						Type:    "web",
						Image:   image.Image{Repository: "remind101/acme-inc", Tag: "latest"},
						Command: []string{"./bin/web"},
						Env: map[string]string{
							"B":   "foo",
							"A":   "foo",
							"FOO": "bar",
						},
						Exposure: &scheduler.Exposure{
							Type: &scheduler.HTTPExposure{},
						},
						Labels: map[string]string{
							"empire.app.process": "web",
						},
						MemoryLimit: 128 * bytesize.MB,
						CPUShares:   256,
						Instances:   1,
						Nproc:       256,
					},
					{
						Type:      "vacuum",
						Image:     image.Image{Repository: "remind101/acme-inc", Tag: "latest"},
						Command:   []string{"./bin/vacuum"},
						Schedule:  scheduler.CRONSchedule("* * * * *"),
						Instances: 1,
						Labels: map[string]string{
							"empire.app.process": "vacuum",
						},
						MemoryLimit: 128 * bytesize.MB,
						CPUShares:   256,
						Nproc:       256,
					},
				},
			},
		},

		{
			"cron.json",
			&scheduler.App{
				ID:      "1234",
				Release: "v1",
				Name:    "acme-inc",
				Processes: []*scheduler.Process{
					{
						Type:      "send-emails",
						Image:     image.Image{Repository: "remind101/acme-inc", Tag: "latest"},
						Command:   []string{"./bin/send-emails"},
						Schedule:  scheduler.CRONSchedule("* * * * *"),
						Instances: 1,
						Labels: map[string]string{
							"empire.app.process": "send-emails",
						},
						MemoryLimit: 128 * bytesize.MB,
						CPUShares:   256,
						Nproc:       256,
					},
					{
						Type:      "vacuum",
						Image:     image.Image{Repository: "remind101/acme-inc", Tag: "latest"},
						Command:   []string{"./bin/vacuum"},
						Schedule:  scheduler.CRONSchedule("* * * * *"),
						Instances: 0,
						Labels: map[string]string{
							"empire.app.process": "vacuum",
						},
						MemoryLimit: 128 * bytesize.MB,
						CPUShares:   256,
						Nproc:       256,
					},
				},
			},
		},
	}

	for _, tt := range tests {
		tmpl := newTemplate()
		tmpl.NoCompress = true
		buf := new(bytes.Buffer)

		filename := fmt.Sprintf("templates/%s", tt.file)
		err := tmpl.Execute(buf, tt.app)
		assert.NoError(t, err)

		expected, err := ioutil.ReadFile(filename)
		assert.NoError(t, err)

		assert.Equal(t, string(expected), buf.String())
		ioutil.WriteFile(filename, buf.Bytes(), 0660)
	}
}
Пример #4
0
func TestEmpireTemplate(t *testing.T) {
	tests := []struct {
		file string
		app  *scheduler.App
	}{
		{
			"basic.json",
			&scheduler.App{
				ID:      "1234",
				Release: "v1",
				Name:    "acme-inc",
				Env: map[string]string{
					// These should get re-sorted in
					// alphabetical order.
					"C": "foo",
					"A": "foobar",
					"B": "bar",
				},
				Processes: []*scheduler.Process{
					{
						Type:    "web",
						Image:   image.Image{Repository: "remind101/acme-inc", Tag: "latest"},
						Command: []string{"./bin/web"},
						Env: map[string]string{
							"PORT": "8080",
						},
						Exposure: &scheduler.Exposure{
							Ports: []scheduler.Port{
								{
									Host:      80,
									Container: 8080,
									Protocol:  &scheduler.HTTP{},
								},
							},
						},
						Labels: map[string]string{
							"empire.app.process": "web",
						},
						MemoryLimit: 128 * bytesize.MB,
						CPUShares:   256,
						Instances:   1,
						Nproc:       256,
					},
					{
						Type:    "worker",
						Image:   image.Image{Repository: "remind101/acme-inc", Tag: "latest"},
						Command: []string{"./bin/worker"},
						Labels: map[string]string{
							"empire.app.process": "worker",
						},
						Env: map[string]string{
							"FOO": "BAR",
						},
					},
				},
			},
		},

		{
			"basic-alb.json",
			&scheduler.App{
				ID:      "1234",
				Release: "v1",
				Name:    "acme-inc",
				Env: map[string]string{
					// These should get re-sorted in
					// alphabetical order.
					"C": "foo",
					"A": "foobar",
					"B": "bar",

					"LOAD_BALANCER_TYPE": "alb",
				},
				Processes: []*scheduler.Process{
					{
						Type:    "web",
						Image:   image.Image{Repository: "remind101/acme-inc", Tag: "latest"},
						Command: []string{"./bin/web"},
						Exposure: &scheduler.Exposure{
							Ports: []scheduler.Port{
								{
									Host:      80,
									Container: 8080,
									Protocol:  &scheduler.HTTP{},
								},
							},
						},
						Labels: map[string]string{
							"empire.app.process": "web",
						},
						Env: map[string]string{
							"PORT": "8080",
						},
						MemoryLimit: 128 * bytesize.MB,
						CPUShares:   256,
						Instances:   1,
						Nproc:       256,
					},
					{
						Type:    "worker",
						Image:   image.Image{Repository: "remind101/acme-inc", Tag: "latest"},
						Command: []string{"./bin/worker"},
						Labels: map[string]string{
							"empire.app.process": "worker",
						},
						Env: map[string]string{
							"FOO": "BAR",
						},
					},
				},
			},
		},

		{
			"https.json",
			&scheduler.App{
				ID:      "1234",
				Release: "v1",
				Name:    "acme-inc",
				Processes: []*scheduler.Process{
					{
						Type:    "web",
						Command: []string{"./bin/web"},
						Env: map[string]string{
							"PORT": "8080",
						},
						Exposure: &scheduler.Exposure{
							Ports: []scheduler.Port{
								{
									Host:      80,
									Container: 8080,
									Protocol:  &scheduler.HTTP{},
								},
								{
									Host:      443,
									Container: 8080,
									Protocol: &scheduler.HTTPS{
										Cert: "arn:aws:iam::012345678901:server-certificate/AcmeIncDotCom",
									},
								},
							},
						},
					},
					{
						Type:    "api",
						Command: []string{"./bin/api"},
						Env: map[string]string{
							"PORT": "8080",
						},
						Exposure: &scheduler.Exposure{
							Ports: []scheduler.Port{
								{
									Host:      80,
									Container: 8080,
									Protocol:  &scheduler.HTTP{},
								},
								{
									Host:      443,
									Container: 8080,
									Protocol: &scheduler.HTTPS{
										Cert: "AcmeIncDotCom", // Simple cert format.
									},
								},
							},
						},
					},
				},
			},
		},

		{
			"https-alb.json",
			&scheduler.App{
				ID:      "1234",
				Release: "v1",
				Name:    "acme-inc",
				Processes: []*scheduler.Process{
					{
						Type:    "web",
						Command: []string{"./bin/web"},
						Labels: map[string]string{
							"empire.app.process": "web",
						},
						Env: map[string]string{
							"PORT":               "8080",
							"LOAD_BALANCER_TYPE": "alb",
						},
						Exposure: &scheduler.Exposure{
							Ports: []scheduler.Port{
								{
									Host:      80,
									Container: 8080,
									Protocol:  &scheduler.HTTP{},
								},
								{
									Host:      443,
									Container: 8080,
									Protocol: &scheduler.HTTPS{
										Cert: "arn:aws:iam::012345678901:server-certificate/AcmeIncDotCom",
									},
								},
							},
						},
					},
					{
						Type:    "api",
						Command: []string{"./bin/api"},
						Labels: map[string]string{
							"empire.app.process": "api",
						},
						Env: map[string]string{
							"PORT": "8080",
							"EMPIRE_X_LOAD_BALANCER_TYPE": "alb",
						},
						Exposure: &scheduler.Exposure{
							Ports: []scheduler.Port{
								{
									Host:      80,
									Container: 8080,
									Protocol:  &scheduler.HTTP{},
								},
								{
									Host:      443,
									Container: 8080,
									Protocol: &scheduler.HTTPS{
										Cert: "AcmeIncDotCom", // Simple cert format
									},
								},
							},
						},
					},
				},
			},
		},

		{
			"custom.json",
			&scheduler.App{
				ID:      "1234",
				Release: "v1",
				Name:    "acme-inc",
				Env: map[string]string{
					"ECS_TASK_DEFINITION": "custom",
				},
				Processes: []*scheduler.Process{
					{
						Type:    "web",
						Image:   image.Image{Repository: "remind101/acme-inc", Tag: "latest"},
						Command: []string{"./bin/web"},
						Env: map[string]string{
							"B":    "foo",
							"A":    "foo",
							"FOO":  "bar",
							"PORT": "8080",
						},
						Exposure: &scheduler.Exposure{
							Ports: []scheduler.Port{
								{
									Host:      80,
									Container: 8080,
									Protocol:  &scheduler.HTTP{},
								},
							},
						},
						Labels: map[string]string{
							"empire.app.process": "web",
						},
						MemoryLimit: 128 * bytesize.MB,
						CPUShares:   256,
						Instances:   1,
						Nproc:       256,
					},
					{
						Type:      "vacuum",
						Image:     image.Image{Repository: "remind101/acme-inc", Tag: "latest"},
						Command:   []string{"./bin/vacuum"},
						Schedule:  scheduler.CRONSchedule("* * * * *"),
						Instances: 1,
						Labels: map[string]string{
							"empire.app.process": "vacuum",
						},
						MemoryLimit: 128 * bytesize.MB,
						CPUShares:   256,
						Nproc:       256,
					},
				},
			},
		},

		{
			"cron.json",
			&scheduler.App{
				ID:      "1234",
				Release: "v1",
				Name:    "acme-inc",
				Processes: []*scheduler.Process{
					{
						Type:      "send-emails",
						Image:     image.Image{Repository: "remind101/acme-inc", Tag: "latest"},
						Command:   []string{"./bin/send-emails"},
						Schedule:  scheduler.CRONSchedule("* * * * *"),
						Instances: 1,
						Labels: map[string]string{
							"empire.app.process": "send-emails",
						},
						MemoryLimit: 128 * bytesize.MB,
						CPUShares:   256,
						Nproc:       256,
					},
					{
						Type:      "vacuum",
						Image:     image.Image{Repository: "remind101/acme-inc", Tag: "latest"},
						Command:   []string{"./bin/vacuum"},
						Schedule:  scheduler.CRONSchedule("* * * * *"),
						Instances: 0,
						Labels: map[string]string{
							"empire.app.process": "vacuum",
						},
						MemoryLimit: 128 * bytesize.MB,
						CPUShares:   256,
						Nproc:       256,
					},
				},
			},
		},
	}

	stackTags := []*cloudformation.Tag{
		{Key: aws.String("environment"), Value: aws.String("test")},
	}

	for _, tt := range tests {
		t.Run(tt.file, func(t *testing.T) {
			tmpl := newTemplate()
			tmpl.NoCompress = true
			buf := new(bytes.Buffer)

			filename := fmt.Sprintf("templates/%s", tt.file)
			data := &TemplateData{tt.app, stackTags}
			err := tmpl.Execute(buf, data)
			if assert.NoError(t, err) {
				expected, err := ioutil.ReadFile(filename)
				assert.NoError(t, err)

				if got, want := buf.String(), string(expected); got != want {
					ioutil.WriteFile(filename, buf.Bytes(), 0660)
					t.Errorf("expected generated template to match existing %s. Wrote to %s", tt.file, filename)
				}
			}
		})
	}
}
Пример #5
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)
}