summaryrefslogtreecommitdiff
path: root/pkg
diff options
context:
space:
mode:
Diffstat (limited to 'pkg')
-rw-r--r--pkg/api/handlers/compat/images_build.go183
-rw-r--r--pkg/api/handlers/compat/networks.go22
-rw-r--r--pkg/api/handlers/compat/swagger.go7
-rw-r--r--pkg/api/handlers/libpod/networks.go14
-rw-r--r--pkg/api/server/register_networks.go66
-rw-r--r--pkg/bindings/images/build.go154
-rw-r--r--pkg/bindings/network/network.go18
-rw-r--r--pkg/bindings/network/types.go6
-rw-r--r--pkg/bindings/network/types_prune_options.go75
-rw-r--r--pkg/domain/entities/engine_container.go1
-rw-r--r--pkg/domain/entities/network.go12
-rw-r--r--pkg/domain/infra/abi/images.go17
-rw-r--r--pkg/domain/infra/abi/network.go25
-rw-r--r--pkg/domain/infra/tunnel/images.go11
-rw-r--r--pkg/domain/infra/tunnel/network.go5
15 files changed, 481 insertions, 135 deletions
diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go
index 415ff85cd..0f27a090f 100644
--- a/pkg/api/handlers/compat/images_build.go
+++ b/pkg/api/handlers/compat/images_build.go
@@ -60,29 +60,39 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
}()
query := struct {
- BuildArgs string `schema:"buildargs"`
- CacheFrom string `schema:"cachefrom"`
- CpuPeriod uint64 `schema:"cpuperiod"` // nolint
- CpuQuota int64 `schema:"cpuquota"` // nolint
- CpuSetCpus string `schema:"cpusetcpus"` // nolint
- CpuShares uint64 `schema:"cpushares"` // nolint
- Dockerfile string `schema:"dockerfile"`
- ExtraHosts string `schema:"extrahosts"`
- ForceRm bool `schema:"forcerm"`
- HTTPProxy bool `schema:"httpproxy"`
- Labels string `schema:"labels"`
- Layers bool `schema:"layers"`
- MemSwap int64 `schema:"memswap"`
- Memory int64 `schema:"memory"`
- NetworkMode string `schema:"networkmode"`
- NoCache bool `schema:"nocache"`
- Outputs string `schema:"outputs"`
- Platform string `schema:"platform"`
- Pull bool `schema:"pull"`
- Quiet bool `schema:"q"`
- Registry string `schema:"registry"`
- Remote string `schema:"remote"`
- Rm bool `schema:"rm"`
+ AddHosts string `schema:"extrahosts"`
+ AdditionalCapabilities string `schema:"addcaps"`
+ Annotations string `schema:"annotations"`
+ BuildArgs string `schema:"buildargs"`
+ CacheFrom string `schema:"cachefrom"`
+ ConfigureNetwork int64 `schema:"networkmode"`
+ CpuPeriod uint64 `schema:"cpuperiod"` // nolint
+ CpuQuota int64 `schema:"cpuquota"` // nolint
+ CpuSetCpus string `schema:"cpusetcpus"` // nolint
+ CpuShares uint64 `schema:"cpushares"` // nolint
+ Devices string `schema:"devices"`
+ Dockerfile string `schema:"dockerfile"`
+ DropCapabilities string `schema:"dropcaps"`
+ ForceRm bool `schema:"forcerm"`
+ From string `schema:"from"`
+ HTTPProxy bool `schema:"httpproxy"`
+ Isolation int64 `schema:"isolation"`
+ Jobs uint64 `schema:"jobs"` // nolint
+ Labels string `schema:"labels"`
+ Layers bool `schema:"layers"`
+ LogRusage bool `schema:"rusage"`
+ Manifest string `schema:"manifest"`
+ MemSwap int64 `schema:"memswap"`
+ Memory int64 `schema:"memory"`
+ NoCache bool `schema:"nocache"`
+ OutputFormat string `schema:"outputformat"`
+ Platform string `schema:"platform"`
+ Pull bool `schema:"pull"`
+ Quiet bool `schema:"q"`
+ Registry string `schema:"registry"`
+ Rm bool `schema:"rm"`
+ //FIXME SecurityOpt in remote API is not handled
+ SecurityOpt string `schema:"securityopt"`
ShmSize int `schema:"shmsize"`
Squash bool `schema:"squash"`
Tag []string `schema:"t"`
@@ -101,14 +111,57 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
return
}
+ // convert label formats
+ var addCaps = []string{}
+ if _, found := r.URL.Query()["addcaps"]; found {
+ var m = []string{}
+ if err := json.Unmarshal([]byte(query.AdditionalCapabilities), &m); err != nil {
+ utils.BadRequest(w, "addcaps", query.AdditionalCapabilities, err)
+ return
+ }
+ addCaps = m
+ }
+ addhosts := []string{}
+ if _, found := r.URL.Query()["extrahosts"]; found {
+ if err := json.Unmarshal([]byte(query.AddHosts), &addhosts); err != nil {
+ utils.BadRequest(w, "extrahosts", query.AddHosts, err)
+ return
+ }
+ }
+
+ // convert label formats
+ var dropCaps = []string{}
+ if _, found := r.URL.Query()["dropcaps"]; found {
+ var m = []string{}
+ if err := json.Unmarshal([]byte(query.DropCapabilities), &m); err != nil {
+ utils.BadRequest(w, "dropcaps", query.DropCapabilities, err)
+ return
+ }
+ dropCaps = m
+ }
+
+ // convert label formats
+ var devices = []string{}
+ if _, found := r.URL.Query()["devices"]; found {
+ var m = []string{}
+ if err := json.Unmarshal([]byte(query.DropCapabilities), &m); err != nil {
+ utils.BadRequest(w, "devices", query.DropCapabilities, err)
+ return
+ }
+ devices = m
+ }
+
var output string
if len(query.Tag) > 0 {
output = query.Tag[0]
}
-
- var additionalNames []string
+ format := buildah.Dockerv2ImageManifest
+ if utils.IsLibpodRequest(r) {
+ format = query.OutputFormat
+ }
+ var additionalTags []string
if len(query.Tag) > 1 {
- additionalNames = query.Tag[1:]
+ additionalTags = query.Tag[1:]
}
var buildArgs = map[string]string{}
@@ -120,17 +173,21 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
}
// convert label formats
+ var annotations = []string{}
+ if _, found := r.URL.Query()["annotations"]; found {
+ if err := json.Unmarshal([]byte(query.Annotations), &annotations); err != nil {
+ utils.BadRequest(w, "annotations", query.Annotations, err)
+ return
+ }
+ }
+
+ // convert label formats
var labels = []string{}
if _, found := r.URL.Query()["labels"]; found {
- var m = map[string]string{}
- if err := json.Unmarshal([]byte(query.Labels), &m); err != nil {
+ if err := json.Unmarshal([]byte(query.Labels), &labels); err != nil {
utils.BadRequest(w, "labels", query.Labels, err)
return
}
-
- for k, v := range m {
- labels = append(labels, k+"="+v)
- }
}
pullPolicy := buildah.PullIfMissing
@@ -160,27 +217,14 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
reporter := channel.NewWriter(make(chan []byte, 1))
defer reporter.Close()
+
buildOptions := imagebuildah.BuildOptions{
- ContextDirectory: contextDirectory,
- PullPolicy: pullPolicy,
- Registry: query.Registry,
- IgnoreUnrecognizedInstructions: true,
- Quiet: query.Quiet,
- Layers: query.Layers,
- Isolation: buildah.IsolationChroot,
- Compression: archive.Gzip,
- Args: buildArgs,
- Output: output,
- AdditionalTags: additionalNames,
- Out: stdout,
- Err: auxout,
- ReportWriter: reporter,
- OutputFormat: buildah.Dockerv2ImageManifest,
- SystemContext: &types.SystemContext{
- AuthFilePath: authfile,
- DockerAuthConfig: creds,
- },
+ AddCapabilities: addCaps,
+ AdditionalTags: additionalTags,
+ Annotations: annotations,
+ Args: buildArgs,
CommonBuildOpts: &buildah.CommonBuildOptions{
+ AddHost: addhosts,
CPUPeriod: query.CpuPeriod,
CPUQuota: query.CpuQuota,
CPUShares: query.CpuShares,
@@ -190,12 +234,37 @@ func BuildImage(w http.ResponseWriter, r *http.Request) {
MemorySwap: query.MemSwap,
ShmSize: strconv.Itoa(query.ShmSize),
},
- Squash: query.Squash,
- Labels: labels,
- NoCache: query.NoCache,
- RemoveIntermediateCtrs: query.Rm,
- ForceRmIntermediateCtrs: query.ForceRm,
- Target: query.Target,
+ Compression: archive.Gzip,
+ ConfigureNetwork: buildah.NetworkConfigurationPolicy(query.ConfigureNetwork),
+ ContextDirectory: contextDirectory,
+ Devices: devices,
+ DropCapabilities: dropCaps,
+ Err: auxout,
+ ForceRmIntermediateCtrs: query.ForceRm,
+ From: query.From,
+ IgnoreUnrecognizedInstructions: true,
+ // FIXME, This is very broken. Buildah will only work with chroot
+ // Isolation: buildah.Isolation(query.Isolation),
+ Isolation: buildah.IsolationChroot,
+
+ Labels: labels,
+ Layers: query.Layers,
+ Manifest: query.Manifest,
+ NoCache: query.NoCache,
+ Out: stdout,
+ Output: output,
+ OutputFormat: format,
+ PullPolicy: pullPolicy,
+ Quiet: query.Quiet,
+ Registry: query.Registry,
+ RemoveIntermediateCtrs: query.Rm,
+ ReportWriter: reporter,
+ Squash: query.Squash,
+ SystemContext: &types.SystemContext{
+ AuthFilePath: authfile,
+ DockerAuthConfig: creds,
+ },
+ Target: query.Target,
}
runtime := r.Context().Value("runtime").(*libpod.Runtime)
diff --git a/pkg/api/handlers/compat/networks.go b/pkg/api/handlers/compat/networks.go
index f0b922885..f7a70816f 100644
--- a/pkg/api/handlers/compat/networks.go
+++ b/pkg/api/handlers/compat/networks.go
@@ -388,3 +388,25 @@ func Disconnect(w http.ResponseWriter, r *http.Request) {
}
utils.WriteResponse(w, http.StatusOK, "OK")
}
+
+// Prune removes unused networks
+func Prune(w http.ResponseWriter, r *http.Request) {
+ // TODO Filters are not implemented
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ ic := abi.ContainerEngine{Libpod: runtime}
+ pruneOptions := entities.NetworkPruneOptions{}
+ pruneReports, err := ic.NetworkPrune(r.Context(), pruneOptions)
+ if err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ return
+ }
+ var prunedNetworks []string //nolint
+ for _, pr := range pruneReports {
+ if pr.Error != nil {
+ logrus.Error(pr.Error)
+ continue
+ }
+ prunedNetworks = append(prunedNetworks, pr.Name)
+ }
+ utils.WriteResponse(w, http.StatusOK, prunedNetworks)
+}
diff --git a/pkg/api/handlers/compat/swagger.go b/pkg/api/handlers/compat/swagger.go
index 0a514822b..1d1f1ecf2 100644
--- a/pkg/api/handlers/compat/swagger.go
+++ b/pkg/api/handlers/compat/swagger.go
@@ -77,3 +77,10 @@ type swagCompatNetworkDisconnectRequest struct {
// in:body
Body struct{ types.NetworkDisconnect }
}
+
+// Network prune
+// swagger:response NetworkPruneResponse
+type swagCompatNetworkPruneResponse struct {
+ // in:body
+ Body []string
+}
diff --git a/pkg/api/handlers/libpod/networks.go b/pkg/api/handlers/libpod/networks.go
index d3bf06988..998f89d96 100644
--- a/pkg/api/handlers/libpod/networks.go
+++ b/pkg/api/handlers/libpod/networks.go
@@ -175,3 +175,17 @@ func ExistsNetwork(w http.ResponseWriter, r *http.Request) {
}
utils.WriteResponse(w, http.StatusNoContent, "")
}
+
+// Prune removes unused networks
+func Prune(w http.ResponseWriter, r *http.Request) {
+ // TODO Filters are not implemented
+ runtime := r.Context().Value("runtime").(*libpod.Runtime)
+ ic := abi.ContainerEngine{Libpod: runtime}
+ pruneOptions := entities.NetworkPruneOptions{}
+ pruneReports, err := ic.NetworkPrune(r.Context(), pruneOptions)
+ if err != nil {
+ utils.Error(w, "Something went wrong.", http.StatusInternalServerError, err)
+ return
+ }
+ utils.WriteResponse(w, http.StatusOK, pruneReports)
+}
diff --git a/pkg/api/server/register_networks.go b/pkg/api/server/register_networks.go
index 3d9e7fb89..d3345d8da 100644
--- a/pkg/api/server/register_networks.go
+++ b/pkg/api/server/register_networks.go
@@ -9,19 +9,6 @@ import (
)
func (s *APIServer) registerNetworkHandlers(r *mux.Router) error {
- // swagger:operation POST /networks/prune compat compatPruneNetwork
- // ---
- // tags:
- // - networks (compat)
- // Summary: Delete unused networks
- // description: Not supported
- // produces:
- // - application/json
- // responses:
- // 404:
- // $ref: "#/responses/NoSuchNetwork"
- r.HandleFunc(VersionedPath("/networks/prune"), compat.UnsupportedHandler).Methods(http.MethodPost)
- r.HandleFunc("/networks/prune", compat.UnsupportedHandler).Methods(http.MethodPost)
// swagger:operation DELETE /networks/{name} compat compatRemoveNetwork
// ---
// tags:
@@ -172,6 +159,35 @@ func (s *APIServer) registerNetworkHandlers(r *mux.Router) error {
// $ref: "#/responses/InternalError"
r.HandleFunc(VersionedPath("/networks/{name}/disconnect"), s.APIHandler(compat.Disconnect)).Methods(http.MethodPost)
r.HandleFunc("/networks/{name}/disconnect", s.APIHandler(compat.Disconnect)).Methods(http.MethodPost)
+ // swagger:operation POST /networks/prune compat compatPruneNetwork
+ // ---
+ // tags:
+ // - networks (compat)
+ // summary: Delete unused networks
+ // description: Remove CNI networks that do not have containers
+ // produces:
+ // - application/json
+ // parameters:
+ // - in: query
+ // name: filters
+ // type: string
+ // description: |
+ // NOT IMPLEMENTED
+ // Filters to process on the prune list, encoded as JSON (a map[string][]string).
+ // Available filters:
+ // - until=<timestamp> Prune networks created before this timestamp. The <timestamp> can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. 10m, 1h30m) computed relative to the daemon machine’s time.
+ // - label (label=<key>, label=<key>=<value>, label!=<key>, or label!=<key>=<value>) Prune networks with (or without, in case label!=... is used) the specified labels.
+ // responses:
+ // 200:
+ // description: OK
+ // schema:
+ // type: array
+ // items:
+ // type: string
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.HandleFunc(VersionedPath("/networks/prune"), s.APIHandler(compat.Prune)).Methods(http.MethodPost)
+ r.HandleFunc("/networks/prune", s.APIHandler(compat.Prune)).Methods(http.MethodPost)
// swagger:operation DELETE /libpod/networks/{name} libpod libpodRemoveNetwork
// ---
@@ -353,5 +369,29 @@ func (s *APIServer) registerNetworkHandlers(r *mux.Router) error {
// 500:
// $ref: "#/responses/InternalError"
r.HandleFunc(VersionedPath("/libpod/networks/{name}/disconnect"), s.APIHandler(compat.Disconnect)).Methods(http.MethodPost)
+ // swagger:operation POST /libpod/networks/prune libpod libpodPruneNetwork
+ // ---
+ // tags:
+ // - networks
+ // summary: Delete unused networks
+ // description: Remove CNI networks that do not have containers
+ // produces:
+ // - application/json
+ // parameters:
+ // - in: query
+ // name: filters
+ // type: string
+ // description: |
+ // NOT IMPLEMENTED
+ // Filters to process on the prune list, encoded as JSON (a map[string][]string).
+ // Available filters:
+ // - until=<timestamp> Prune networks created before this timestamp. The <timestamp> can be Unix timestamps, date formatted timestamps, or Go duration strings (e.g. 10m, 1h30m) computed relative to the daemon machine’s time.
+ // - label (label=<key>, label=<key>=<value>, label!=<key>, or label!=<key>=<value>) Prune networks with (or without, in case label!=... is used) the specified labels.
+ // responses:
+ // 200:
+ // $ref: "#/responses/NetworkPruneResponse"
+ // 500:
+ // $ref: "#/responses/InternalError"
+ r.HandleFunc(VersionedPath("/libpod/networks/prune"), s.APIHandler(libpod.Prune)).Methods(http.MethodPost)
return nil
}
diff --git a/pkg/bindings/images/build.go b/pkg/bindings/images/build.go
index 02765816f..8ea09b881 100644
--- a/pkg/bindings/images/build.go
+++ b/pkg/bindings/images/build.go
@@ -31,36 +31,31 @@ import (
func Build(ctx context.Context, containerFiles []string, options entities.BuildOptions) (*entities.BuildReport, error) {
params := url.Values{}
- if t := options.Output; len(t) > 0 {
- params.Set("t", t)
+ if caps := options.AddCapabilities; len(caps) > 0 {
+ c, err := jsoniter.MarshalToString(caps)
+ if err != nil {
+ return nil, err
+ }
+ params.Add("addcaps", c)
}
+
+ if annotations := options.Annotations; len(annotations) > 0 {
+ l, err := jsoniter.MarshalToString(annotations)
+ if err != nil {
+ return nil, err
+ }
+ params.Set("annotations", l)
+ }
+ params.Add("t", options.Output)
for _, tag := range options.AdditionalTags {
params.Add("t", tag)
}
- if options.Quiet {
- params.Set("q", "1")
- }
- if options.NoCache {
- params.Set("nocache", "1")
- }
- if options.Layers {
- params.Set("layers", "1")
- }
- // TODO cachefrom
- if options.PullPolicy == buildah.PullAlways {
- params.Set("pull", "1")
- }
- if options.RemoveIntermediateCtrs {
- params.Set("rm", "1")
- }
- if options.ForceRmIntermediateCtrs {
- params.Set("forcerm", "1")
- }
- if mem := options.CommonBuildOpts.Memory; mem > 0 {
- params.Set("memory", strconv.Itoa(int(mem)))
- }
- if memSwap := options.CommonBuildOpts.MemorySwap; memSwap > 0 {
- params.Set("memswap", strconv.Itoa(int(memSwap)))
+ if buildArgs := options.Args; len(buildArgs) > 0 {
+ bArgs, err := jsoniter.MarshalToString(buildArgs)
+ if err != nil {
+ return nil, err
+ }
+ params.Set("buildargs", bArgs)
}
if cpuShares := options.CommonBuildOpts.CPUShares; cpuShares > 0 {
params.Set("cpushares", strconv.Itoa(int(cpuShares)))
@@ -74,22 +69,38 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
if cpuQuota := options.CommonBuildOpts.CPUQuota; cpuQuota > 0 {
params.Set("cpuquota", strconv.Itoa(int(cpuQuota)))
}
- if buildArgs := options.Args; len(buildArgs) > 0 {
- bArgs, err := jsoniter.MarshalToString(buildArgs)
+ params.Set("networkmode", strconv.Itoa(int(options.ConfigureNetwork)))
+ params.Set("outputformat", options.OutputFormat)
+
+ if devices := options.Devices; len(devices) > 0 {
+ d, err := jsoniter.MarshalToString(devices)
if err != nil {
return nil, err
}
- params.Set("buildargs", bArgs)
+ params.Add("devices", d)
}
- if shmSize := options.CommonBuildOpts.ShmSize; len(shmSize) > 0 {
- shmBytes, err := units.RAMInBytes(shmSize)
+
+ if caps := options.DropCapabilities; len(caps) > 0 {
+ c, err := jsoniter.MarshalToString(caps)
if err != nil {
return nil, err
}
- params.Set("shmsize", strconv.Itoa(int(shmBytes)))
+ params.Add("dropcaps", c)
}
- if options.Squash {
- params.Set("squash", "1")
+
+ if options.ForceRmIntermediateCtrs {
+ params.Set("forcerm", "1")
+ }
+ if len(options.From) > 0 {
+ params.Set("from", options.From)
+ }
+
+ params.Set("isolation", strconv.Itoa(int(options.Isolation)))
+ if options.CommonBuildOpts.HTTPProxy {
+ params.Set("httpproxy", "1")
+ }
+ if options.Jobs != nil {
+ params.Set("jobs", strconv.FormatUint(uint64(*options.Jobs), 10))
}
if labels := options.Labels; len(labels) > 0 {
l, err := jsoniter.MarshalToString(labels)
@@ -98,10 +109,66 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
}
params.Set("labels", l)
}
- if options.CommonBuildOpts.HTTPProxy {
- params.Set("httpproxy", "1")
+ if options.Layers {
+ params.Set("layers", "1")
+ }
+ if options.LogRusage {
+ params.Set("rusage", "1")
+ }
+ if len(options.Manifest) > 0 {
+ params.Set("manifest", options.Manifest)
+ }
+ if memSwap := options.CommonBuildOpts.MemorySwap; memSwap > 0 {
+ params.Set("memswap", strconv.Itoa(int(memSwap)))
+ }
+ if mem := options.CommonBuildOpts.Memory; mem > 0 {
+ params.Set("memory", strconv.Itoa(int(mem)))
+ }
+ if options.NoCache {
+ params.Set("nocache", "1")
+ }
+ if t := options.Output; len(t) > 0 {
+ params.Set("output", t)
+ }
+ var platform string
+ if len(options.OS) > 0 {
+ platform = options.OS
+ }
+ if len(options.Architecture) > 0 {
+ if len(platform) == 0 {
+ platform = "linux"
+ }
+ platform += "/" + options.Architecture
+ }
+ if len(platform) > 0 {
+ params.Set("platform", platform)
+ }
+ if options.PullPolicy == buildah.PullAlways {
+ params.Set("pull", "1")
+ }
+ if options.Quiet {
+ params.Set("q", "1")
+ }
+ if options.RemoveIntermediateCtrs {
+ params.Set("rm", "1")
+ }
+ if hosts := options.CommonBuildOpts.AddHost; len(hosts) > 0 {
+ h, err := jsoniter.MarshalToString(hosts)
+ if err != nil {
+ return nil, err
+ }
+ params.Set("extrahosts", h)
+ }
+ if shmSize := options.CommonBuildOpts.ShmSize; len(shmSize) > 0 {
+ shmBytes, err := units.RAMInBytes(shmSize)
+ if err != nil {
+ return nil, err
+ }
+ params.Set("shmsize", strconv.Itoa(int(shmBytes)))
+ }
+ if options.Squash {
+ params.Set("squash", "1")
}
-
var (
headers map[string]string
err error
@@ -124,19 +191,6 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO
stdout = options.Out
}
- // TODO network?
-
- var platform string
- if OS := options.OS; len(OS) > 0 {
- platform += OS
- }
- if arch := options.Architecture; len(arch) > 0 {
- platform += "/" + arch
- }
- if len(platform) > 0 {
- params.Set("platform", platform)
- }
-
entries := make([]string, len(containerFiles))
copy(entries, containerFiles)
entries = append(entries, options.ContextDirectory)
diff --git a/pkg/bindings/network/network.go b/pkg/bindings/network/network.go
index 8debeee84..428e60cf2 100644
--- a/pkg/bindings/network/network.go
+++ b/pkg/bindings/network/network.go
@@ -180,3 +180,21 @@ func Exists(ctx context.Context, nameOrID string, options *ExistsOptions) (bool,
}
return response.IsSuccess(), nil
}
+
+// Prune removes unused CNI networks
+func Prune(ctx context.Context, options *PruneOptions) ([]*entities.NetworkPruneReport, error) {
+ // TODO Filters is not implemented
+ var (
+ prunedNetworks []*entities.NetworkPruneReport
+ )
+ conn, err := bindings.GetClient(ctx)
+ if err != nil {
+ return nil, err
+ }
+
+ response, err := conn.DoRequest(nil, http.MethodPost, "/networks/prune", nil, nil)
+ if err != nil {
+ return nil, err
+ }
+ return prunedNetworks, response.Process(&prunedNetworks)
+}
diff --git a/pkg/bindings/network/types.go b/pkg/bindings/network/types.go
index 91cbcf044..47dce67c7 100644
--- a/pkg/bindings/network/types.go
+++ b/pkg/bindings/network/types.go
@@ -74,3 +74,9 @@ type ConnectOptions struct {
// if a network exists
type ExistsOptions struct {
}
+
+//go:generate go run ../generator/generator.go PruneOptions
+// PruneOptions are optional options for removing unused
+// CNI networks
+type PruneOptions struct {
+}
diff --git a/pkg/bindings/network/types_prune_options.go b/pkg/bindings/network/types_prune_options.go
new file mode 100644
index 000000000..c56dcd0d3
--- /dev/null
+++ b/pkg/bindings/network/types_prune_options.go
@@ -0,0 +1,75 @@
+package network
+
+import (
+ "net/url"
+ "reflect"
+ "strings"
+
+ "github.com/containers/podman/v2/pkg/bindings/util"
+ jsoniter "github.com/json-iterator/go"
+ "github.com/pkg/errors"
+)
+
+/*
+This file is generated automatically by go generate. Do not edit.
+*/
+
+// Changed
+func (o *PruneOptions) Changed(fieldName string) bool {
+ r := reflect.ValueOf(o)
+ value := reflect.Indirect(r).FieldByName(fieldName)
+ return !value.IsNil()
+}
+
+// ToParams
+func (o *PruneOptions) ToParams() (url.Values, error) {
+ params := url.Values{}
+ if o == nil {
+ return params, nil
+ }
+ json := jsoniter.ConfigCompatibleWithStandardLibrary
+ s := reflect.ValueOf(o)
+ if reflect.Ptr == s.Kind() {
+ s = s.Elem()
+ }
+ sType := s.Type()
+ for i := 0; i < s.NumField(); i++ {
+ fieldName := sType.Field(i).Name
+ if !o.Changed(fieldName) {
+ continue
+ }
+ fieldName = strings.ToLower(fieldName)
+ f := s.Field(i)
+ if reflect.Ptr == f.Kind() {
+ f = f.Elem()
+ }
+ switch {
+ case util.IsSimpleType(f):
+ params.Set(fieldName, util.SimpleTypeToParam(f))
+ case f.Kind() == reflect.Slice:
+ for i := 0; i < f.Len(); i++ {
+ elem := f.Index(i)
+ if util.IsSimpleType(elem) {
+ params.Add(fieldName, util.SimpleTypeToParam(elem))
+ } else {
+ return nil, errors.New("slices must contain only simple types")
+ }
+ }
+ case f.Kind() == reflect.Map:
+ lowerCaseKeys := make(map[string][]string)
+ iter := f.MapRange()
+ for iter.Next() {
+ lowerCaseKeys[iter.Key().Interface().(string)] = iter.Value().Interface().([]string)
+
+ }
+ s, err := json.MarshalToString(lowerCaseKeys)
+ if err != nil {
+ return nil, err
+ }
+
+ params.Set(fieldName, s)
+ }
+
+ }
+ return params, nil
+}
diff --git a/pkg/domain/entities/engine_container.go b/pkg/domain/entities/engine_container.go
index 9ff1714e7..d43b422a3 100644
--- a/pkg/domain/entities/engine_container.go
+++ b/pkg/domain/entities/engine_container.go
@@ -63,6 +63,7 @@ type ContainerEngine interface {
NetworkExists(ctx context.Context, networkname string) (*BoolReport, error)
NetworkInspect(ctx context.Context, namesOrIds []string, options InspectOptions) ([]NetworkInspectReport, []error, error)
NetworkList(ctx context.Context, options NetworkListOptions) ([]*NetworkListReport, error)
+ NetworkPrune(ctx context.Context, options NetworkPruneOptions) ([]*NetworkPruneReport, error)
NetworkReload(ctx context.Context, names []string, options NetworkReloadOptions) ([]*NetworkReloadReport, error)
NetworkRm(ctx context.Context, namesOrIds []string, options NetworkRmOptions) ([]*NetworkRmReport, error)
PlayKube(ctx context.Context, path string, opts PlayKubeOptions) (*PlayKubeReport, error)
diff --git a/pkg/domain/entities/network.go b/pkg/domain/entities/network.go
index b76bfcac7..1859f920e 100644
--- a/pkg/domain/entities/network.go
+++ b/pkg/domain/entities/network.go
@@ -80,3 +80,15 @@ type NetworkConnectOptions struct {
Aliases []string
Container string
}
+
+// NetworkPruneReport containers the name of network and an error
+// associated in its pruning (removal)
+// swagger:model NetworkPruneReport
+type NetworkPruneReport struct {
+ Name string
+ Error error
+}
+
+// NetworkPruneOptions describes options for pruning
+// unused cni networks
+type NetworkPruneOptions struct{}
diff --git a/pkg/domain/infra/abi/images.go b/pkg/domain/infra/abi/images.go
index 8ca93e770..f2d0f2c39 100644
--- a/pkg/domain/infra/abi/images.go
+++ b/pkg/domain/infra/abi/images.go
@@ -580,12 +580,21 @@ func (ir *ImageEngine) Remove(ctx context.Context, images []string, opts entitie
// without having to pass all local data around.
deleteImage := func(img *image.Image) error {
results, err := ir.Libpod.RemoveImage(ctx, img, opts.Force)
- if err != nil {
+ switch errors.Cause(err) {
+ case nil:
+ // Removal worked, so let's report it.
+ report.Deleted = append(report.Deleted, results.Deleted)
+ report.Untagged = append(report.Untagged, results.Untagged...)
+ return nil
+ case storage.ErrImageUnknown:
+ // The image must have been removed already (see #6510).
+ report.Deleted = append(report.Deleted, img.ID())
+ report.Untagged = append(report.Untagged, img.ID())
+ return nil
+ default:
+ // Fatal error.
return err
}
- report.Deleted = append(report.Deleted, results.Deleted)
- report.Untagged = append(report.Untagged, results.Untagged...)
- return nil
}
// Delete all images from the local storage.
diff --git a/pkg/domain/infra/abi/network.go b/pkg/domain/infra/abi/network.go
index bc4328fcd..13fabe89d 100644
--- a/pkg/domain/infra/abi/network.go
+++ b/pkg/domain/infra/abi/network.go
@@ -155,3 +155,28 @@ func (ic *ContainerEngine) NetworkExists(ctx context.Context, networkname string
Value: exists,
}, nil
}
+
+// Network prune removes unused cni networks
+func (ic *ContainerEngine) NetworkPrune(ctx context.Context, options entities.NetworkPruneOptions) ([]*entities.NetworkPruneReport, error) {
+ runtimeConfig, err := ic.Libpod.GetConfig()
+ if err != nil {
+ return nil, err
+ }
+ cons, err := ic.Libpod.GetAllContainers()
+ if err != nil {
+ return nil, err
+ }
+ // Gather up all the non-default networks that the
+ // containers want
+ usedNetworks := make(map[string]bool)
+ for _, c := range cons {
+ nets, _, err := c.Networks()
+ if err != nil {
+ return nil, err
+ }
+ for _, n := range nets {
+ usedNetworks[n] = true
+ }
+ }
+ return network.PruneNetworks(runtimeConfig, usedNetworks)
+}
diff --git a/pkg/domain/infra/tunnel/images.go b/pkg/domain/infra/tunnel/images.go
index f10c8c175..daad911cd 100644
--- a/pkg/domain/infra/tunnel/images.go
+++ b/pkg/domain/infra/tunnel/images.go
@@ -350,17 +350,6 @@ func (ir *ImageEngine) Build(_ context.Context, containerFiles []string, opts en
if err != nil {
return nil, err
}
- // For remote clients, if the option for writing to a file was
- // selected, we need to write to the *client's* filesystem.
- if len(opts.IIDFile) > 0 {
- f, err := os.Create(opts.IIDFile)
- if err != nil {
- return nil, err
- }
- if _, err := f.WriteString(report.ID); err != nil {
- return nil, err
- }
- }
return report, nil
}
diff --git a/pkg/domain/infra/tunnel/network.go b/pkg/domain/infra/tunnel/network.go
index bdb1beb03..990bfa880 100644
--- a/pkg/domain/infra/tunnel/network.go
+++ b/pkg/domain/infra/tunnel/network.go
@@ -89,3 +89,8 @@ func (ic *ContainerEngine) NetworkExists(ctx context.Context, networkname string
Value: exists,
}, nil
}
+
+// Network prune removes unused cni networks
+func (ic *ContainerEngine) NetworkPrune(ctx context.Context, options entities.NetworkPruneOptions) ([]*entities.NetworkPruneReport, error) {
+ return network.Prune(ic.ClientCtx, nil)
+}