mirror of https://github.com/docker/compose.git
556 lines
18 KiB
Go
556 lines
18 KiB
Go
/*
|
|
Copyright 2020 Docker Compose CLI authors
|
|
|
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
you may not use this file except in compliance with the License.
|
|
You may obtain a copy of the License at
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
See the License for the specific language governing permissions and
|
|
limitations under the License.
|
|
*/
|
|
|
|
package api
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/compose-spec/compose-go/types"
|
|
"github.com/docker/compose/v2/pkg/utils"
|
|
)
|
|
|
|
// Service manages a compose project
|
|
type Service interface {
|
|
// Build executes the equivalent to a `compose build`
|
|
Build(ctx context.Context, project *types.Project, options BuildOptions) error
|
|
// Push executes the equivalent to a `compose push`
|
|
Push(ctx context.Context, project *types.Project, options PushOptions) error
|
|
// Pull executes the equivalent of a `compose pull`
|
|
Pull(ctx context.Context, project *types.Project, options PullOptions) error
|
|
// Create executes the equivalent to a `compose create`
|
|
Create(ctx context.Context, project *types.Project, options CreateOptions) error
|
|
// Start executes the equivalent to a `compose start`
|
|
Start(ctx context.Context, projectName string, options StartOptions) error
|
|
// Restart restarts containers
|
|
Restart(ctx context.Context, projectName string, options RestartOptions) error
|
|
// Stop executes the equivalent to a `compose stop`
|
|
Stop(ctx context.Context, projectName string, options StopOptions) error
|
|
// Up executes the equivalent to a `compose up`
|
|
Up(ctx context.Context, project *types.Project, options UpOptions) error
|
|
// Down executes the equivalent to a `compose down`
|
|
Down(ctx context.Context, projectName string, options DownOptions) error
|
|
// Logs executes the equivalent to a `compose logs`
|
|
Logs(ctx context.Context, projectName string, consumer LogConsumer, options LogOptions) error
|
|
// Ps executes the equivalent to a `compose ps`
|
|
Ps(ctx context.Context, projectName string, options PsOptions) ([]ContainerSummary, error)
|
|
// List executes the equivalent to a `docker stack ls`
|
|
List(ctx context.Context, options ListOptions) ([]Stack, error)
|
|
// Convert translate compose model into backend's native format
|
|
Config(ctx context.Context, project *types.Project, options ConfigOptions) ([]byte, error)
|
|
// Kill executes the equivalent to a `compose kill`
|
|
Kill(ctx context.Context, projectName string, options KillOptions) error
|
|
// RunOneOffContainer creates a service oneoff container and starts its dependencies
|
|
RunOneOffContainer(ctx context.Context, project *types.Project, opts RunOptions) (int, error)
|
|
// Remove executes the equivalent to a `compose rm`
|
|
Remove(ctx context.Context, projectName string, options RemoveOptions) error
|
|
// Exec executes a command in a running service container
|
|
Exec(ctx context.Context, projectName string, options RunOptions) (int, error)
|
|
// Copy copies a file/folder between a service container and the local filesystem
|
|
Copy(ctx context.Context, projectName string, options CopyOptions) error
|
|
// Pause executes the equivalent to a `compose pause`
|
|
Pause(ctx context.Context, projectName string, options PauseOptions) error
|
|
// UnPause executes the equivalent to a `compose unpause`
|
|
UnPause(ctx context.Context, projectName string, options PauseOptions) error
|
|
// Top executes the equivalent to a `compose top`
|
|
Top(ctx context.Context, projectName string, services []string) ([]ContainerProcSummary, error)
|
|
// Events executes the equivalent to a `compose events`
|
|
Events(ctx context.Context, projectName string, options EventsOptions) error
|
|
// Port executes the equivalent to a `compose port`
|
|
Port(ctx context.Context, projectName string, service string, port uint16, options PortOptions) (string, int, error)
|
|
// Images executes the equivalent of a `compose images`
|
|
Images(ctx context.Context, projectName string, options ImagesOptions) ([]ImageSummary, error)
|
|
// MaxConcurrency defines upper limit for concurrent operations against engine API
|
|
MaxConcurrency(parallel int)
|
|
// DryRunMode defines if dry run applies to the command
|
|
DryRunMode(ctx context.Context, dryRun bool) (context.Context, error)
|
|
// Watch services' development context and sync/notify/rebuild/restart on changes
|
|
Watch(ctx context.Context, project *types.Project, services []string, options WatchOptions) error
|
|
// Viz generates a graphviz graph of the project services
|
|
Viz(ctx context.Context, project *types.Project, options VizOptions) (string, error)
|
|
}
|
|
|
|
type VizOptions struct {
|
|
// IncludeNetworks if true, network names a container is attached to should appear in the graph node
|
|
IncludeNetworks bool
|
|
// IncludePorts if true, ports a container exposes should appear in the graph node
|
|
IncludePorts bool
|
|
// IncludeImageName if true, name of the image used to create a container should appear in the graph node
|
|
IncludeImageName bool
|
|
// Indentation string to be used to indent graphviz code, e.g. "\t", " "
|
|
Indentation string
|
|
}
|
|
|
|
// WatchOptions group options of the Watch API
|
|
type WatchOptions struct {
|
|
}
|
|
|
|
// BuildOptions group options of the Build API
|
|
type BuildOptions struct {
|
|
// Pull always attempt to pull a newer version of the image
|
|
Pull bool
|
|
// Push pushes service images
|
|
Push bool
|
|
// Progress set type of progress output ("auto", "plain", "tty")
|
|
Progress string
|
|
// Args set build-time args
|
|
Args types.MappingWithEquals
|
|
// NoCache disables cache use
|
|
NoCache bool
|
|
// Quiet make the build process not output to the console
|
|
Quiet bool
|
|
// Services passed in the command line to be built
|
|
Services []string
|
|
// Ssh authentications passed in the command line
|
|
SSHs []types.SSHKey
|
|
// Memory limit for the build container
|
|
Memory int64
|
|
}
|
|
|
|
// Apply mutates project according to build options
|
|
func (o BuildOptions) Apply(project *types.Project) error {
|
|
platform := project.Environment["DOCKER_DEFAULT_PLATFORM"]
|
|
for i, service := range project.Services {
|
|
if service.Image == "" && service.Build == nil {
|
|
return fmt.Errorf("invalid service %q. Must specify either image or build", service.Name)
|
|
}
|
|
|
|
if service.Build == nil {
|
|
continue
|
|
}
|
|
service.Image = GetImageNameOrDefault(service, project.Name)
|
|
if platform != "" {
|
|
if len(service.Build.Platforms) > 0 && !utils.StringContains(service.Build.Platforms, platform) {
|
|
return fmt.Errorf("service %q build.platforms does not support value set by DOCKER_DEFAULT_PLATFORM: %s", service.Name, platform)
|
|
}
|
|
service.Platform = platform
|
|
}
|
|
if service.Platform != "" {
|
|
if len(service.Build.Platforms) > 0 && !utils.StringContains(service.Build.Platforms, service.Platform) {
|
|
return fmt.Errorf("service %q build configuration does not support platform: %s", service.Name, service.Platform)
|
|
}
|
|
}
|
|
|
|
service.Build.Pull = service.Build.Pull || o.Pull
|
|
service.Build.NoCache = service.Build.NoCache || o.NoCache
|
|
|
|
project.Services[i] = service
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// CreateOptions group options of the Create API
|
|
type CreateOptions struct {
|
|
// Services defines the services user interacts with
|
|
Services []string
|
|
// Remove legacy containers for services that are not defined in the project
|
|
RemoveOrphans bool
|
|
// Ignore legacy containers for services that are not defined in the project
|
|
IgnoreOrphans bool
|
|
// Recreate define the strategy to apply on existing containers
|
|
Recreate string
|
|
// RecreateDependencies define the strategy to apply on dependencies services
|
|
RecreateDependencies string
|
|
// Inherit reuse anonymous volumes from previous container
|
|
Inherit bool
|
|
// Timeout set delay to wait for container to gracelfuly stop before sending SIGKILL
|
|
Timeout *time.Duration
|
|
// QuietPull makes the pulling process quiet
|
|
QuietPull bool
|
|
}
|
|
|
|
// StartOptions group options of the Start API
|
|
type StartOptions struct {
|
|
// Project is the compose project used to define this app. Might be nil if user ran command just with project name
|
|
Project *types.Project
|
|
// Attach to container and forward logs if not nil
|
|
Attach LogConsumer
|
|
// AttachTo set the services to attach to
|
|
AttachTo []string
|
|
// CascadeStop stops the application when a container stops
|
|
CascadeStop bool
|
|
// ExitCodeFrom return exit code from specified service
|
|
ExitCodeFrom string
|
|
// Wait won't return until containers reached the running|healthy state
|
|
Wait bool
|
|
WaitTimeout time.Duration
|
|
// Services passed in the command line to be started
|
|
Services []string
|
|
}
|
|
|
|
// RestartOptions group options of the Restart API
|
|
type RestartOptions struct {
|
|
// Project is the compose project used to define this app. Might be nil if user ran command just with project name
|
|
Project *types.Project
|
|
// Timeout override container restart timeout
|
|
Timeout *time.Duration
|
|
// Services passed in the command line to be restarted
|
|
Services []string
|
|
}
|
|
|
|
// StopOptions group options of the Stop API
|
|
type StopOptions struct {
|
|
// Project is the compose project used to define this app. Might be nil if user ran command just with project name
|
|
Project *types.Project
|
|
// Timeout override container stop timeout
|
|
Timeout *time.Duration
|
|
// Services passed in the command line to be stopped
|
|
Services []string
|
|
}
|
|
|
|
// UpOptions group options of the Up API
|
|
type UpOptions struct {
|
|
Create CreateOptions
|
|
Start StartOptions
|
|
}
|
|
|
|
// DownOptions group options of the Down API
|
|
type DownOptions struct {
|
|
// RemoveOrphans will cleanup containers that are not declared on the compose model but own the same labels
|
|
RemoveOrphans bool
|
|
// Project is the compose project used to define this app. Might be nil if user ran `down` just with project name
|
|
Project *types.Project
|
|
// Timeout override container stop timeout
|
|
Timeout *time.Duration
|
|
// Images remove image used by services. 'all': Remove all images. 'local': Remove only images that don't have a tag
|
|
Images string
|
|
// Volumes remove volumes, both declared in the `volumes` section and anonymous ones
|
|
Volumes bool
|
|
}
|
|
|
|
// ConfigOptions group options of the Config API
|
|
type ConfigOptions struct {
|
|
// Format define the output format used to dump converted application model (json|yaml)
|
|
Format string
|
|
// Output defines the path to save the application model
|
|
Output string
|
|
// Resolve image reference to digests
|
|
ResolveImageDigests bool
|
|
}
|
|
|
|
// PushOptions group options of the Push API
|
|
type PushOptions struct {
|
|
Quiet bool
|
|
IgnoreFailures bool
|
|
}
|
|
|
|
// PullOptions group options of the Pull API
|
|
type PullOptions struct {
|
|
Quiet bool
|
|
IgnoreFailures bool
|
|
IgnoreBuildable bool
|
|
}
|
|
|
|
// ImagesOptions group options of the Images API
|
|
type ImagesOptions struct {
|
|
Services []string
|
|
}
|
|
|
|
// KillOptions group options of the Kill API
|
|
type KillOptions struct {
|
|
// RemoveOrphans will cleanup containers that are not declared on the compose model but own the same labels
|
|
RemoveOrphans bool
|
|
// Project is the compose project used to define this app. Might be nil if user ran command just with project name
|
|
Project *types.Project
|
|
// Services passed in the command line to be killed
|
|
Services []string
|
|
// Signal to send to containers
|
|
Signal string
|
|
}
|
|
|
|
// RemoveOptions group options of the Remove API
|
|
type RemoveOptions struct {
|
|
// Project is the compose project used to define this app. Might be nil if user ran command just with project name
|
|
Project *types.Project
|
|
// Stop option passed in the command line
|
|
Stop bool
|
|
// Volumes remove anonymous volumes
|
|
Volumes bool
|
|
// Force don't ask to confirm removal
|
|
Force bool
|
|
// Services passed in the command line to be removed
|
|
Services []string
|
|
}
|
|
|
|
// RunOptions group options of the Run API
|
|
type RunOptions struct {
|
|
// Project is the compose project used to define this app. Might be nil if user ran command just with project name
|
|
Project *types.Project
|
|
Name string
|
|
Service string
|
|
Command []string
|
|
Entrypoint []string
|
|
Detach bool
|
|
AutoRemove bool
|
|
Tty bool
|
|
Interactive bool
|
|
WorkingDir string
|
|
User string
|
|
Environment []string
|
|
Labels types.Labels
|
|
Privileged bool
|
|
UseNetworkAliases bool
|
|
NoDeps bool
|
|
// QuietPull makes the pulling process quiet
|
|
QuietPull bool
|
|
// used by exec
|
|
Index int
|
|
}
|
|
|
|
// EventsOptions group options of the Events API
|
|
type EventsOptions struct {
|
|
Services []string
|
|
Consumer func(event Event) error
|
|
}
|
|
|
|
// Event is a container runtime event served by Events API
|
|
type Event struct {
|
|
Timestamp time.Time
|
|
Service string
|
|
Container string
|
|
Status string
|
|
Attributes map[string]string
|
|
}
|
|
|
|
// PortOptions group options of the Port API
|
|
type PortOptions struct {
|
|
Protocol string
|
|
Index int
|
|
}
|
|
|
|
func (e Event) String() string {
|
|
t := e.Timestamp.Format("2006-01-02 15:04:05.000000")
|
|
var attr []string
|
|
for k, v := range e.Attributes {
|
|
attr = append(attr, fmt.Sprintf("%s=%s", k, v))
|
|
}
|
|
return fmt.Sprintf("%s container %s %s (%s)\n", t, e.Status, e.Container, strings.Join(attr, ", "))
|
|
|
|
}
|
|
|
|
// ListOptions group options of the ls API
|
|
type ListOptions struct {
|
|
All bool
|
|
}
|
|
|
|
// PsOptions group options of the Ps API
|
|
type PsOptions struct {
|
|
Project *types.Project
|
|
All bool
|
|
Services []string
|
|
}
|
|
|
|
// CopyOptions group options of the cp API
|
|
type CopyOptions struct {
|
|
Source string
|
|
Destination string
|
|
All bool
|
|
Index int
|
|
FollowLink bool
|
|
CopyUIDGID bool
|
|
}
|
|
|
|
// PortPublisher hold status about published port
|
|
type PortPublisher struct {
|
|
URL string
|
|
TargetPort int
|
|
PublishedPort int
|
|
Protocol string
|
|
}
|
|
|
|
// ContainerSummary hold high-level description of a container
|
|
type ContainerSummary struct {
|
|
ID string
|
|
Name string
|
|
Image any
|
|
Command string
|
|
Project string
|
|
Service string
|
|
Created int64
|
|
State string
|
|
Status string
|
|
Health string
|
|
ExitCode int
|
|
Publishers PortPublishers
|
|
}
|
|
|
|
// PortPublishers is a slice of PortPublisher
|
|
type PortPublishers []PortPublisher
|
|
|
|
// Len implements sort.Interface
|
|
func (p PortPublishers) Len() int {
|
|
return len(p)
|
|
}
|
|
|
|
// Less implements sort.Interface
|
|
func (p PortPublishers) Less(i, j int) bool {
|
|
left := p[i]
|
|
right := p[j]
|
|
if left.URL != right.URL {
|
|
return left.URL < right.URL
|
|
}
|
|
if left.TargetPort != right.TargetPort {
|
|
return left.TargetPort < right.TargetPort
|
|
}
|
|
if left.PublishedPort != right.PublishedPort {
|
|
return left.PublishedPort < right.PublishedPort
|
|
}
|
|
return left.Protocol < right.Protocol
|
|
}
|
|
|
|
// Swap implements sort.Interface
|
|
func (p PortPublishers) Swap(i, j int) {
|
|
p[i], p[j] = p[j], p[i]
|
|
}
|
|
|
|
// ContainerProcSummary holds container processes top data
|
|
type ContainerProcSummary struct {
|
|
ID string
|
|
Name string
|
|
Processes [][]string
|
|
Titles []string
|
|
}
|
|
|
|
// ImageSummary holds container image description
|
|
type ImageSummary struct {
|
|
ID string
|
|
ContainerName string
|
|
Repository string
|
|
Tag string
|
|
Size int64
|
|
}
|
|
|
|
// ServiceStatus hold status about a service
|
|
type ServiceStatus struct {
|
|
ID string
|
|
Name string
|
|
Replicas int
|
|
Desired int
|
|
Ports []string
|
|
Publishers []PortPublisher
|
|
}
|
|
|
|
// LogOptions defines optional parameters for the `Log` API
|
|
type LogOptions struct {
|
|
Project *types.Project
|
|
Services []string
|
|
Tail string
|
|
Since string
|
|
Until string
|
|
Follow bool
|
|
Timestamps bool
|
|
}
|
|
|
|
// PauseOptions group options of the Pause API
|
|
type PauseOptions struct {
|
|
// Services passed in the command line to be started
|
|
Services []string
|
|
// Project is the compose project used to define this app. Might be nil if user ran command just with project name
|
|
Project *types.Project
|
|
}
|
|
|
|
const (
|
|
// STARTING indicates that stack is being deployed
|
|
STARTING string = "Starting"
|
|
// RUNNING indicates that stack is deployed and services are running
|
|
RUNNING string = "Running"
|
|
// UPDATING indicates that some stack resources are being recreated
|
|
UPDATING string = "Updating"
|
|
// REMOVING indicates that stack is being deleted
|
|
REMOVING string = "Removing"
|
|
// UNKNOWN indicates unknown stack state
|
|
UNKNOWN string = "Unknown"
|
|
// FAILED indicates that stack deployment failed
|
|
FAILED string = "Failed"
|
|
)
|
|
|
|
const (
|
|
// RecreateDiverged to recreate services which configuration diverges from compose model
|
|
RecreateDiverged = "diverged"
|
|
// RecreateForce to force service container being recreated
|
|
RecreateForce = "force"
|
|
// RecreateNever to never recreate existing service containers
|
|
RecreateNever = "never"
|
|
)
|
|
|
|
// Stack holds the name and state of a compose application/stack
|
|
type Stack struct {
|
|
ID string
|
|
Name string
|
|
Status string
|
|
ConfigFiles string
|
|
Reason string
|
|
}
|
|
|
|
// LogConsumer is a callback to process log messages from services
|
|
type LogConsumer interface {
|
|
Log(containerName, message string)
|
|
Err(containerName, message string)
|
|
Status(container, msg string)
|
|
Register(container string)
|
|
}
|
|
|
|
// ContainerEventListener is a callback to process ContainerEvent from services
|
|
type ContainerEventListener func(event ContainerEvent)
|
|
|
|
// ContainerEvent notify an event has been collected on source container implementing Service
|
|
type ContainerEvent struct {
|
|
Type int
|
|
// Container is the name of the container _without the project prefix_.
|
|
//
|
|
// This is only suitable for display purposes within Compose, as it's
|
|
// not guaranteed to be unique across services.
|
|
Container string
|
|
ID string
|
|
Service string
|
|
Line string
|
|
// ContainerEventExit only
|
|
ExitCode int
|
|
Restarting bool
|
|
}
|
|
|
|
const (
|
|
// ContainerEventLog is a ContainerEvent of type log on stdout. Line is set
|
|
ContainerEventLog = iota
|
|
// ContainerEventErr is a ContainerEvent of type log on stderr. Line is set
|
|
ContainerEventErr
|
|
// ContainerEventAttach is a ContainerEvent of type attach. First event sent about a container
|
|
ContainerEventAttach
|
|
// ContainerEventStopped is a ContainerEvent of type stopped.
|
|
ContainerEventStopped
|
|
// ContainerEventRecreated let consumer know container stopped but his being replaced
|
|
ContainerEventRecreated
|
|
// ContainerEventExit is a ContainerEvent of type exit. ExitCode is set
|
|
ContainerEventExit
|
|
// UserCancel user cancelled compose up, we are stopping containers
|
|
UserCancel
|
|
)
|
|
|
|
// Separator is used for naming components
|
|
var Separator = "-"
|
|
|
|
// GetImageNameOrDefault computes the default image name for a service, used to tag built images
|
|
func GetImageNameOrDefault(service types.ServiceConfig, projectName string) string {
|
|
imageName := service.Image
|
|
if imageName == "" {
|
|
imageName = projectName + Separator + service.Name
|
|
}
|
|
return imageName
|
|
}
|