github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/pkg/bindings/images/images.go (about)

     1  package images
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io"
     7  	"net/http"
     8  	"net/url"
     9  	"strconv"
    10  
    11  	"github.com/containers/image/v5/types"
    12  	"github.com/containers/libpod/pkg/api/handlers"
    13  	"github.com/containers/libpod/pkg/bindings"
    14  	"github.com/containers/libpod/pkg/domain/entities"
    15  	"github.com/pkg/errors"
    16  )
    17  
    18  // Exists a lightweight way to determine if an image exists in local storage.  It returns a
    19  // boolean response.
    20  func Exists(ctx context.Context, nameOrID string) (bool, error) {
    21  	conn, err := bindings.GetClient(ctx)
    22  	if err != nil {
    23  		return false, err
    24  	}
    25  	response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/exists", nil, nameOrID)
    26  	if err != nil {
    27  		return false, err
    28  	}
    29  	return response.IsSuccess(), nil
    30  }
    31  
    32  // List returns a list of images in local storage.  The all boolean and filters parameters are optional
    33  // ways to alter the image query.
    34  func List(ctx context.Context, all *bool, filters map[string][]string) ([]*entities.ImageSummary, error) {
    35  	var imageSummary []*entities.ImageSummary
    36  	conn, err := bindings.GetClient(ctx)
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  	params := url.Values{}
    41  	if all != nil {
    42  		params.Set("all", strconv.FormatBool(*all))
    43  	}
    44  	if filters != nil {
    45  		strFilters, err := bindings.FiltersToString(filters)
    46  		if err != nil {
    47  			return nil, err
    48  		}
    49  		params.Set("filters", strFilters)
    50  	}
    51  	response, err := conn.DoRequest(nil, http.MethodGet, "/images/json", params)
    52  	if err != nil {
    53  		return imageSummary, err
    54  	}
    55  	return imageSummary, response.Process(&imageSummary)
    56  }
    57  
    58  // Get performs an image inspect.  To have the on-disk size of the image calculated, you can
    59  // use the optional size parameter.
    60  func GetImage(ctx context.Context, nameOrID string, size *bool) (*entities.ImageData, error) {
    61  	conn, err := bindings.GetClient(ctx)
    62  	if err != nil {
    63  		return nil, err
    64  	}
    65  	params := url.Values{}
    66  	if size != nil {
    67  		params.Set("size", strconv.FormatBool(*size))
    68  	}
    69  	inspectedData := entities.ImageData{}
    70  	response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/json", params, nameOrID)
    71  	if err != nil {
    72  		return &inspectedData, err
    73  	}
    74  	return &inspectedData, response.Process(&inspectedData)
    75  }
    76  
    77  func ImageTree(ctx context.Context, nameOrId string) error {
    78  	return bindings.ErrNotImplemented
    79  }
    80  
    81  // History returns the parent layers of an image.
    82  func History(ctx context.Context, nameOrID string) ([]*handlers.HistoryResponse, error) {
    83  	var history []*handlers.HistoryResponse
    84  	conn, err := bindings.GetClient(ctx)
    85  	if err != nil {
    86  		return nil, err
    87  	}
    88  	response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/history", nil, nameOrID)
    89  	if err != nil {
    90  		return history, err
    91  	}
    92  	return history, response.Process(&history)
    93  }
    94  
    95  func Load(ctx context.Context, r io.Reader, name *string) (*entities.ImageLoadReport, error) {
    96  	var report entities.ImageLoadReport
    97  	conn, err := bindings.GetClient(ctx)
    98  	if err != nil {
    99  		return nil, err
   100  	}
   101  	params := url.Values{}
   102  	if name != nil {
   103  		params.Set("reference", *name)
   104  	}
   105  	response, err := conn.DoRequest(r, http.MethodPost, "/images/load", params)
   106  	if err != nil {
   107  		return nil, err
   108  	}
   109  	return &report, response.Process(&report)
   110  }
   111  
   112  // Remove deletes an image from local storage.  The optional force parameter will forcibly remove
   113  // the image by removing all all containers, including those that are Running, first.
   114  func Remove(ctx context.Context, nameOrID string, force *bool) ([]map[string]string, error) {
   115  	var deletes []map[string]string
   116  	conn, err := bindings.GetClient(ctx)
   117  	if err != nil {
   118  		return nil, err
   119  	}
   120  	params := url.Values{}
   121  	if force != nil {
   122  		params.Set("force", strconv.FormatBool(*force))
   123  	}
   124  	response, err := conn.DoRequest(nil, http.MethodDelete, "/images/%s", params, nameOrID)
   125  	if err != nil {
   126  		return nil, err
   127  	}
   128  	return deletes, response.Process(&deletes)
   129  }
   130  
   131  // Export saves an image from local storage as a tarball or image archive.  The optional format
   132  // parameter is used to change the format of the output.
   133  func Export(ctx context.Context, nameOrID string, w io.Writer, format *string, compress *bool) error {
   134  	conn, err := bindings.GetClient(ctx)
   135  	if err != nil {
   136  		return err
   137  	}
   138  	params := url.Values{}
   139  	if format != nil {
   140  		params.Set("format", *format)
   141  	}
   142  	if compress != nil {
   143  		params.Set("compress", strconv.FormatBool(*compress))
   144  	}
   145  	response, err := conn.DoRequest(nil, http.MethodGet, "/images/%s/get", params, nameOrID)
   146  	if err != nil {
   147  		return err
   148  	}
   149  
   150  	if response.StatusCode/100 == 2 || response.StatusCode/100 == 3 {
   151  		_, err = io.Copy(w, response.Body)
   152  		return err
   153  	}
   154  	return nil
   155  }
   156  
   157  // Prune removes unused images from local storage.  The optional filters can be used to further
   158  // define which images should be pruned.
   159  func Prune(ctx context.Context, all *bool, filters map[string][]string) ([]string, error) {
   160  	var (
   161  		deleted []string
   162  	)
   163  	conn, err := bindings.GetClient(ctx)
   164  	if err != nil {
   165  		return nil, err
   166  	}
   167  	params := url.Values{}
   168  	if all != nil {
   169  		params.Set("all", strconv.FormatBool(*all))
   170  	}
   171  	if filters != nil {
   172  		stringFilter, err := bindings.FiltersToString(filters)
   173  		if err != nil {
   174  			return nil, err
   175  		}
   176  		params.Set("filters", stringFilter)
   177  	}
   178  	response, err := conn.DoRequest(nil, http.MethodPost, "/images/prune", params)
   179  	if err != nil {
   180  		return deleted, err
   181  	}
   182  	return deleted, response.Process(&deleted)
   183  }
   184  
   185  // Tag adds an additional name to locally-stored image. Both the tag and repo parameters are required.
   186  func Tag(ctx context.Context, nameOrID, tag, repo string) error {
   187  	conn, err := bindings.GetClient(ctx)
   188  	if err != nil {
   189  		return err
   190  	}
   191  	params := url.Values{}
   192  	params.Set("tag", tag)
   193  	params.Set("repo", repo)
   194  	response, err := conn.DoRequest(nil, http.MethodPost, "/images/%s/tag", params, nameOrID)
   195  	if err != nil {
   196  		return err
   197  	}
   198  	return response.Process(nil)
   199  }
   200  
   201  // Untag removes a name from locally-stored image. Both the tag and repo parameters are required.
   202  func Untag(ctx context.Context, nameOrID, tag, repo string) error {
   203  	conn, err := bindings.GetClient(ctx)
   204  	if err != nil {
   205  		return err
   206  	}
   207  	params := url.Values{}
   208  	params.Set("tag", tag)
   209  	params.Set("repo", repo)
   210  	response, err := conn.DoRequest(nil, http.MethodPost, "/images/%s/untag", params, nameOrID)
   211  	if err != nil {
   212  		return err
   213  	}
   214  	return response.Process(nil)
   215  }
   216  
   217  func Build(nameOrId string) {}
   218  
   219  // Imports adds the given image to the local image store.  This can be done by file and the given reader
   220  // or via the url parameter.  Additional metadata can be associated with the image by using the changes and
   221  // message parameters.  The image can also be tagged given a reference. One of url OR r must be provided.
   222  func Import(ctx context.Context, changes []string, message, reference, u *string, r io.Reader) (*entities.ImageImportReport, error) {
   223  	var report entities.ImageImportReport
   224  	if r != nil && u != nil {
   225  		return nil, errors.New("url and r parameters cannot be used together")
   226  	}
   227  	conn, err := bindings.GetClient(ctx)
   228  	if err != nil {
   229  		return nil, err
   230  	}
   231  	params := url.Values{}
   232  	for _, change := range changes {
   233  		params.Add("changes", change)
   234  	}
   235  	if message != nil {
   236  		params.Set("message", *message)
   237  	}
   238  	if reference != nil {
   239  		params.Set("reference", *reference)
   240  	}
   241  	if u != nil {
   242  		params.Set("url", *u)
   243  	}
   244  	response, err := conn.DoRequest(r, http.MethodPost, "/images/import", params)
   245  	if err != nil {
   246  		return nil, err
   247  	}
   248  	return &report, response.Process(&report)
   249  }
   250  
   251  // Pull is the binding for libpod's v2 endpoints for pulling images.  Note that
   252  // `rawImage` must be a reference to a registry (i.e., of docker transport or be
   253  // normalized to one).  Other transports are rejected as they do not make sense
   254  // in a remote context.
   255  func Pull(ctx context.Context, rawImage string, options entities.ImagePullOptions) ([]string, error) {
   256  	conn, err := bindings.GetClient(ctx)
   257  	if err != nil {
   258  		return nil, err
   259  	}
   260  	params := url.Values{}
   261  	params.Set("reference", rawImage)
   262  	params.Set("credentials", options.Credentials)
   263  	params.Set("overrideArch", options.OverrideArch)
   264  	params.Set("overrideOS", options.OverrideOS)
   265  	if options.TLSVerify != types.OptionalBoolUndefined {
   266  		val := bool(options.TLSVerify == types.OptionalBoolTrue)
   267  		params.Set("tlsVerify", strconv.FormatBool(val))
   268  	}
   269  	params.Set("allTags", strconv.FormatBool(options.AllTags))
   270  
   271  	response, err := conn.DoRequest(nil, http.MethodPost, "/images/pull", params)
   272  	if err != nil {
   273  		return nil, err
   274  	}
   275  
   276  	reports := []handlers.LibpodImagesPullReport{}
   277  	if err := response.Process(&reports); err != nil {
   278  		return nil, err
   279  	}
   280  
   281  	pulledImages := []string{}
   282  	for _, r := range reports {
   283  		pulledImages = append(pulledImages, r.ID)
   284  	}
   285  
   286  	return pulledImages, nil
   287  }
   288  
   289  // Push is the binding for libpod's v2 endpoints for push images.  Note that
   290  // `source` must be a refering to an image in the remote's container storage.
   291  // The destination must be a reference to a registry (i.e., of docker transport
   292  // or be normalized to one).  Other transports are rejected as they do not make
   293  // sense in a remote context.
   294  func Push(ctx context.Context, source string, destination string, options entities.ImagePushOptions) error {
   295  	conn, err := bindings.GetClient(ctx)
   296  	if err != nil {
   297  		return err
   298  	}
   299  	params := url.Values{}
   300  	params.Set("credentials", options.Credentials)
   301  	params.Set("destination", destination)
   302  	if options.TLSVerify != types.OptionalBoolUndefined {
   303  		val := bool(options.TLSVerify == types.OptionalBoolTrue)
   304  		params.Set("tlsVerify", strconv.FormatBool(val))
   305  	}
   306  
   307  	path := fmt.Sprintf("/images/%s/push", source)
   308  	_, err = conn.DoRequest(nil, http.MethodPost, path, params)
   309  	return err
   310  }
   311  
   312  // Search is the binding for libpod's v2 endpoints for Search images.
   313  func Search(ctx context.Context, term string, opts entities.ImageSearchOptions) ([]entities.ImageSearchReport, error) {
   314  	conn, err := bindings.GetClient(ctx)
   315  	if err != nil {
   316  		return nil, err
   317  	}
   318  	params := url.Values{}
   319  	params.Set("term", term)
   320  	params.Set("limit", strconv.Itoa(opts.Limit))
   321  	for _, f := range opts.Filters {
   322  		params.Set("filters", f)
   323  	}
   324  
   325  	if opts.TLSVerify != types.OptionalBoolUndefined {
   326  		val := bool(opts.TLSVerify == types.OptionalBoolTrue)
   327  		params.Set("tlsVerify", strconv.FormatBool(val))
   328  	}
   329  
   330  	response, err := conn.DoRequest(nil, http.MethodGet, "/images/search", params)
   331  	if err != nil {
   332  		return nil, err
   333  	}
   334  
   335  	results := []entities.ImageSearchReport{}
   336  	if err := response.Process(&results); err != nil {
   337  		return nil, err
   338  	}
   339  
   340  	return results, nil
   341  }