diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/domain/entities/engine_container.go | 1 | ||||
-rw-r--r-- | pkg/domain/entities/generate.go | 11 | ||||
-rw-r--r-- | pkg/domain/infra/abi/containers.go | 27 | ||||
-rw-r--r-- | pkg/domain/infra/abi/generate.go | 60 | ||||
-rw-r--r-- | pkg/domain/infra/tunnel/generate.go | 5 | ||||
-rw-r--r-- | pkg/specgen/generate/container.go | 39 | ||||
-rw-r--r-- | pkg/specgen/generate/pod_create.go | 14 |
7 files changed, 131 insertions, 26 deletions
diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go index e4eb808b4..6a766eb84 100644 --- a/pkg/domain/entities/engine_container.go +++ b/pkg/domain/entities/engine_container.go @@ -54,6 +54,7 @@ type ContainerEngine interface { ContainerWait(ctx context.Context, namesOrIds []string, options WaitOptions) ([]WaitReport, error) Diff(ctx context.Context, namesOrIds []string, options DiffOptions) (*DiffReport, error) Events(ctx context.Context, opts EventsOptions) error + GenerateSpec(ctx context.Context, opts *GenerateSpecOptions) (*GenerateSpecReport, error) GenerateSystemd(ctx context.Context, nameOrID string, opts GenerateSystemdOptions) (*GenerateSystemdReport, error) GenerateKube(ctx context.Context, nameOrIDs []string, opts GenerateKubeOptions) (*GenerateKubeReport, error) SystemPrune(ctx context.Context, options SystemPruneOptions) (*SystemPruneReport, error) diff --git a/pkg/domain/entities/generate.go b/pkg/domain/entities/generate.go index 73dd64ecd..cc5fbb6fb 100644 --- a/pkg/domain/entities/generate.go +++ b/pkg/domain/entities/generate.go @@ -53,3 +53,14 @@ type GenerateKubeReport struct { // Reader - the io.Reader to reader the generated YAML file. Reader io.Reader } + +type GenerateSpecReport struct { + Data []byte +} + +type GenerateSpecOptions struct { + ID string + FileName string + Compact bool + Name bool +} diff --git a/pkg/domain/infra/abi/containers.go b/pkg/domain/infra/abi/containers.go index 900a51302..5b5bc665e 100644 --- a/pkg/domain/infra/abi/containers.go +++ b/pkg/domain/infra/abi/containers.go @@ -7,7 +7,6 @@ import ( "io/ioutil" "os" "strconv" - "strings" "sync" "time" @@ -1675,31 +1674,7 @@ func (ic *ContainerEngine) ContainerClone(ctx context.Context, ctrCloneOpts enti if err == nil { n += "-clone" } - switch { - case strings.Contains(n, "-clone"): - ind := strings.Index(n, "-clone") + 6 - num, err := strconv.Atoi(n[ind:]) - if num == 0 && err != nil { // clone1 is hard to get with this logic, just check for it here. - _, err = ic.Libpod.LookupContainer(n + "1") - if err != nil { - spec.Name = n + "1" - break - } - } else { - n = n[0:ind] - } - err = nil - count := num - for err == nil { - count++ - tempN := n + strconv.Itoa(count) - _, err = ic.Libpod.LookupContainer(tempN) - } - n += strconv.Itoa(count) - spec.Name = n - default: - spec.Name = c.Name() + "-clone" - } + spec.Name = generate.CheckName(ic.Libpod, n, true) } rtSpec, spec, opts, err := generate.MakeContainer(context.Background(), ic.Libpod, spec, true, c) diff --git a/pkg/domain/infra/abi/generate.go b/pkg/domain/infra/abi/generate.go index 31885ce54..f588f591a 100644 --- a/pkg/domain/infra/abi/generate.go +++ b/pkg/domain/infra/abi/generate.go @@ -3,6 +3,7 @@ package abi import ( "bytes" "context" + "encoding/json" "fmt" "strings" @@ -10,6 +11,8 @@ import ( "github.com/containers/podman/v4/libpod/define" "github.com/containers/podman/v4/pkg/domain/entities" k8sAPI "github.com/containers/podman/v4/pkg/k8s.io/api/core/v1" + "github.com/containers/podman/v4/pkg/specgen" + generateUtils "github.com/containers/podman/v4/pkg/specgen/generate" "github.com/containers/podman/v4/pkg/systemd/generate" "github.com/ghodss/yaml" ) @@ -41,6 +44,63 @@ func (ic *ContainerEngine) GenerateSystemd(ctx context.Context, nameOrID string, return &entities.GenerateSystemdReport{Units: units}, nil } +func (ic *ContainerEngine) GenerateSpec(ctx context.Context, opts *entities.GenerateSpecOptions) (*entities.GenerateSpecReport, error) { + var spec *specgen.SpecGenerator + var pspec *specgen.PodSpecGenerator + var err error + if _, err := ic.Libpod.LookupContainer(opts.ID); err == nil { + spec = &specgen.SpecGenerator{} + _, _, err = generateUtils.ConfigToSpec(ic.Libpod, spec, opts.ID) + if err != nil { + return nil, err + } + } else if p, err := ic.Libpod.LookupPod(opts.ID); err == nil { + pspec = &specgen.PodSpecGenerator{} + pspec.Name = p.Name() + _, err := generateUtils.PodConfigToSpec(ic.Libpod, pspec, &entities.ContainerCreateOptions{}, opts.ID) + if err != nil { + return nil, err + } + } + + if pspec == nil && spec == nil { + return nil, fmt.Errorf("could not find a pod or container with the id %s", opts.ID) + } + + // rename if we are looking to consume the output and make a new entity + if opts.Name { + if spec != nil { + spec.Name = generateUtils.CheckName(ic.Libpod, spec.Name, true) + } else { + pspec.Name = generateUtils.CheckName(ic.Libpod, pspec.Name, false) + } + } + + j := []byte{} + if spec != nil { + j, err = json.MarshalIndent(spec, "", " ") + if err != nil { + return nil, err + } + } else if pspec != nil { + j, err = json.MarshalIndent(pspec, "", " ") + if err != nil { + return nil, err + } + } + + // compact output + if opts.Compact { + compacted := &bytes.Buffer{} + err := json.Compact(compacted, j) + if err != nil { + return nil, err + } + return &entities.GenerateSpecReport{Data: compacted.Bytes()}, nil + } + return &entities.GenerateSpecReport{Data: j}, nil // regular output +} + func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string, options entities.GenerateKubeOptions) (*entities.GenerateKubeReport, error) { var ( pods []*libpod.Pod diff --git a/pkg/domain/infra/tunnel/generate.go b/pkg/domain/infra/tunnel/generate.go index 235d478ec..ed63d363a 100644 --- a/pkg/domain/infra/tunnel/generate.go +++ b/pkg/domain/infra/tunnel/generate.go @@ -2,6 +2,7 @@ package tunnel import ( "context" + "fmt" "github.com/containers/podman/v4/pkg/bindings/generate" "github.com/containers/podman/v4/pkg/domain/entities" @@ -43,3 +44,7 @@ func (ic *ContainerEngine) GenerateKube(ctx context.Context, nameOrIDs []string, options := new(generate.KubeOptions).WithService(opts.Service) return generate.Kube(ic.ClientCtx, nameOrIDs, options) } + +func (ic *ContainerEngine) GenerateSpec(ctx context.Context, opts *entities.GenerateSpecOptions) (*entities.GenerateSpecReport, error) { + return nil, fmt.Errorf("GenerateSpec is not supported on the remote API") +} diff --git a/pkg/specgen/generate/container.go b/pkg/specgen/generate/container.go index 20cacc10d..ec85f0f79 100644 --- a/pkg/specgen/generate/container.go +++ b/pkg/specgen/generate/container.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "os" + "strconv" "strings" "time" @@ -563,3 +564,41 @@ func FinishThrottleDevices(s *specgen.SpecGenerator) error { } return nil } + +// Check name looks for existing containers/pods with the same name, and modifies the given string until a new name is found +func CheckName(rt *libpod.Runtime, n string, kind bool) string { + switch { + case strings.Contains(n, "-clone"): + ind := strings.Index(n, "-clone") + 6 + num, err := strconv.Atoi(n[ind:]) + if num == 0 && err != nil { // clone1 is hard to get with this logic, just check for it here. + if kind { + _, err = rt.LookupContainer(n + "1") + } else { + _, err = rt.LookupPod(n + "1") + } + + if err != nil { + n += "1" + break + } + } else { + n = n[0:ind] + } + err = nil + count := num + for err == nil { + count++ + tempN := n + strconv.Itoa(count) + if kind { + _, err = rt.LookupContainer(tempN) + } else { + _, err = rt.LookupPod(tempN) + } + } + n += strconv.Itoa(count) + default: + n += "-clone" + } + return n +} diff --git a/pkg/specgen/generate/pod_create.go b/pkg/specgen/generate/pod_create.go index 4e6362c9b..d6063b9a0 100644 --- a/pkg/specgen/generate/pod_create.go +++ b/pkg/specgen/generate/pod_create.go @@ -2,6 +2,7 @@ package generate import ( "context" + "encoding/json" "fmt" "net" "os" @@ -327,6 +328,19 @@ func PodConfigToSpec(rt *libpod.Runtime, spec *specgen.PodSpecGenerator, infraOp } spec.InfraContainerSpec = infraSpec + matching, err := json.Marshal(infraSpec) + if err != nil { + return nil, err + } + + // track name before unmarshal so we do not overwrite w/ infra + name := spec.Name + err = json.Unmarshal(matching, spec) + if err != nil { + return nil, err + } + + spec.Name = name } // need to reset hostname, name etc of both pod and infra |