cmd/list, pkg/podman: Limit access to the raw 'podman images' JSON
This builds on top of commit 0465d78fd9034ce9. The toolboxImage type has been renamed to Image and moved into the podman package. There is nothing Toolbx specific about the type - it represents any image returned by 'podman images'. The images are only later filtered for Toolbx images. Secondly, having the Image type inside the podman package makes it possible to encapsulate the unmarshalling of the JSON within the package without exposing the raw JSON to outside consumers. This is desirable because the unmarshalling involves tracking changes in the JSON output by different Podman versions, and it's better to limit such details to the podman package. https://github.com/containers/toolbox/pull/1190
This commit is contained in:
parent
5baf3162a9
commit
5f324d537e
|
|
@ -30,13 +30,6 @@ import (
|
||||||
"golang.org/x/term"
|
"golang.org/x/term"
|
||||||
)
|
)
|
||||||
|
|
||||||
type toolboxImage struct {
|
|
||||||
ID string
|
|
||||||
Names []string
|
|
||||||
Created string
|
|
||||||
Labels map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
type toolboxContainer struct {
|
type toolboxContainer struct {
|
||||||
ID string
|
ID string
|
||||||
Names []string
|
Names []string
|
||||||
|
|
@ -107,7 +100,7 @@ func list(cmd *cobra.Command, args []string) error {
|
||||||
lsImages = false
|
lsImages = false
|
||||||
}
|
}
|
||||||
|
|
||||||
var images []toolboxImage
|
var images []podman.Image
|
||||||
var containers []toolboxContainer
|
var containers []toolboxContainer
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
|
|
@ -187,22 +180,16 @@ func listHelp(cmd *cobra.Command, args []string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getImages() ([]toolboxImage, error) {
|
func getImages() ([]podman.Image, error) {
|
||||||
logrus.Debug("Fetching all images")
|
logrus.Debug("Fetching all images")
|
||||||
args := []string{"--sort", "repository"}
|
args := []string{"--sort", "repository"}
|
||||||
data, err := podman.GetImagesJSON(args...)
|
images, err := podman.GetImages(args...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.Debugf("Fetching all images failed: %s", err)
|
logrus.Debugf("Fetching all images failed: %s", err)
|
||||||
return nil, errors.New("failed to get images")
|
return nil, errors.New("failed to get images")
|
||||||
}
|
}
|
||||||
|
|
||||||
var images []toolboxImage
|
var toolboxImages []podman.Image
|
||||||
if err := json.Unmarshal(data, &images); err != nil {
|
|
||||||
logrus.Debugf("Fetching all images failed: %s", err)
|
|
||||||
return nil, errors.New("failed to get images")
|
|
||||||
}
|
|
||||||
|
|
||||||
var toolboxImages []toolboxImage
|
|
||||||
|
|
||||||
for _, image := range images {
|
for _, image := range images {
|
||||||
for label := range toolboxLabels {
|
for label := range toolboxLabels {
|
||||||
|
|
@ -216,7 +203,7 @@ func getImages() ([]toolboxImage, error) {
|
||||||
return toolboxImages, nil
|
return toolboxImages, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func listOutput(images []toolboxImage, containers []toolboxContainer) {
|
func listOutput(images []podman.Image, containers []toolboxContainer) {
|
||||||
if len(images) != 0 {
|
if len(images) != 0 {
|
||||||
writer := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
writer := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
||||||
fmt.Fprintf(writer, "%s\t%s\t%s\n", "IMAGE ID", "IMAGE NAME", "CREATED")
|
fmt.Fprintf(writer, "%s\t%s\t%s\n", "IMAGE ID", "IMAGE NAME", "CREATED")
|
||||||
|
|
@ -302,35 +289,6 @@ func listOutput(images []toolboxImage, containers []toolboxContainer) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (image *toolboxImage) UnmarshalJSON(data []byte) error {
|
|
||||||
var raw struct {
|
|
||||||
ID string
|
|
||||||
Names []string
|
|
||||||
Created interface{}
|
|
||||||
Labels map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := json.Unmarshal(data, &raw); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
image.ID = raw.ID
|
|
||||||
image.Names = raw.Names
|
|
||||||
|
|
||||||
// Until Podman 2.0.x the field 'Created' held a human-readable string in
|
|
||||||
// format "5 minutes ago". Since Podman 2.1 the field holds an integer with
|
|
||||||
// Unix time. Go interprets numbers in JSON as float64.
|
|
||||||
switch value := raw.Created.(type) {
|
|
||||||
case string:
|
|
||||||
image.Created = value
|
|
||||||
case float64:
|
|
||||||
image.Created = utils.HumanDuration(int64(value))
|
|
||||||
}
|
|
||||||
|
|
||||||
image.Labels = raw.Labels
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *toolboxContainer) UnmarshalJSON(data []byte) error {
|
func (c *toolboxContainer) UnmarshalJSON(data []byte) error {
|
||||||
var raw struct {
|
var raw struct {
|
||||||
ID string
|
ID string
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,17 @@ import (
|
||||||
|
|
||||||
"github.com/HarryMichal/go-version"
|
"github.com/HarryMichal/go-version"
|
||||||
"github.com/containers/toolbox/pkg/shell"
|
"github.com/containers/toolbox/pkg/shell"
|
||||||
|
"github.com/containers/toolbox/pkg/utils"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Image struct {
|
||||||
|
ID string
|
||||||
|
Names []string
|
||||||
|
Created string
|
||||||
|
Labels map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
podmanVersion string
|
podmanVersion string
|
||||||
)
|
)
|
||||||
|
|
@ -35,6 +43,35 @@ var (
|
||||||
LogLevel = logrus.ErrorLevel
|
LogLevel = logrus.ErrorLevel
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func (image *Image) UnmarshalJSON(data []byte) error {
|
||||||
|
var raw struct {
|
||||||
|
ID string
|
||||||
|
Names []string
|
||||||
|
Created interface{}
|
||||||
|
Labels map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := json.Unmarshal(data, &raw); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
image.ID = raw.ID
|
||||||
|
image.Names = raw.Names
|
||||||
|
|
||||||
|
// Until Podman 2.0.x the field 'Created' held a human-readable string in
|
||||||
|
// format "5 minutes ago". Since Podman 2.1 the field holds an integer with
|
||||||
|
// Unix time. Go interprets numbers in JSON as float64.
|
||||||
|
switch value := raw.Created.(type) {
|
||||||
|
case string:
|
||||||
|
image.Created = value
|
||||||
|
case float64:
|
||||||
|
image.Created = utils.HumanDuration(int64(value))
|
||||||
|
}
|
||||||
|
|
||||||
|
image.Labels = raw.Labels
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// CheckVersion compares provided version with the version of Podman.
|
// CheckVersion compares provided version with the version of Podman.
|
||||||
//
|
//
|
||||||
// Takes in one string parameter that should be in the format that is used for versioning (eg. 1.0.0, 2.5.1-dev).
|
// Takes in one string parameter that should be in the format that is used for versioning (eg. 1.0.0, 2.5.1-dev).
|
||||||
|
|
@ -95,14 +132,14 @@ func GetContainers(args ...string) ([]map[string]interface{}, error) {
|
||||||
return containers, nil
|
return containers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetImagesJSON is a wrapper function around `podman images --format json` command.
|
// GetImages is a wrapper function around `podman images --format json` command.
|
||||||
//
|
//
|
||||||
// Parameter args accepts an array of strings to be passed to the wrapped command (eg. ["-a", "--filter", "123"]).
|
// Parameter args accepts an array of strings to be passed to the wrapped command (eg. ["-a", "--filter", "123"]).
|
||||||
//
|
//
|
||||||
// Returned value is the JSON representing the images.
|
// Returned value is a slice of Images.
|
||||||
//
|
//
|
||||||
// If a problem happens during execution, first argument is nil and second argument holds the error message.
|
// If a problem happens during execution, first argument is nil and second argument holds the error message.
|
||||||
func GetImagesJSON(args ...string) ([]byte, error) {
|
func GetImages(args ...string) ([]Image, error) {
|
||||||
var stdout bytes.Buffer
|
var stdout bytes.Buffer
|
||||||
|
|
||||||
logLevelString := LogLevel.String()
|
logLevelString := LogLevel.String()
|
||||||
|
|
@ -112,7 +149,12 @@ func GetImagesJSON(args ...string) ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
data := stdout.Bytes()
|
data := stdout.Bytes()
|
||||||
return data, nil
|
var images []Image
|
||||||
|
if err := json.Unmarshal(data, &images); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return images, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetVersion returns version of Podman in a string
|
// GetVersion returns version of Podman in a string
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue