func TestDownloadAgentMD5Mismatch(t *testing.T) {
	mockCtrl := gomock.NewController(t)
	defer mockCtrl.Finish()

	md5response := &http.Response{}
	md5sum := "md5sum"
	tarballResponse := &http.Response{
		StatusCode: 200,
		Body:       ioutil.NopCloser(&bytes.Buffer{}),
	}

	mockFS := NewMockfileSystem(mockCtrl)
	mockFS.EXPECT().MkdirAll(config.CacheDirectory(), os.ModeDir|0700)
	mockGetter := NewMockhttpGetter(mockCtrl)
	mockGetter.EXPECT().Get(config.AgentRemoteTarballMD5()).Return(md5response, nil)
	mockFS.EXPECT().ReadAll(md5response.Body).Return([]byte(md5sum), nil)
	mockGetter.EXPECT().Get(config.AgentRemoteTarball()).Return(tarballResponse, nil)
	tempfile, err := ioutil.TempFile("", "test")
	if err != nil {
		t.Fail()
	}
	defer tempfile.Close()
	mockFS.EXPECT().TempFile("", "ecs-agent.tar").Return(tempfile, nil)
	mockFS.EXPECT().TeeReader(tarballResponse.Body, gomock.Any())
	mockFS.EXPECT().Copy(tempfile, gomock.Any()).Return(int64(0), nil)
	mockFS.EXPECT().Remove(tempfile.Name())

	d := &Downloader{
		getter: mockGetter,
		fs:     mockFS,
	}

	d.DownloadAgent()
}
Exemple #2
0
func (c *Client) getContainerConfig() *godocker.Config {

	// default environment variables
	envVariables := map[string]string{
		"ECS_LOGFILE":                   logDir + "/" + config.AgentLogFile,
		"ECS_DATADIR":                   dataDir,
		"ECS_AGENT_CONFIG_FILE_PATH":    config.AgentJSONConfigFile(),
		"ECS_UPDATE_DOWNLOAD_DIR":       config.CacheDirectory(),
		"ECS_UPDATES_ENABLED":           "true",
		"ECS_AVAILABLE_LOGGING_DRIVERS": "[\"json-file\",\"syslog\"]",
	}

	// merge in user-supplied environment variables
	for envKey, envValue := range c.loadEnvVariables() {
		envVariables[envKey] = envValue
	}

	var env []string
	for envKey, envValue := range envVariables {
		env = append(env, envKey+"="+envValue)
	}

	exposedPorts := map[godocker.Port]struct{}{
		agentIntrospectionPort + "/tcp": struct{}{},
	}

	return &godocker.Config{
		Env:          env,
		ExposedPorts: exposedPorts,
		Image:        config.AgentImageName,
	}
}
func TestDownloadAgentTempFile(t *testing.T) {
	mockCtrl := gomock.NewController(t)
	defer mockCtrl.Finish()

	md5response := &http.Response{}
	md5sum := "md5sum"
	tarballResponse := &http.Response{
		StatusCode: 200,
		Body:       ioutil.NopCloser(&bytes.Buffer{}),
	}

	mockFS := NewMockfileSystem(mockCtrl)
	mockFS.EXPECT().MkdirAll(config.CacheDirectory(), os.ModeDir|0700)
	mockGetter := NewMockhttpGetter(mockCtrl)
	mockGetter.EXPECT().Get(config.AgentRemoteTarballMD5()).Return(md5response, nil)
	mockFS.EXPECT().ReadAll(md5response.Body).Return([]byte(md5sum), nil)
	mockGetter.EXPECT().Get(config.AgentRemoteTarball()).Return(tarballResponse, nil)
	mockFS.EXPECT().TempFile("", "ecs-agent.tar").Return(nil, errors.New("test error"))

	d := &Downloader{
		getter: mockGetter,
		fs:     mockFS,
	}

	d.DownloadAgent()
}
Exemple #4
0
func (d *Downloader) getDesiredImageFile() (string, error) {
	file, err := d.fs.Open(config.DesiredImageLocatorFile())
	if err != nil {
		return "", err
	}
	defer file.Close()
	reader := bufio.NewReader(file)
	desiredImageString, err := reader.ReadString('\n')
	if err != nil {
		return "", err
	}
	desiredImageFile := strings.TrimSpace(config.CacheDirectory() + "/" + d.fs.Base(desiredImageString))
	return desiredImageFile, nil
}
Exemple #5
0
func (c *Client) getHostConfig() *godocker.HostConfig {
	binds := []string{
		defaultDockerEndpoint + ":" + defaultDockerEndpoint,
		config.LogDirectory() + ":" + logDir,
		config.AgentDataDirectory() + ":" + dataDir,
		config.AgentConfigDirectory() + ":" + config.AgentConfigDirectory(),
		config.CacheDirectory() + ":" + config.CacheDirectory(),
		config.CgroupDirectory() + ":" + config.CgroupDirectory() + readOnly,
		config.ExecDriverDirectory() + ":" + execDriverDir + readOnly,
	}
	portBindings := map[godocker.Port][]godocker.PortBinding{
		agentIntrospectionPort + "/tcp": []godocker.PortBinding{
			godocker.PortBinding{
				HostIP:   "127.0.0.1",
				HostPort: agentIntrospectionPort,
			},
		},
	}
	return &godocker.HostConfig{
		Binds:        binds,
		PortBindings: portBindings,
	}
}
func TestDownloadAgentMkdirFailure(t *testing.T) {
	mockCtrl := gomock.NewController(t)
	defer mockCtrl.Finish()

	mockFS := NewMockfileSystem(mockCtrl)

	mockFS.EXPECT().MkdirAll(config.CacheDirectory(), os.ModeDir|0700).Return(errors.New("test error"))

	d := &Downloader{
		fs: mockFS,
	}

	d.DownloadAgent()
}
Exemple #7
0
// DownloadAgent downloads a fresh copy of the Agent and performs an
// integrity check on the downloaded image
func (d *Downloader) DownloadAgent() error {
	err := d.fs.MkdirAll(config.CacheDirectory(), os.ModeDir|orwPerm)
	if err != nil {
		return err
	}

	publishedMd5Sum, err := d.getPublishedMd5Sum()
	if err != nil {
		return err
	}

	publishedTarballReader, err := d.getPublishedTarball()
	if err != nil {
		return err
	}
	defer publishedTarballReader.Close()

	md5hash := md5.New()
	tempFile, err := d.fs.TempFile("", "ecs-agent.tar")
	if err != nil {
		return err
	}
	log.Debugf("Temp file %s", tempFile.Name())
	defer func() {
		if err != nil {
			log.Debugf("Removing temp file %s", tempFile.Name())
			d.fs.Remove(tempFile.Name())
		}
	}()
	defer tempFile.Close()

	teeReader := d.fs.TeeReader(publishedTarballReader, md5hash)
	_, err = d.fs.Copy(tempFile, teeReader)
	if err != nil {
		return err
	}

	calculatedMd5Sum := md5hash.Sum(nil)
	calculatedMd5SumString := fmt.Sprintf("%x", calculatedMd5Sum)
	log.Debugf("Expected %s", publishedMd5Sum)
	log.Debugf("Calculated %s", calculatedMd5SumString)
	if publishedMd5Sum != calculatedMd5SumString {
		err = fmt.Errorf("mismatched md5sum while downloading %s", config.AgentRemoteTarball())
		return err
	}

	log.Debugf("Attempting to rename %s to %s", tempFile.Name(), config.AgentTarball())
	return d.fs.Rename(tempFile.Name(), config.AgentTarball())
}
func TestDownloadAgentDownloadMD5Failure(t *testing.T) {
	mockCtrl := gomock.NewController(t)
	defer mockCtrl.Finish()

	mockFS := NewMockfileSystem(mockCtrl)
	mockGetter := NewMockhttpGetter(mockCtrl)

	mockFS.EXPECT().MkdirAll(config.CacheDirectory(), os.ModeDir|0700)
	mockGetter.EXPECT().Get(config.AgentRemoteTarballMD5()).Return(nil, errors.New("test error"))

	d := &Downloader{
		getter: mockGetter,
		fs:     mockFS,
	}

	d.DownloadAgent()
}
func TestLoadDesiredAgent(t *testing.T) {
	mockCtrl := gomock.NewController(t)
	defer mockCtrl.Finish()

	desiredImage := "my-new-agent-image"

	mockFS := NewMockfileSystem(mockCtrl)

	mockFS.EXPECT().Open(config.DesiredImageLocatorFile()).Return(ioutil.NopCloser(bytes.NewBufferString(desiredImage+"\n")), nil)
	mockFS.EXPECT().Base(gomock.Any()).Return(desiredImage + "\n")
	mockFS.EXPECT().Open(config.CacheDirectory() + "/" + desiredImage)

	d := &Downloader{
		fs: mockFS,
	}

	d.LoadDesiredAgent()
}
Exemple #10
0
func (c *Client) getContainerConfig() *godocker.Config {
	env := append(c.loadEnvVariables(),
		"ECS_LOGFILE="+logDir+"/"+config.AgentLogFile,
		"ECS_DATADIR="+dataDir,
		"ECS_AGENT_CONFIG_FILE_PATH="+config.AgentJSONConfigFile(),
		"ECS_UPDATE_DOWNLOAD_DIR="+config.CacheDirectory(),
		"ECS_UPDATES_ENABLED=true",
	)

	exposedPorts := map[godocker.Port]struct{}{
		agentIntrospectionPort + "/tcp": struct{}{},
	}

	return &godocker.Config{
		Env:          env,
		ExposedPorts: exposedPorts,
		Image:        config.AgentImageName,
	}
}
func TestDownloadAgentDownloadTarballFailure(t *testing.T) {
	mockCtrl := gomock.NewController(t)
	defer mockCtrl.Finish()

	md5response := &http.Response{}
	md5sum := "md5sum"

	mockFS := NewMockfileSystem(mockCtrl)
	mockFS.EXPECT().MkdirAll(config.CacheDirectory(), os.ModeDir|0700)
	mockGetter := NewMockhttpGetter(mockCtrl)
	mockGetter.EXPECT().Get(config.AgentRemoteTarballMD5()).Return(md5response, nil)
	mockFS.EXPECT().ReadAll(md5response.Body).Return([]byte(md5sum), nil)
	mockGetter.EXPECT().Get(config.AgentRemoteTarball()).Return(nil, errors.New("test error"))

	d := &Downloader{
		getter: mockGetter,
		fs:     mockFS,
	}

	d.DownloadAgent()
}
func TestDownloadAgentReadPublishedMd5Failure(t *testing.T) {
	mockCtrl := gomock.NewController(t)
	defer mockCtrl.Finish()

	md5response := &http.Response{
		Body: ioutil.NopCloser(&bytes.Buffer{}),
	}

	mockFS := NewMockfileSystem(mockCtrl)
	mockFS.EXPECT().MkdirAll(config.CacheDirectory(), os.ModeDir|0700)
	mockGetter := NewMockhttpGetter(mockCtrl)
	mockGetter.EXPECT().Get(config.AgentRemoteTarballMD5()).Return(md5response, nil)
	mockFS.EXPECT().ReadAll(md5response.Body).Return(nil, errors.New("test error"))

	d := &Downloader{
		getter: mockGetter,
		fs:     mockFS,
	}

	d.DownloadAgent()
}
func TestDownloadAgentSuccess(t *testing.T) {
	mockCtrl := gomock.NewController(t)
	defer mockCtrl.Finish()

	tarballContents := "tarball contents"
	tarballResponse := &http.Response{
		StatusCode: 200,
		Body:       ioutil.NopCloser(bytes.NewBufferString(tarballContents)),
	}
	expectedMd5Sum := fmt.Sprintf("%x\n", md5.Sum([]byte(tarballContents)))
	md5response := &http.Response{}

	mockFS := NewMockfileSystem(mockCtrl)
	mockFS.EXPECT().MkdirAll(config.CacheDirectory(), os.ModeDir|0700)
	mockGetter := NewMockhttpGetter(mockCtrl)
	mockGetter.EXPECT().Get(config.AgentRemoteTarballMD5()).Return(md5response, nil)
	mockFS.EXPECT().ReadAll(md5response.Body).Return([]byte(expectedMd5Sum), nil)
	mockGetter.EXPECT().Get(config.AgentRemoteTarball()).Return(tarballResponse, nil)
	tempfile, err := ioutil.TempFile("", "test")
	if err != nil {
		t.Fail()
	}
	defer tempfile.Close()
	mockFS.EXPECT().TempFile("", "ecs-agent.tar").Return(tempfile, nil)
	mockFS.EXPECT().TeeReader(tarballResponse.Body, gomock.Any()).Do(func(reader io.Reader, writer io.Writer) {
		_, err = io.Copy(writer, reader)
		if err != nil {
			t.Fail()
		}
	})
	mockFS.EXPECT().Copy(tempfile, gomock.Any()).Return(int64(0), nil)
	mockFS.EXPECT().Rename(tempfile.Name(), config.AgentTarball())

	d := &Downloader{
		getter: mockGetter,
		fs:     mockFS,
	}

	d.DownloadAgent()
}
func validateCommonCreateContainerOptions(opts godocker.CreateContainerOptions, t *testing.T) {
	if opts.Name != "ecs-agent" {
		t.Errorf("Expected container Name to be %s but was %s", "ecs-agent", opts.Name)
	}
	cfg := opts.Config

	if len(cfg.Env) < 3 {
		t.Errorf("Expected at least 3 elements to be in Env, but was %d", len(cfg.Env))
	}
	envVariables := make(map[string]struct{})
	for _, envVar := range cfg.Env {
		envVariables[envVar] = struct{}{}
	}
	expectKey("ECS_DATADIR=/data", envVariables, t)
	expectKey("ECS_LOGFILE=/log/"+config.AgentLogFile, envVariables, t)
	expectKey("ECS_AGENT_CONFIG_FILE_PATH="+config.AgentJSONConfigFile(), envVariables, t)
	expectKey("ECS_UPDATE_DOWNLOAD_DIR="+config.CacheDirectory(), envVariables, t)
	expectKey("ECS_UPDATES_ENABLED=true", envVariables, t)
	expectKey(`ECS_AVAILABLE_LOGGING_DRIVERS=["json-file","syslog","awslogs"]`, envVariables, t)

	if len(cfg.ExposedPorts) != 1 {
		t.Errorf("Expected exactly 1 element to be in ExposedPorts, but was %d", len(cfg.ExposedPorts))
	}
	expectPort("51678/tcp", cfg.ExposedPorts, t)

	if cfg.Image != config.AgentImageName {
		t.Errorf("Expected image to be %s", config.AgentImageName)
	}

	hostCfg := opts.HostConfig

	if len(hostCfg.Binds) != 5 {
		t.Errorf("Expected exactly 5 elements to be in Binds, but was %d", len(hostCfg.Binds))
	}
	binds := make(map[string]struct{})
	for _, binding := range hostCfg.Binds {
		binds[binding] = struct{}{}
	}
	defaultDockerSocket, _ := config.DockerUnixSocket()
	expectKey(defaultDockerSocket+":"+defaultDockerSocket, binds, t)
	expectKey(config.LogDirectory()+":/log", binds, t)
	expectKey(config.AgentDataDirectory()+":/data", binds, t)
	expectKey(config.AgentConfigDirectory()+":"+config.AgentConfigDirectory(), binds, t)
	expectKey(config.CacheDirectory()+":"+config.CacheDirectory(), binds, t)

	if len(hostCfg.PortBindings) != 1 {
		t.Errorf("Expected exactly 1 element to be in PortBindings, but was %d", len(hostCfg.PortBindings))
	}
	if portBindings, ok := hostCfg.PortBindings["51678/tcp"]; ok {
		if len(portBindings) != 1 {
			t.Errorf("Expected exactly 1 element to be in portBindings, but was %d", len(portBindings))
		} else {
			portBinding := portBindings[0]
			if portBinding.HostIP != "127.0.0.1" {
				t.Errorf("Expected HostIP to be 127.0.0.1, but was %s", portBinding.HostIP)
			}
			if portBinding.HostPort != "51678" {
				t.Errorf("Expected HostPort to be 51678, but was %s", portBinding.HostPort)
			}
		}
	} else {
		t.Error("Expected 51678/tcp to be defined")
	}
}