github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/pkg/api/handlers/types.go (about)

     1  package handlers
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  	"time"
     8  
     9  	"github.com/containers/image/v5/manifest"
    10  	libpodImage "github.com/containers/podman/v2/libpod/image"
    11  	"github.com/containers/podman/v2/pkg/domain/entities"
    12  	docker "github.com/docker/docker/api/types"
    13  	dockerContainer "github.com/docker/docker/api/types/container"
    14  	dockerNetwork "github.com/docker/docker/api/types/network"
    15  	"github.com/docker/go-connections/nat"
    16  	"github.com/pkg/errors"
    17  )
    18  
    19  type AuthConfig struct {
    20  	docker.AuthConfig
    21  }
    22  
    23  type ImageInspect struct {
    24  	docker.ImageInspect
    25  }
    26  
    27  type ContainerConfig struct {
    28  	dockerContainer.Config
    29  }
    30  
    31  type LibpodImagesLoadReport struct {
    32  	ID string `json:"id"`
    33  }
    34  
    35  type LibpodImagesPullReport struct {
    36  	entities.ImagePullReport
    37  }
    38  
    39  // LibpodImagesRemoveReport is the return type for image removal via the rest
    40  // api.
    41  type LibpodImagesRemoveReport struct {
    42  	entities.ImageRemoveReport
    43  	// Image removal requires is to return data and an error.
    44  	Errors []string
    45  }
    46  
    47  type ContainersPruneReport struct {
    48  	docker.ContainersPruneReport
    49  }
    50  
    51  type LibpodContainersPruneReport struct {
    52  	ID             string `json:"id"`
    53  	SpaceReclaimed int64  `json:"space"`
    54  	PruneError     string `json:"error"`
    55  }
    56  
    57  type Info struct {
    58  	docker.Info
    59  	BuildahVersion     string
    60  	CPURealtimePeriod  bool
    61  	CPURealtimeRuntime bool
    62  	CgroupVersion      string
    63  	Rootless           bool
    64  	SwapFree           int64
    65  	SwapTotal          int64
    66  	Uptime             string
    67  }
    68  
    69  type Container struct {
    70  	docker.Container
    71  	docker.ContainerCreateConfig
    72  }
    73  
    74  type DiskUsage struct {
    75  	docker.DiskUsage
    76  }
    77  
    78  type VolumesPruneReport struct {
    79  	docker.VolumesPruneReport
    80  }
    81  
    82  type ImagesPruneReport struct {
    83  	docker.ImagesPruneReport
    84  }
    85  
    86  type BuildCachePruneReport struct {
    87  	docker.BuildCachePruneReport
    88  }
    89  
    90  type NetworkPruneReport struct {
    91  	docker.NetworksPruneReport
    92  }
    93  
    94  type ConfigCreateResponse struct {
    95  	docker.ConfigCreateResponse
    96  }
    97  
    98  type PushResult struct {
    99  	docker.PushResult
   100  }
   101  
   102  type BuildResult struct {
   103  	docker.BuildResult
   104  }
   105  
   106  type ContainerWaitOKBody struct {
   107  	StatusCode int
   108  	Error      struct {
   109  		Message string
   110  	}
   111  }
   112  
   113  // CreateContainerConfig used when compatible endpoint creates a container
   114  type CreateContainerConfig struct {
   115  	Name                   string                         // container name
   116  	dockerContainer.Config                                // desired container configuration
   117  	HostConfig             dockerContainer.HostConfig     // host dependent configuration for container
   118  	NetworkingConfig       dockerNetwork.NetworkingConfig // network configuration for container
   119  }
   120  
   121  // swagger:model IDResponse
   122  type IDResponse struct {
   123  	// ID
   124  	ID string `json:"Id"`
   125  }
   126  
   127  type ContainerTopOKBody struct {
   128  	dockerContainer.ContainerTopOKBody
   129  }
   130  
   131  type PodTopOKBody struct {
   132  	dockerContainer.ContainerTopOKBody
   133  }
   134  
   135  // swagger:model PodCreateConfig
   136  type PodCreateConfig struct {
   137  	Name         string   `json:"name"`
   138  	CGroupParent string   `json:"cgroup-parent"`
   139  	Hostname     string   `json:"hostname"`
   140  	Infra        bool     `json:"infra"`
   141  	InfraCommand string   `json:"infra-command"`
   142  	InfraImage   string   `json:"infra-image"`
   143  	Labels       []string `json:"labels"`
   144  	Publish      []string `json:"publish"`
   145  	Share        string   `json:"share"`
   146  }
   147  
   148  type HistoryResponse struct {
   149  	ID        string   `json:"Id"`
   150  	Created   int64    `json:"Created"`
   151  	CreatedBy string   `json:"CreatedBy"`
   152  	Tags      []string `json:"Tags"`
   153  	Size      int64    `json:"Size"`
   154  	Comment   string   `json:"Comment"`
   155  }
   156  
   157  type ImageLayer struct{}
   158  
   159  type ImageTreeResponse struct {
   160  	ID     string       `json:"id"`
   161  	Tags   []string     `json:"tags"`
   162  	Size   string       `json:"size"`
   163  	Layers []ImageLayer `json:"layers"`
   164  }
   165  
   166  type ExecCreateConfig struct {
   167  	docker.ExecConfig
   168  }
   169  
   170  type ExecCreateResponse struct {
   171  	docker.IDResponse
   172  }
   173  
   174  type ExecStartConfig struct {
   175  	Detach bool `json:"Detach"`
   176  	Tty    bool `json:"Tty"`
   177  }
   178  
   179  func ImageToImageSummary(l *libpodImage.Image) (*entities.ImageSummary, error) {
   180  	containers, err := l.Containers()
   181  	if err != nil {
   182  		return nil, errors.Wrapf(err, "failed to obtain Containers for image %s", l.ID())
   183  	}
   184  	containerCount := len(containers)
   185  
   186  	// FIXME: GetParent() panics
   187  	// parent, err := l.GetParent(context.TODO())
   188  	// if err != nil {
   189  	// 	return nil, errors.Wrapf(err, "failed to obtain ParentID for image %s", l.ID())
   190  	// }
   191  
   192  	labels, err := l.Labels(context.TODO())
   193  	if err != nil {
   194  		return nil, errors.Wrapf(err, "failed to obtain Labels for image %s", l.ID())
   195  	}
   196  
   197  	size, err := l.Size(context.TODO())
   198  	if err != nil {
   199  		return nil, errors.Wrapf(err, "failed to obtain Size for image %s", l.ID())
   200  	}
   201  
   202  	repoTags, err := l.RepoTags()
   203  	if err != nil {
   204  		return nil, errors.Wrapf(err, "failed to obtain RepoTags for image %s", l.ID())
   205  	}
   206  
   207  	digests := make([]string, len(l.Digests()))
   208  	for i, d := range l.Digests() {
   209  		digests[i] = string(d)
   210  	}
   211  
   212  	is := entities.ImageSummary{
   213  		ID:           l.ID(),
   214  		ParentId:     l.Parent,
   215  		RepoTags:     repoTags,
   216  		Created:      l.Created().Unix(),
   217  		Size:         int64(*size),
   218  		SharedSize:   0,
   219  		VirtualSize:  l.VirtualSize,
   220  		Labels:       labels,
   221  		Containers:   containerCount,
   222  		ReadOnly:     l.IsReadOnly(),
   223  		Dangling:     l.Dangling(),
   224  		Names:        l.Names(),
   225  		Digest:       string(l.Digest()),
   226  		Digests:      digests,
   227  		ConfigDigest: string(l.ConfigDigest),
   228  		History:      l.NamesHistory(),
   229  	}
   230  	return &is, nil
   231  }
   232  
   233  func ImageDataToImageInspect(ctx context.Context, l *libpodImage.Image) (*ImageInspect, error) {
   234  	info, err := l.Inspect(context.Background())
   235  	if err != nil {
   236  		return nil, err
   237  	}
   238  	ports, err := portsToPortSet(info.Config.ExposedPorts)
   239  	if err != nil {
   240  		return nil, err
   241  	}
   242  
   243  	// TODO the rest of these still need wiring!
   244  	config := dockerContainer.Config{
   245  		//	Hostname:        "",
   246  		//	Domainname:      "",
   247  		User: info.User,
   248  		//	AttachStdin:     false,
   249  		//	AttachStdout:    false,
   250  		//	AttachStderr:    false,
   251  		ExposedPorts: ports,
   252  		//	Tty:             false,
   253  		//	OpenStdin:       false,
   254  		//	StdinOnce:       false,
   255  		Env: info.Config.Env,
   256  		Cmd: info.Config.Cmd,
   257  		// Healthcheck: l.ImageData.HealthCheck,
   258  		//	ArgsEscaped:     false,
   259  		//	Image:           "",
   260  		Volumes:    info.Config.Volumes,
   261  		WorkingDir: info.Config.WorkingDir,
   262  		Entrypoint: info.Config.Entrypoint,
   263  		//	NetworkDisabled: false,
   264  		//	MacAddress:      "",
   265  		// OnBuild:    info.Config.OnBuild,
   266  		Labels:     info.Labels,
   267  		StopSignal: info.Config.StopSignal,
   268  		//	StopTimeout:     nil,
   269  		//	Shell:           nil,
   270  	}
   271  	ic, err := l.ToImageRef(ctx)
   272  	if err != nil {
   273  		return nil, err
   274  	}
   275  
   276  	rootfs := docker.RootFS{}
   277  	if info.RootFS != nil {
   278  		rootfs.Type = info.RootFS.Type
   279  		rootfs.Layers = make([]string, 0, len(info.RootFS.Layers))
   280  		for _, layer := range info.RootFS.Layers {
   281  			rootfs.Layers = append(rootfs.Layers, string(layer))
   282  		}
   283  	}
   284  	dockerImageInspect := docker.ImageInspect{
   285  		Architecture:  l.Architecture,
   286  		Author:        l.Author,
   287  		Comment:       info.Comment,
   288  		Config:        &config,
   289  		Created:       l.Created().Format(time.RFC3339Nano),
   290  		DockerVersion: info.Version,
   291  		GraphDriver:   docker.GraphDriverData{},
   292  		ID:            fmt.Sprintf("sha256:%s", l.ID()),
   293  		Metadata:      docker.ImageMetadata{},
   294  		Os:            l.Os,
   295  		OsVersion:     l.Version,
   296  		Parent:        l.Parent,
   297  		RepoDigests:   info.RepoDigests,
   298  		RepoTags:      info.RepoTags,
   299  		RootFS:        rootfs,
   300  		Size:          info.Size,
   301  		Variant:       "",
   302  		VirtualSize:   info.VirtualSize,
   303  	}
   304  	bi := ic.ConfigInfo()
   305  	// For docker images, we need to get the Container id and config
   306  	// and populate the image with it.
   307  	if bi.MediaType == manifest.DockerV2Schema2ConfigMediaType {
   308  		d := manifest.Schema2Image{}
   309  		b, err := ic.ConfigBlob(ctx)
   310  		if err != nil {
   311  			return nil, err
   312  		}
   313  		if err := json.Unmarshal(b, &d); err != nil {
   314  			return nil, err
   315  		}
   316  		// populate the Container id into the image
   317  		dockerImageInspect.Container = d.Container
   318  		containerConfig := dockerContainer.Config{}
   319  		configBytes, err := json.Marshal(d.ContainerConfig)
   320  		if err != nil {
   321  			return nil, err
   322  		}
   323  		if err := json.Unmarshal(configBytes, &containerConfig); err != nil {
   324  			return nil, err
   325  		}
   326  		// populate the Container config in the image
   327  		dockerImageInspect.ContainerConfig = &containerConfig
   328  		// populate parent
   329  		dockerImageInspect.Parent = d.Parent.String()
   330  	}
   331  	return &ImageInspect{dockerImageInspect}, nil
   332  
   333  }
   334  
   335  // portsToPortSet converts libpods exposed ports to dockers structs
   336  func portsToPortSet(input map[string]struct{}) (nat.PortSet, error) {
   337  	ports := make(nat.PortSet)
   338  	for k := range input {
   339  		proto, port := nat.SplitProtoPort(k)
   340  		switch proto {
   341  		// See the OCI image spec for details:
   342  		// https://github.com/opencontainers/image-spec/blob/e562b04403929d582d449ae5386ff79dd7961a11/config.md#properties
   343  		case "tcp", "":
   344  			p, err := nat.NewPort("tcp", port)
   345  			if err != nil {
   346  				return nil, errors.Wrapf(err, "unable to create tcp port from %s", k)
   347  			}
   348  			ports[p] = struct{}{}
   349  		case "udp":
   350  			p, err := nat.NewPort("udp", port)
   351  			if err != nil {
   352  				return nil, errors.Wrapf(err, "unable to create tcp port from %s", k)
   353  			}
   354  			ports[p] = struct{}{}
   355  		default:
   356  			return nil, errors.Errorf("invalid port proto %q in %q", proto, k)
   357  		}
   358  	}
   359  	return ports, nil
   360  }