예제 #1
0
파일: cmd.go 프로젝트: jcantrill/geard
func (ctx *CommandContext) installImage(c *cobra.Command, args []string) {
	if err := ctx.environment.ExtractVariablesFrom(&args, true); err != nil {
		cmd.Fail(1, err.Error())
	}

	if len(args) < 2 {
		cmd.Fail(1, "Valid arguments: <image_name> <id> ...")
	}

	t := ctx.Transport.Get()

	imageId := args[0]
	if imageId == "" {
		cmd.Fail(1, "Argument 1 must be a Docker image to base the service on")
	}
	ids, err := cloc.NewContainerLocators(t, args[1:]...)
	if err != nil {
		cmd.Fail(1, "You must pass one or more valid service names: %s", err.Error())
	}

	for _, locator := range ids {
		if imageId == string(cloc.AsIdentifier(locator)) {
			cmd.Fail(1, "Image name and container id must not be the same: %s", imageId)
		}
	}

	cmd.Executor{
		On: ids,
		Serial: func(on cmd.Locator) cmd.JobRequest {
			r := cjobs.InstallContainerRequest{
				RequestIdentifier: jobs.NewRequestIdentifier(),

				Id:               cloc.AsIdentifier(on),
				Image:            imageId,
				Started:          ctx.start,
				Isolate:          ctx.isolate,
				SocketActivation: ctx.sockAct,

				Ports:        *ctx.portPairs.Get().(*port.PortPairs),
				Environment:  &ctx.environment.Description,
				NetworkLinks: ctx.networkLinks.NetworkLinks,
				VolumeConfig: ctx.volumeConfig.VolumeConfig,
				SystemdSlice: ctx.systemdSlice,
			}
			return &r
		},
		Output:    os.Stdout,
		Transport: t,
	}.StreamAndExit()
}
예제 #2
0
파일: cmd.go 프로젝트: pmorie/geard
func (ctx *CommandContext) restartContainer(c *cobra.Command, args []string) {
	t := ctx.Transport.Get()

	if err := ExtractContainerLocatorsFromDeployment(t, ctx.deploymentPath, &args); err != nil {
		cmd.Fail(1, err.Error())
	}
	if len(args) < 1 {
		cmd.Fail(1, "Valid arguments: <id> ...")
	}
	ids, err := cloc.NewContainerLocators(t, args...)
	if err != nil {
		cmd.Fail(1, "You must pass one or more valid service names: %s", err.Error())
	}

	cmd.Executor{
		On: ids,
		Serial: func(on cmd.Locator) cmd.JobRequest {
			return &cjobs.RestartContainerRequest{
				Id: cloc.AsIdentifier(on),
			}
		},
		Output:    os.Stdout,
		Transport: t,
	}.StreamAndExit()
}
예제 #3
0
파일: cmd.go 프로젝트: pmorie/geard
func (ctx *CommandContext) linkContainers(c *cobra.Command, args []string) {
	if len(args) < 1 {
		cmd.Fail(1, "Valid arguments: <id> ...")
	}

	t := ctx.Transport.Get()

	ids, err := cloc.NewContainerLocators(t, args...)
	if err != nil {
		cmd.Fail(1, "You must pass one or more valid service names: %s", err.Error())
	}
	if ctx.networkLinks.NetworkLinks == nil {
		ctx.networkLinks.NetworkLinks = &containers.NetworkLinks{}
	}

	cmd.Executor{
		On: ids,
		Group: func(on ...cmd.Locator) cmd.JobRequest {
			links := &containers.ContainerLinks{make([]containers.ContainerLink, 0, len(on))}
			for i := range on {
				links.Links = append(links.Links, containers.ContainerLink{cloc.AsIdentifier(on[i]), *ctx.networkLinks.NetworkLinks})
			}
			return &cjobs.LinkContainersRequest{links}
		},
		Output: os.Stdout,
		OnSuccess: func(r *cmd.CliJobResponse, w io.Writer, job cmd.RequestedJob) {
			fmt.Fprintf(w, "Links set on %s\n", job.Request.(*cjobs.LinkContainersRequest).ContainerLinks.String())
		},
		Transport: t,
	}.StreamAndExit()
}
예제 #4
0
파일: cmd.go 프로젝트: pmorie/geard
func (ctx *CommandContext) deleteContainer(c *cobra.Command, args []string) {
	t := ctx.Transport.Get()

	if err := ExtractContainerLocatorsFromDeployment(t, ctx.deploymentPath, &args); err != nil {
		cmd.Fail(1, err.Error())
	}

	if len(args) < 1 {
		cmd.Fail(1, "Valid arguments: <id> ...")
	}

	ids, err := cloc.NewContainerLocators(t, args...)
	if err != nil {
		cmd.Fail(1, "You must pass one or more valid service names: %s", err.Error())
	}

	cmd.Executor{
		On: ids,
		Serial: func(on cmd.Locator) cmd.JobRequest {
			return &cjobs.DeleteContainerRequest{
				Id: cloc.AsIdentifier(on),
			}
		},
		Output: os.Stdout,
		OnSuccess: func(r *cmd.CliJobResponse, w io.Writer, job cmd.RequestedJob) {
			fmt.Fprintf(w, "Deleted %s", string(job.Request.(*cjobs.DeleteContainerRequest).Id))
		},
		Transport: t,
	}.StreamAndExit()
}
예제 #5
0
파일: cmd.go 프로젝트: pmorie/geard
func (ctx *CommandContext) setEnvironment(c *cobra.Command, args []string) {
	if err := ctx.environment.ExtractVariablesFrom(&args, false); err != nil {
		cmd.Fail(1, err.Error())
	}

	if len(args) < 1 {
		cmd.Fail(1, "Valid arguments: <name>... <key>=<value>...")
	}

	t := ctx.Transport.Get()

	ids, err := cloc.NewContainerLocators(t, args...)
	if err != nil {
		cmd.Fail(1, "You must pass one or more valid service names: %s", err.Error())
	}

	cmd.Executor{
		On: ids,
		Serial: func(on cmd.Locator) cmd.JobRequest {
			ctx.environment.Description.Id = cloc.AsIdentifier(on)
			if ctx.resetEnv {
				return &cjobs.PutEnvironmentRequest{ctx.environment.Description}
			}

			return &cjobs.PatchEnvironmentRequest{ctx.environment.Description}
		},
		Output:    os.Stdout,
		Transport: t,
	}.StreamAndExit()
}
예제 #6
0
파일: cmd.go 프로젝트: pmorie/geard
func (ctx *CommandContext) containerStatus(c *cobra.Command, args []string) {
	t := ctx.Transport.Get()

	if err := ExtractContainerLocatorsFromDeployment(t, ctx.deploymentPath, &args); err != nil {
		cmd.Fail(1, err.Error())
	}
	if len(args) < 1 {
		cmd.Fail(1, "Valid arguments: <id> ...")
	}
	ids, err := cloc.NewContainerLocators(t, args...)
	if err != nil {
		cmd.Fail(1, "You must pass one or more valid service names: %s", err.Error())
	}

	data, errors := cmd.Executor{
		On: ids,
		Serial: func(on cmd.Locator) cmd.JobRequest {
			return &cjobs.ContainerStatusRequest{
				Id: cloc.AsIdentifier(on),
			}
		},
		Output:    os.Stdout,
		Transport: t,
	}.Gather()

	for i := range data {
		if buf, ok := data[i].(*bytes.Buffer); ok {
			if i > 0 {
				fmt.Fprintf(os.Stdout, "\n-------------\n")
			}
			buf.WriteTo(os.Stdout)
		}
	}
	if len(errors) > 0 {
		for i := range errors {
			fmt.Fprintf(os.Stderr, "Error: %s\n", errors[i])
		}
		os.Exit(1)
	}
	os.Exit(0)
}
예제 #7
0
파일: cmd.go 프로젝트: pmorie/geard
func (ctx *CommandContext) showEnvironment(c *cobra.Command, args []string) {
	if len(args) < 1 {
		cmd.Fail(1, "Valid arguments: <id> ...")
	}

	t := ctx.Transport.Get()

	ids, err := cloc.NewContainerLocators(t, args[0:]...)
	if err != nil {
		cmd.Fail(1, "You must pass one or more valid environment ids: %s", err.Error())
	}

	data, errors := cmd.Executor{
		On: ids,
		Serial: func(on cmd.Locator) cmd.JobRequest {
			return &cjobs.GetEnvironmentRequest{
				Id: cloc.AsIdentifier(on),
			}
		},
		Output:    os.Stdout,
		Transport: t,
	}.Gather()

	for i := range data {
		if buf, ok := data[i].(*bytes.Buffer); ok {
			buf.WriteTo(os.Stdout)
		}
	}
	if len(errors) > 0 {
		for i := range errors {
			fmt.Fprintf(os.Stderr, "Error: %s\n", errors[i])
		}
		os.Exit(1)
	}
	os.Exit(0)
}
예제 #8
0
파일: cmd.go 프로젝트: pmorie/geard
func (ctx *CommandContext) deployContainers(c *cobra.Command, args []string) {
	if len(args) < 1 {
		cmd.Fail(1, "Valid arguments: <deployment_file|URL> <host> ...")
	}

	t := ctx.Transport.Get()

	path := args[0]
	if path == "" {
		cmd.Fail(1, "Argument 1 must be deployment file or URL describing how the containers are related")
	}

	u, err := url.Parse(path)
	if nil != err {
		cmd.Fail(1, "Cannot Parse Argument 1: %s", err.Error())
	}

	var deploy *deployment.Deployment
	switch u.Scheme {
	case "":
		deploy, err = deployment.NewDeploymentFromFile(u.Path)
	case "file":
		deploy, err = deployment.NewDeploymentFromFile(u.Path)
	case "http", "https":
		deploy, err = deployment.NewDeploymentFromURL(u.String(), *ctx.Insecure, time.Duration(ctx.timeout))
	default:
		cmd.Fail(1, "Unsupported URL Scheme '%s' for deployment", u.Scheme)
	}

	if nil != err {
		cmd.Fail(1, "Unable to load deployment from %s: %s", path, err.Error())
	}

	if len(args) == 1 {
		args = append(args, transport.Local.String())
	}
	servers, err := transport.NewTransportLocators(t, args[1:]...)
	if err != nil {
		cmd.Fail(1, "You must pass zero or more valid host names (use '%s' or pass no arguments for the current server): %s", transport.Local.String(), err.Error())
	}

	re := regexp.MustCompile("\\.\\d{8}\\-\\d{6}\\z")
	now := time.Now().Format(".20060102-150405")
	base := filepath.Base(path)
	base = re.ReplaceAllString(base, "")
	newPath := base + now

	fmt.Printf("==> Deploying %s\n", path)
	changes, removed, err := deploy.Describe(deployment.SimplePlacement(servers), t)
	if err != nil {
		cmd.Fail(1, "Deployment is not valid: %s", err.Error())
	}

	if len(removed) > 0 {
		removedIds, err := LocatorsForDeploymentInstances(t, removed)
		if err != nil {
			cmd.Fail(1, "Unable to generate deployment info: %s", err.Error())
		}

		failures := cmd.Executor{
			On: removedIds,
			Serial: func(on cmd.Locator) cmd.JobRequest {
				return &cjobs.DeleteContainerRequest{
					Id: cloc.AsIdentifier(on),
				}
			},
			Output: os.Stdout,
			OnSuccess: func(r *cmd.CliJobResponse, w io.Writer, job cmd.RequestedJob) {
				fmt.Fprintf(w, "==> Deleted %s", string(job.Request.(*cjobs.DeleteContainerRequest).Id))
			},
			Transport: t,
		}.Stream()
		for i := range failures {
			fmt.Fprintf(os.Stderr, failures[i].Error())
		}
	}

	addedIds, err := LocatorsForDeploymentInstances(t, changes.Instances.Added())
	if err != nil {
		cmd.Fail(1, "Unable to generate deployment info: %s", err.Error())
	}

	errors := cmd.Executor{
		On: addedIds,
		Serial: func(on cmd.Locator) cmd.JobRequest {
			instance, _ := changes.Instances.Find(cloc.AsIdentifier(on))
			links := instance.NetworkLinks()

			return &cjobs.InstallContainerRequest{
				RequestIdentifier: jobs.NewRequestIdentifier(),

				Id:          instance.Id,
				Image:       instance.Image,
				Environment: instance.EnvironmentVariables(),
				Isolate:     ctx.isolate,

				Ports:        instance.Ports.PortPairs(),
				NetworkLinks: &links,
			}
		},
		OnSuccess: func(r *cmd.CliJobResponse, w io.Writer, job cmd.RequestedJob) {
			installJob := job.Request.(*cjobs.InstallContainerRequest)
			instance, _ := changes.Instances.Find(installJob.Id)
			if pairs, ok := installJob.PortMappingsFrom(r.Pending); ok {
				if !instance.Ports.Update(pairs) {
					fmt.Fprintf(os.Stderr, "Not all ports listed %+v were returned by the server %+v", instance.Ports, pairs)
				}
			}
		},
		Output:    os.Stdout,
		Transport: t,
	}.Stream()

	changes.UpdateLinks()

	for _, c := range changes.Containers {
		instances := c.Instances()
		if len(instances) > 0 {
			for _, link := range instances[0].NetworkLinks() {
				fmt.Printf("==> Linking %s: %s:%d -> %s:%d\n", c.Name, link.FromHost, link.FromPort, link.ToHost, link.ToPort)
			}
		}
	}

	contents, _ := json.MarshalIndent(changes, "", "  ")
	contents = append(contents, []byte("\n")...)
	if err := ioutil.WriteFile(newPath, contents, 0664); err != nil {
		fmt.Fprintf(os.Stderr, "Unable to write %s: %s\n", newPath, err.Error())
	}

	linkedIds, err := LocatorsForDeploymentInstances(t, changes.Instances.Linked())
	if err != nil {
		cmd.Fail(1, "Unable to generate deployment info: %s", err.Error())
	}

	cmd.Executor{
		On: linkedIds,
		Group: func(on ...cmd.Locator) cmd.JobRequest {
			links := []containers.ContainerLink{}
			for i := range on {
				instance, _ := changes.Instances.Find(cloc.AsIdentifier(on[i]))
				network := instance.NetworkLinks()
				if len(network) > 0 {
					links = append(links, containers.ContainerLink{instance.Id, network})
				}
			}

			return &cjobs.LinkContainersRequest{&containers.ContainerLinks{links}}
		},
		Output:    os.Stdout,
		Transport: t,
	}.Stream()

	cmd.Executor{
		On: addedIds,
		Serial: func(on cmd.Locator) cmd.JobRequest {
			return &cjobs.StartedContainerStateRequest{
				Id: cloc.AsIdentifier(on),
			}
		},
		Output:    os.Stdout,
		Transport: t,
	}.Stream()

	fmt.Printf("==> Deployed as %s\n", newPath)
	if len(errors) > 0 {
		for i := range errors {
			fmt.Fprintf(os.Stderr, "Error: %s\n", errors[i])
		}
		os.Exit(1)
	}
}