func (i *Inspector) FinishMonitoring() {
	cmdResponse, err := ipc.SendContainerCmd(&messages.StopMonitor{})
	utils.WarnOn(err)
	_ = cmdResponse

	log.Debugf("'stop' response => '%v'\n", cmdResponse)
	log.Info("docker-slim: waiting for the container finish its work...")

	//for now there's only one event ("done")
	//getEvt() should timeout in two minutes (todo: pick a good timeout)
	evt, err := ipc.GetContainerEvt()
	utils.WarnOn(err)
	_ = evt
	log.Debugf("docker-slim: sensor event => '%v'\n", evt)
}
func (i *Inspector) ShutdownContainer() error {
	i.shutdownContainerChannels()

	if i.ShowContainerLogs {
		var outData bytes.Buffer
		outw := bufio.NewWriter(&outData)
		var errData bytes.Buffer
		errw := bufio.NewWriter(&errData)

		log.Debug("docker-slim: getting container logs => ", i.ContainerID)
		logsOptions := dockerapi.LogsOptions{
			Container:    i.ContainerID,
			OutputStream: outw,
			ErrorStream:  errw,
			Stdout:       true,
			Stderr:       true,
		}

		err := i.ApiClient.Logs(logsOptions)
		if err != nil {
			log.Infof("docker-slim: error getting container logs => %v - %v\n", i.ContainerID, err)
		} else {
			outw.Flush()
			errw.Flush()
			fmt.Println("docker-slim: container stdout:")
			outData.WriteTo(os.Stdout)
			fmt.Println("docker-slim: container stderr:")
			errData.WriteTo(os.Stdout)
		}
	}

	err := i.ApiClient.StopContainer(i.ContainerID, 9)
	utils.WarnOn(err)

	removeOption := dockerapi.RemoveContainerOptions{
		ID:            i.ContainerID,
		RemoveVolumes: true,
		Force:         true,
	}
	err = i.ApiClient.RemoveContainer(removeOption)
	return nil
}
示例#3
0
func OnProfile(doDebug bool,
	statePath string,
	clientConfig *config.DockerClient,
	imageRef string,
	doHttpProbe bool,
	httpProbeCmds []config.HttpProbeCmd,
	doShowContainerLogs bool,
	overrides *config.ContainerOverrides,
	volumeMounts map[string]config.VolumeMount,
	excludePaths map[string]bool,
	includePaths map[string]bool,
	continueAfter *config.ContinueAfter) {
	fmt.Printf("docker-slim: [profile] image=%v\n", imageRef)
	doRmFileArtifacts := false

	client := dockerclient.New(clientConfig)

	imageInspector, err := image.NewInspector(client, imageRef)
	utils.FailOn(err)

	log.Info("docker-slim: inspecting 'fat' image metadata...")
	err = imageInspector.Inspect()
	utils.FailOn(err)

	localVolumePath, artifactLocation := utils.PrepareSlimDirs(statePath, imageInspector.ImageInfo.ID)
	imageInspector.ArtifactLocation = artifactLocation

	log.Infof("docker-slim: [%v] 'fat' image size => %v (%v)\n",
		imageInspector.ImageInfo.ID,
		imageInspector.ImageInfo.VirtualSize,
		humanize.Bytes(uint64(imageInspector.ImageInfo.VirtualSize)))

	log.Info("docker-slim: processing 'fat' image info...")
	err = imageInspector.ProcessCollectedData()
	utils.FailOn(err)

	containerInspector, err := container.NewInspector(client,
		imageInspector,
		localVolumePath,
		overrides,
		doShowContainerLogs,
		volumeMounts,
		excludePaths,
		includePaths,
		doDebug)
	utils.FailOn(err)

	log.Info("docker-slim: starting instrumented 'fat' container...")
	err = containerInspector.RunContainer()
	utils.FailOn(err)

	log.Info("docker-slim: watching container monitor...")

	if "probe" == continueAfter.Mode {
		doHttpProbe = true
	}

	if doHttpProbe {
		probe, err := http.NewCustomProbe(containerInspector, httpProbeCmds)
		utils.FailOn(err)
		probe.Start()
		continueAfter.ContinueChan = probe.DoneChan()
	}

	switch continueAfter.Mode {
	case "enter":
		fmt.Println("docker-slim: press <enter> when you are done using the container...")
		creader := bufio.NewReader(os.Stdin)
		_, _, _ = creader.ReadLine()
	case "signal":
		fmt.Println("docker-slim: send SIGUSR1 when you are done using the container...")
		<-continueAfter.ContinueChan
		fmt.Println("docker-slim: got SIGUSR1...")
	case "timeout":
		fmt.Printf("docker-slim: waiting for the target container (%v seconds)...\n", int(continueAfter.Timeout))
		<-time.After(time.Second * continueAfter.Timeout)
		fmt.Printf("docker-slim: done waiting for the target container...")
	case "probe":
		fmt.Println("docker-slim: waiting for the HTTP probe to finish...")
		<-continueAfter.ContinueChan
		fmt.Println("docker-slim: HTTP probe is done...")
	default:
		utils.Fail("unknown continue-after mode")
	}

	containerInspector.FinishMonitoring()

	log.Info("docker-slim: shutting down 'fat' container...")
	err = containerInspector.ShutdownContainer()
	utils.WarnOn(err)

	log.Info("docker-slim: processing instrumented 'fat' container info...")
	err = containerInspector.ProcessCollectedData()
	utils.FailOn(err)

	if doRmFileArtifacts {
		log.Info("docker-slim: removing temporary artifacts...")
		err = utils.RemoveArtifacts(artifactLocation) //TODO: remove only the "files" subdirectory
		utils.WarnOn(err)
	}

	fmt.Println("docker-slim: [profile] done.")
}
示例#4
0
func New(config *config.DockerClient) *docker.Client {
	var client *docker.Client
	var err error

	newTLSClient := func(host string, certPath string, verify bool) (*docker.Client, error) {
		var ca []byte

		cert, err := ioutil.ReadFile(filepath.Join(certPath, "cert.pem"))
		if err != nil {
			return nil, err
		}

		key, err := ioutil.ReadFile(filepath.Join(certPath, "key.pem"))
		if err != nil {
			return nil, err
		}

		if verify {
			var err error
			ca, err = ioutil.ReadFile(filepath.Join(certPath, "ca.pem"))
			if err != nil {
				return nil, err
			}
		}

		return docker.NewVersionedTLSClientFromBytes(host, cert, key, ca, "")
	}

	switch {
	case config.Host != "" &&
		config.UseTLS &&
		config.VerifyTLS &&
		config.TLSCertPath != "":
		client, err = newTLSClient(config.Host, config.TLSCertPath, true)
		utils.FailOn(err)
		log.Debug("docker-slim: new Docker client (TLS,verify) [1]")

	case config.Host != "" &&
		config.UseTLS &&
		!config.VerifyTLS &&
		config.TLSCertPath != "":
		client, err = newTLSClient(config.Host, config.TLSCertPath, false)
		utils.FailOn(err)
		log.Debug("docker-slim: new Docker client (TLS,no verify) [2]")

	case config.Host != "" &&
		!config.UseTLS:
		client, err = docker.NewClient(config.Host)
		utils.FailOn(err)
		log.Debug("docker-slim: new Docker client [3]")

	case config.Host == "" &&
		!config.VerifyTLS &&
		config.Env["DOCKER_TLS_VERIFY"] == "1" &&
		config.Env["DOCKER_CERT_PATH"] != "" &&
		config.Env["DOCKER_HOST"] != "":
		client, err = newTLSClient(config.Env["DOCKER_HOST"], config.Env["DOCKER_CERT_PATH"], false)
		utils.FailOn(err)
		log.Debug("docker-slim: new Docker client (TLS,no verify) [4]")

	case config.Env["DOCKER_HOST"] != "":
		client, err = docker.NewClientFromEnv()
		utils.FailOn(err)
		log.Debug("docker-slim: new Docker client (env) [5]")

	case config.Host == "" && config.Env["DOCKER_HOST"] == "":
		config.Host = "unix:///var/run/docker.sock"
		client, err = docker.NewClient(config.Host)
		utils.FailOn(err)
		log.Debug("docker-slim: new Docker client (default) [6]")

	default:
		utils.Fail("no config for Docker client")
	}

	if config.Env["DOCKER_HOST"] == "" {
		if err := os.Setenv("DOCKER_HOST", config.Host); err != nil {
			utils.WarnOn(err)
		}

		log.Debug("docker-slim: configured DOCKER_HOST env var")
	}

	return client
}
示例#5
0
func main() {
	flag.Parse()

	if enableDebug {
		log.SetLevel(log.DebugLevel)
	}

	log.Infof("sensor: args => %#v\n", os.Args)

	dirName, err := os.Getwd()
	utils.WarnOn(err)
	log.Debugf("sensor: cwd => %#v\n", dirName)

	initSignalHandlers()
	defer func() {
		log.Debug("defered cleanup on shutdown...")
		cleanupOnShutdown()
	}()

	log.Debug("sensor: setting up channels...")
	doneChan = make(chan struct{})

	err = ipc.InitChannels()
	utils.FailOn(err)

	cmdChan, err := ipc.RunCmdServer(doneChan)
	utils.FailOn(err)

	monDoneChan := make(chan bool, 1)
	monDoneAckChan := make(chan bool)
	pidsChan := make(chan []int, 1)
	ptmonStartChan := make(chan int, 1)

	log.Info("sensor: waiting for commands...")
doneRunning:
	for {
		select {
		case cmd := <-cmdChan:
			log.Debug("\nsensor: command => ", cmd)
			switch data := cmd.(type) {
			case *messages.StartMonitor:
				if data == nil {
					log.Info("sensor: 'start' command - no data...")
					break
				}

				log.Debugf("sensor: 'start' command (%#v) - starting monitor...\n", data)
				monitor(monDoneChan, monDoneAckChan, pidsChan, ptmonStartChan, data, dirName)

				//target app started by ptmon... (long story :-))
				//TODO: need to get the target app pid to pemon, so it can filter process events
				log.Debugf("sensor: target app started => %v %#v\n", data.AppName, data.AppArgs)
				time.Sleep(3 * time.Second)

			case *messages.StopMonitor:
				log.Debug("sensor: 'stop' command - stopping monitor...")
				break doneRunning
			default:
				log.Debug("sensor: ignoring unknown command => ", cmd)
			}

		case <-time.After(time.Second * 5):
			log.Debug(".")
		}
	}

	monDoneChan <- true
	log.Info("sensor: waiting for monitor to finish...")
	<-monDoneAckChan

	ipc.TryPublishEvt(3, "monitor.finish.completed")

	log.Info("sensor: done!")
}