diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/api/handlers/compat/containers.go | 18 | ||||
-rw-r--r-- | pkg/api/handlers/libpod/images_pull.go | 24 | ||||
-rw-r--r-- | pkg/api/server/register_images.go | 4 | ||||
-rw-r--r-- | pkg/bindings/images/pull.go | 10 | ||||
-rw-r--r-- | pkg/bindings/images/types.go | 3 | ||||
-rw-r--r-- | pkg/bindings/images/types_pull_options.go | 16 | ||||
-rw-r--r-- | pkg/domain/entities/pods.go | 41 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/images.go | 2 | ||||
-rw-r--r-- | pkg/errorhandling/errorhandling.go | 9 | ||||
-rw-r--r-- | pkg/specgen/generate/container.go | 3 | ||||
-rw-r--r-- | pkg/specgen/generate/container_create.go | 4 | ||||
-rw-r--r-- | pkg/specgen/generate/pod_create.go | 8 | ||||
-rw-r--r-- | pkg/specgen/podspecgen.go | 12 | ||||
-rw-r--r-- | pkg/specgen/specgen.go | 4 |
14 files changed, 137 insertions, 21 deletions
diff --git a/pkg/api/handlers/compat/containers.go b/pkg/api/handlers/compat/containers.go index 6bc02dd2b..2a0a0b725 100644 --- a/pkg/api/handlers/compat/containers.go +++ b/pkg/api/handlers/compat/containers.go @@ -403,6 +403,24 @@ func LibpodToContainerJSON(l *libpod.Container, sz bool) (*types.ContainerJSON, state.Status = define.ContainerStateCreated.String() } + state.Health = &types.Health{ + Status: inspect.State.Healthcheck.Status, + FailingStreak: inspect.State.Healthcheck.FailingStreak, + } + + log := inspect.State.Healthcheck.Log + + for _, item := range log { + res := &types.HealthcheckResult{} + s, _ := time.Parse(time.RFC3339Nano, item.Start) + e, _ := time.Parse(time.RFC3339Nano, item.End) + res.Start = s + res.End = e + res.ExitCode = item.ExitCode + res.Output = item.Output + state.Health.Log = append(state.Health.Log, res) + } + formatCapabilities(inspect.HostConfig.CapDrop) formatCapabilities(inspect.HostConfig.CapAdd) diff --git a/pkg/api/handlers/libpod/images_pull.go b/pkg/api/handlers/libpod/images_pull.go index e88b53a4b..04b415638 100644 --- a/pkg/api/handlers/libpod/images_pull.go +++ b/pkg/api/handlers/libpod/images_pull.go @@ -26,14 +26,16 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) { runtime := r.Context().Value("runtime").(*libpod.Runtime) decoder := r.Context().Value("decoder").(*schema.Decoder) query := struct { - Reference string `schema:"reference"` - OS string `schema:"OS"` - Arch string `schema:"Arch"` - Variant string `schema:"Variant"` - TLSVerify bool `schema:"tlsVerify"` - AllTags bool `schema:"allTags"` + Reference string `schema:"reference"` + OS string `schema:"OS"` + Arch string `schema:"Arch"` + Variant string `schema:"Variant"` + TLSVerify bool `schema:"tlsVerify"` + AllTags bool `schema:"allTags"` + PullPolicy string `schema:"policy"` }{ - TLSVerify: true, + TLSVerify: true, + PullPolicy: "always", } if err := decoder.Decode(&query, r.URL.Query()); err != nil { @@ -83,12 +85,18 @@ func ImagesPull(w http.ResponseWriter, r *http.Request) { pullOptions.Writer = writer + pullPolicy, err := config.ParsePullPolicy(query.PullPolicy) + if err != nil { + utils.Error(w, "failed to parse pull policy", http.StatusBadRequest, err) + return + } + var pulledImages []*libimage.Image var pullError error runCtx, cancel := context.WithCancel(r.Context()) go func() { defer cancel() - pulledImages, pullError = runtime.LibimageRuntime().Pull(runCtx, query.Reference, config.PullPolicyAlways, pullOptions) + pulledImages, pullError = runtime.LibimageRuntime().Pull(runCtx, query.Reference, pullPolicy, pullOptions) }() flush := func() { diff --git a/pkg/api/server/register_images.go b/pkg/api/server/register_images.go index d075cd098..3410c53cd 100644 --- a/pkg/api/server/register_images.go +++ b/pkg/api/server/register_images.go @@ -974,6 +974,10 @@ func (s *APIServer) registerImagesHandlers(r *mux.Router) error { // description: Pull image for the specified variant. // type: string // - in: query + // name: policy + // description: Pull policy, "always" (default), "missing", "newer", "never". + // type: string + // - in: query // name: tlsVerify // description: Require TLS verification. // type: boolean diff --git a/pkg/bindings/images/pull.go b/pkg/bindings/images/pull.go index 9780c3bff..7dfe9560c 100644 --- a/pkg/bindings/images/pull.go +++ b/pkg/bindings/images/pull.go @@ -13,7 +13,7 @@ import ( "github.com/containers/podman/v3/pkg/auth" "github.com/containers/podman/v3/pkg/bindings" "github.com/containers/podman/v3/pkg/domain/entities" - "github.com/hashicorp/go-multierror" + "github.com/containers/podman/v3/pkg/errorhandling" "github.com/pkg/errors" ) @@ -65,7 +65,7 @@ func Pull(ctx context.Context, rawImage string, options *PullOptions) ([]string, dec := json.NewDecoder(response.Body) var images []string - var mErr error + var pullErrors []error for { var report entities.ImagePullReport if err := dec.Decode(&report); err != nil { @@ -77,7 +77,7 @@ func Pull(ctx context.Context, rawImage string, options *PullOptions) ([]string, select { case <-response.Request.Context().Done(): - return images, mErr + break default: // non-blocking select } @@ -86,7 +86,7 @@ func Pull(ctx context.Context, rawImage string, options *PullOptions) ([]string, case report.Stream != "": fmt.Fprint(stderr, report.Stream) case report.Error != "": - mErr = multierror.Append(mErr, errors.New(report.Error)) + pullErrors = append(pullErrors, errors.New(report.Error)) case len(report.Images) > 0: images = report.Images case report.ID != "": @@ -94,5 +94,5 @@ func Pull(ctx context.Context, rawImage string, options *PullOptions) ([]string, return images, errors.Errorf("failed to parse pull results stream, unexpected input: %v", report) } } - return images, mErr + return images, errorhandling.JoinErrors(pullErrors) } diff --git a/pkg/bindings/images/types.go b/pkg/bindings/images/types.go index 1f3e46729..0aa75a81e 100644 --- a/pkg/bindings/images/types.go +++ b/pkg/bindings/images/types.go @@ -147,6 +147,9 @@ type PullOptions struct { // OS will overwrite the local operating system (OS) for image // pulls. OS *string + // Policy is the pull policy. Supported values are "missing", "never", + // "newer", "always". An empty string defaults to "always". + Policy *string // Password for authenticating against the registry. Password *string // Quiet can be specified to suppress pull progress when pulling. Ignored diff --git a/pkg/bindings/images/types_pull_options.go b/pkg/bindings/images/types_pull_options.go index 0611c4447..8fcf499eb 100644 --- a/pkg/bindings/images/types_pull_options.go +++ b/pkg/bindings/images/types_pull_options.go @@ -84,6 +84,22 @@ func (o *PullOptions) GetOS() string { return *o.OS } +// WithPolicy +func (o *PullOptions) WithPolicy(value string) *PullOptions { + v := &value + o.Policy = v + return o +} + +// GetPolicy +func (o *PullOptions) GetPolicy() string { + var policy string + if o.Policy == nil { + return policy + } + return *o.Policy +} + // WithPassword func (o *PullOptions) WithPassword(value string) *PullOptions { v := &value diff --git a/pkg/domain/entities/pods.go b/pkg/domain/entities/pods.go index 88055454f..35f940bca 100644 --- a/pkg/domain/entities/pods.go +++ b/pkg/domain/entities/pods.go @@ -7,6 +7,8 @@ import ( "github.com/containers/podman/v3/libpod/define" "github.com/containers/podman/v3/pkg/specgen" + "github.com/containers/podman/v3/pkg/util" + "github.com/opencontainers/runtime-spec/specs-go" ) type PodKillOptions struct { @@ -116,13 +118,35 @@ type PodCreateOptions struct { Name string Net *NetOptions Share []string + Cpus float64 + CpusetCpus string } type PodCreateReport struct { Id string //nolint } -func (p PodCreateOptions) ToPodSpecGen(s *specgen.PodSpecGenerator) { +func (p *PodCreateOptions) CPULimits() *specs.LinuxCPU { + cpu := &specs.LinuxCPU{} + hasLimits := false + + if p.Cpus != 0 { + period, quota := util.CoresToPeriodAndQuota(p.Cpus) + cpu.Period = &period + cpu.Quota = "a + hasLimits = true + } + if p.CpusetCpus != "" { + cpu.Cpus = p.CpusetCpus + hasLimits = true + } + if !hasLimits { + return cpu + } + return cpu +} + +func (p *PodCreateOptions) ToPodSpecGen(s *specgen.PodSpecGenerator) error { // Basic Config s.Name = p.Name s.Hostname = p.Hostname @@ -156,6 +180,21 @@ func (p PodCreateOptions) ToPodSpecGen(s *specgen.PodSpecGenerator) { // Cgroup s.CgroupParent = p.CGroupParent + + // Resource config + cpuDat := p.CPULimits() + if s.ResourceLimits == nil { + s.ResourceLimits = &specs.LinuxResources{} + s.ResourceLimits.CPU = &specs.LinuxCPU{} + } + if cpuDat != nil { + s.ResourceLimits.CPU = cpuDat + if p.Cpus != 0 { + s.CPUPeriod = *cpuDat.Period + s.CPUQuota = *cpuDat.Quota + } + } + return nil } type PodPruneOptions struct { diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go index 3fd9a755d..42027a2dc 100644 --- a/pkg/domain/infra/tunnel/images.go +++ b/pkg/domain/infra/tunnel/images.go @@ -107,7 +107,7 @@ func (ir *ImageEngine) Pull(ctx context.Context, rawImage string, opts entities. options := new(images.PullOptions) options.WithAllTags(opts.AllTags).WithAuthfile(opts.Authfile).WithArch(opts.Arch).WithOS(opts.OS) options.WithVariant(opts.Variant).WithPassword(opts.Password) - options.WithQuiet(opts.Quiet).WithUsername(opts.Username) + options.WithQuiet(opts.Quiet).WithUsername(opts.Username).WithPolicy(opts.PullPolicy.String()) if s := opts.SkipTLSVerify; s != types.OptionalBoolUndefined { if s == types.OptionalBoolTrue { options.WithSkipTLSVerify(true) diff --git a/pkg/errorhandling/errorhandling.go b/pkg/errorhandling/errorhandling.go index 9b1740006..6adbc9f34 100644 --- a/pkg/errorhandling/errorhandling.go +++ b/pkg/errorhandling/errorhandling.go @@ -15,6 +15,12 @@ func JoinErrors(errs []error) error { return nil } + // If there's just one error, return it. This prevents the "%d errors + // occurred:" header plus list from the multierror package. + if len(errs) == 1 { + return errs[0] + } + // `multierror` appends new lines which we need to remove to prevent // blank lines when printing the error. var multiE *multierror.Error @@ -24,9 +30,6 @@ func JoinErrors(errs []error) error { if finalErr == nil { return finalErr } - if len(multiE.WrappedErrors()) == 1 && logrus.IsLevelEnabled(logrus.TraceLevel) { - return multiE.WrappedErrors()[0] - } return errors.New(strings.TrimSpace(finalErr.Error())) } diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go index d00e51e82..e7276892d 100644 --- a/pkg/specgen/generate/container.go +++ b/pkg/specgen/generate/container.go @@ -24,7 +24,8 @@ func CompleteSpec(ctx context.Context, r *libpod.Runtime, s *specgen.SpecGenerat var inspectData *libimage.ImageData var err error if s.Image != "" { - newImage, _, err = r.LibimageRuntime().LookupImage(s.Image, nil) + lookupOptions := &libimage.LookupImageOptions{IgnorePlatform: true} + newImage, _, err = r.LibimageRuntime().LookupImage(s.Image, lookupOptions) if err != nil { return nil, err } diff --git a/pkg/specgen/generate/container_create.go b/pkg/specgen/generate/container_create.go index a0f5cc7e6..e2901f0b6 100644 --- a/pkg/specgen/generate/container_create.go +++ b/pkg/specgen/generate/container_create.go @@ -92,7 +92,8 @@ func MakeContainer(ctx context.Context, rt *libpod.Runtime, s *specgen.SpecGener options = append(options, libpod.WithRootFS(s.Rootfs)) } else { var resolvedImageName string - newImage, resolvedImageName, err = rt.LibimageRuntime().LookupImage(s.Image, nil) + lookupOptions := &libimage.LookupImageOptions{IgnorePlatform: true} + newImage, resolvedImageName, err = rt.LibimageRuntime().LookupImage(s.Image, lookupOptions) if err != nil { return nil, err } @@ -346,7 +347,6 @@ func createContainerOptions(ctx context.Context, rt *libpod.Runtime, s *specgen. options = append(options, libpod.WithLogDriver(s.LogConfiguration.Driver)) } } - // Security options if len(s.SelinuxOpts) > 0 { options = append(options, libpod.WithSecLabels(s.SelinuxOpts)) diff --git a/pkg/specgen/generate/pod_create.go b/pkg/specgen/generate/pod_create.go index 07c56b799..023ebb41e 100644 --- a/pkg/specgen/generate/pod_create.go +++ b/pkg/specgen/generate/pod_create.go @@ -54,6 +54,14 @@ func createPodOptions(p *specgen.PodSpecGenerator, rt *libpod.Runtime) ([]libpod if len(p.Name) > 0 { options = append(options, libpod.WithPodName(p.Name)) } + if p.ResourceLimits != nil && p.ResourceLimits.CPU != nil && p.ResourceLimits.CPU.Period != nil && p.ResourceLimits.CPU.Quota != nil { + if *p.ResourceLimits.CPU.Period != 0 || *p.ResourceLimits.CPU.Quota != 0 { + options = append(options, libpod.WithPodCPUPAQ((*p.ResourceLimits.CPU.Period), (*p.ResourceLimits.CPU.Quota))) + } + } + if p.ResourceLimits != nil && p.ResourceLimits.CPU != nil && p.ResourceLimits.CPU.Cpus != "" { + options = append(options, libpod.WithPodCPUSetCPUs(p.ResourceLimits.CPU.Cpus)) + } if len(p.Hostname) > 0 { options = append(options, libpod.WithPodHostname(p.Hostname)) } diff --git a/pkg/specgen/podspecgen.go b/pkg/specgen/podspecgen.go index 7d771f5bb..000a787ea 100644 --- a/pkg/specgen/podspecgen.go +++ b/pkg/specgen/podspecgen.go @@ -2,6 +2,8 @@ package specgen import ( "net" + + spec "github.com/opencontainers/runtime-spec/specs-go" ) // PodBasicConfig contains basic configuration options for pods. @@ -155,6 +157,16 @@ type PodSpecGenerator struct { PodBasicConfig PodNetworkConfig PodCgroupConfig + PodResourceConfig +} + +type PodResourceConfig struct { + // ResourceLimits contains linux specific CPU data for the pod + ResourceLimits *spec.LinuxResources `json:"resource_limits,omitempty"` + // CPU period of the cpuset, determined by --cpus + CPUPeriod uint64 `json:"cpu_period,omitempty"` + // CPU quota of the cpuset, determined by --cpus + CPUQuota int64 `json:"cpu_quota,omitempty"` } // NewPodSpecGenerator creates a new pod spec diff --git a/pkg/specgen/specgen.go b/pkg/specgen/specgen.go index 2815bdebb..c5cc726d7 100644 --- a/pkg/specgen/specgen.go +++ b/pkg/specgen/specgen.go @@ -470,6 +470,10 @@ type ContainerResourceConfig struct { // that are used to configure cgroup v2. // Optional. CgroupConf map[string]string `json:"unified,omitempty"` + // CPU period of the cpuset, determined by --cpus + CPUPeriod uint64 `json:"cpu_period,omitempty"` + // CPU quota of the cpuset, determined by --cpus + CPUQuota int64 `json:"cpu_quota,omitempty"` } // ContainerHealthCheckConfig describes a container healthcheck with attributes |