github.com/containers/podman/v4@v4.9.4/pkg/bindings/images/images.go (about)

     1  package images
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"fmt"
     7  	"io"
     8  	"net/http"
     9  	"net/url"
    10  	"strconv"
    11  
    12  	imageTypes "github.com/containers/image/v5/types"
    13  	"github.com/containers/podman/v4/pkg/api/handlers/types"
    14  	"github.com/containers/podman/v4/pkg/auth"
    15  	"github.com/containers/podman/v4/pkg/bindings"
    16  	"github.com/containers/podman/v4/pkg/domain/entities"
    17  	"github.com/containers/podman/v4/pkg/domain/entities/reports"
    18  )
    19  
    20  // Exists a lightweight way to determine if an image exists in local storage.  It returns a
    21  // boolean response.
    22  func Exists(ctx context.Context, nameOrID string, options *ExistsOptions) (bool, error) {
    23  	conn, err := bindings.GetClient(ctx)
    24  	if err != nil {
    25  		return false, err
    26  	}
    27  	response, err := conn.DoRequest(ctx, nil, http.MethodGet, "/images/%s/exists", nil, nil, nameOrID)
    28  	if err != nil {
    29  		return false, err
    30  	}
    31  	defer response.Body.Close()
    32  
    33  	return response.IsSuccess(), nil
    34  }
    35  
    36  // List returns a list of images in local storage.  The all boolean and filters parameters are optional
    37  // ways to alter the image query.
    38  func List(ctx context.Context, options *ListOptions) ([]*entities.ImageSummary, error) {
    39  	if options == nil {
    40  		options = new(ListOptions)
    41  	}
    42  	var imageSummary []*entities.ImageSummary
    43  	conn, err := bindings.GetClient(ctx)
    44  	if err != nil {
    45  		return nil, err
    46  	}
    47  	params, err := options.ToParams()
    48  	if err != nil {
    49  		return nil, err
    50  	}
    51  	response, err := conn.DoRequest(ctx, nil, http.MethodGet, "/images/json", params, nil)
    52  	if err != nil {
    53  		return imageSummary, err
    54  	}
    55  	defer response.Body.Close()
    56  
    57  	return imageSummary, response.Process(&imageSummary)
    58  }
    59  
    60  // Get performs an image inspect.  To have the on-disk size of the image calculated, you can
    61  // use the optional size parameter.
    62  func GetImage(ctx context.Context, nameOrID string, options *GetOptions) (*entities.ImageInspectReport, error) {
    63  	if options == nil {
    64  		options = new(GetOptions)
    65  	}
    66  	conn, err := bindings.GetClient(ctx)
    67  	if err != nil {
    68  		return nil, err
    69  	}
    70  	params, err := options.ToParams()
    71  	if err != nil {
    72  		return nil, err
    73  	}
    74  	inspectedData := entities.ImageInspectReport{}
    75  	response, err := conn.DoRequest(ctx, nil, http.MethodGet, "/images/%s/json", params, nil, nameOrID)
    76  	if err != nil {
    77  		return &inspectedData, err
    78  	}
    79  	defer response.Body.Close()
    80  
    81  	return &inspectedData, response.Process(&inspectedData)
    82  }
    83  
    84  // Tree retrieves a "tree" based representation of the given image
    85  func Tree(ctx context.Context, nameOrID string, options *TreeOptions) (*entities.ImageTreeReport, error) {
    86  	if options == nil {
    87  		options = new(TreeOptions)
    88  	}
    89  	var report entities.ImageTreeReport
    90  	conn, err := bindings.GetClient(ctx)
    91  	if err != nil {
    92  		return nil, err
    93  	}
    94  	params, err := options.ToParams()
    95  	if err != nil {
    96  		return nil, err
    97  	}
    98  	response, err := conn.DoRequest(ctx, nil, http.MethodGet, "/images/%s/tree", params, nil, nameOrID)
    99  	if err != nil {
   100  		return nil, err
   101  	}
   102  	defer response.Body.Close()
   103  
   104  	return &report, response.Process(&report)
   105  }
   106  
   107  // History returns the parent layers of an image.
   108  func History(ctx context.Context, nameOrID string, options *HistoryOptions) ([]*types.HistoryResponse, error) {
   109  	if options == nil {
   110  		options = new(HistoryOptions)
   111  	}
   112  	_ = options
   113  	var history []*types.HistoryResponse
   114  	conn, err := bindings.GetClient(ctx)
   115  	if err != nil {
   116  		return nil, err
   117  	}
   118  	response, err := conn.DoRequest(ctx, nil, http.MethodGet, "/images/%s/history", nil, nil, nameOrID)
   119  	if err != nil {
   120  		return history, err
   121  	}
   122  	defer response.Body.Close()
   123  
   124  	return history, response.Process(&history)
   125  }
   126  
   127  func Load(ctx context.Context, r io.Reader) (*entities.ImageLoadReport, error) {
   128  	var report entities.ImageLoadReport
   129  	conn, err := bindings.GetClient(ctx)
   130  	if err != nil {
   131  		return nil, err
   132  	}
   133  	response, err := conn.DoRequest(ctx, r, http.MethodPost, "/images/load", nil, nil)
   134  	if err != nil {
   135  		return nil, err
   136  	}
   137  	defer response.Body.Close()
   138  
   139  	return &report, response.Process(&report)
   140  }
   141  
   142  // Export saves images from local storage as a tarball or image archive.  The optional format
   143  // parameter is used to change the format of the output.
   144  func Export(ctx context.Context, nameOrIDs []string, w io.Writer, options *ExportOptions) error {
   145  	if options == nil {
   146  		options = new(ExportOptions)
   147  	}
   148  	conn, err := bindings.GetClient(ctx)
   149  	if err != nil {
   150  		return err
   151  	}
   152  	params, err := options.ToParams()
   153  	if err != nil {
   154  		return err
   155  	}
   156  	for _, ref := range nameOrIDs {
   157  		params.Add("references", ref)
   158  	}
   159  	response, err := conn.DoRequest(ctx, nil, http.MethodGet, "/images/export", params, nil)
   160  	if err != nil {
   161  		return err
   162  	}
   163  	defer response.Body.Close()
   164  
   165  	if response.StatusCode/100 == 2 || response.StatusCode/100 == 3 {
   166  		_, err = io.Copy(w, response.Body)
   167  		return err
   168  	}
   169  	return response.Process(nil)
   170  }
   171  
   172  // Prune removes unused images from local storage.  The optional filters can be used to further
   173  // define which images should be pruned.
   174  func Prune(ctx context.Context, options *PruneOptions) ([]*reports.PruneReport, error) {
   175  	var (
   176  		deleted []*reports.PruneReport
   177  	)
   178  	if options == nil {
   179  		options = new(PruneOptions)
   180  	}
   181  	conn, err := bindings.GetClient(ctx)
   182  	if err != nil {
   183  		return nil, err
   184  	}
   185  	params, err := options.ToParams()
   186  	if err != nil {
   187  		return nil, err
   188  	}
   189  	response, err := conn.DoRequest(ctx, nil, http.MethodPost, "/images/prune", params, nil)
   190  	if err != nil {
   191  		return deleted, err
   192  	}
   193  	defer response.Body.Close()
   194  
   195  	return deleted, response.Process(&deleted)
   196  }
   197  
   198  // Tag adds an additional name to locally-stored image. Both the tag and repo parameters are required.
   199  func Tag(ctx context.Context, nameOrID, tag, repo string, options *TagOptions) error {
   200  	if options == nil {
   201  		options = new(TagOptions)
   202  	}
   203  	_ = options
   204  	conn, err := bindings.GetClient(ctx)
   205  	if err != nil {
   206  		return err
   207  	}
   208  	params := url.Values{}
   209  	params.Set("tag", tag)
   210  	params.Set("repo", repo)
   211  	response, err := conn.DoRequest(ctx, nil, http.MethodPost, "/images/%s/tag", params, nil, nameOrID)
   212  	if err != nil {
   213  		return err
   214  	}
   215  	defer response.Body.Close()
   216  
   217  	return response.Process(nil)
   218  }
   219  
   220  // Untag removes a name from locally-stored image. Both the tag and repo parameters are required.
   221  func Untag(ctx context.Context, nameOrID, tag, repo string, options *UntagOptions) error {
   222  	if options == nil {
   223  		options = new(UntagOptions)
   224  	}
   225  	_ = options
   226  	conn, err := bindings.GetClient(ctx)
   227  	if err != nil {
   228  		return err
   229  	}
   230  	params := url.Values{}
   231  	params.Set("tag", tag)
   232  	params.Set("repo", repo)
   233  	response, err := conn.DoRequest(ctx, nil, http.MethodPost, "/images/%s/untag", params, nil, nameOrID)
   234  	if err != nil {
   235  		return err
   236  	}
   237  	defer response.Body.Close()
   238  
   239  	return response.Process(nil)
   240  }
   241  
   242  // Import adds the given image to the local image store.  This can be done by file and the given reader
   243  // or via the url parameter.  Additional metadata can be associated with the image by using the changes and
   244  // message parameters.  The image can also be tagged given a reference. One of url OR r must be provided.
   245  func Import(ctx context.Context, r io.Reader, options *ImportOptions) (*entities.ImageImportReport, error) {
   246  	if options == nil {
   247  		options = new(ImportOptions)
   248  	}
   249  	var report entities.ImageImportReport
   250  	if r != nil && options.URL != nil {
   251  		return nil, errors.New("url and r parameters cannot be used together")
   252  	}
   253  	conn, err := bindings.GetClient(ctx)
   254  	if err != nil {
   255  		return nil, err
   256  	}
   257  	params, err := options.ToParams()
   258  	if err != nil {
   259  		return nil, err
   260  	}
   261  	response, err := conn.DoRequest(ctx, r, http.MethodPost, "/images/import", params, nil)
   262  	if err != nil {
   263  		return nil, err
   264  	}
   265  	defer response.Body.Close()
   266  
   267  	return &report, response.Process(&report)
   268  }
   269  
   270  // Search is the binding for libpod's v2 endpoints for Search images.
   271  func Search(ctx context.Context, term string, options *SearchOptions) ([]entities.ImageSearchReport, error) {
   272  	if options == nil {
   273  		options = new(SearchOptions)
   274  	}
   275  	conn, err := bindings.GetClient(ctx)
   276  	if err != nil {
   277  		return nil, err
   278  	}
   279  	params, err := options.ToParams()
   280  	if err != nil {
   281  		return nil, err
   282  	}
   283  	params.Set("term", term)
   284  
   285  	// SkipTLSVerify is special.  It's not being serialized by ToParams()
   286  	// because we need to flip the boolean.
   287  	if options.SkipTLSVerify != nil {
   288  		params.Set("tlsVerify", strconv.FormatBool(!options.GetSkipTLSVerify()))
   289  	}
   290  
   291  	header, err := auth.MakeXRegistryAuthHeader(&imageTypes.SystemContext{AuthFilePath: options.GetAuthfile()}, options.GetUsername(), options.GetPassword())
   292  	if err != nil {
   293  		return nil, err
   294  	}
   295  
   296  	response, err := conn.DoRequest(ctx, nil, http.MethodGet, "/images/search", params, header)
   297  	if err != nil {
   298  		return nil, err
   299  	}
   300  	defer response.Body.Close()
   301  
   302  	results := []entities.ImageSearchReport{}
   303  	if err := response.Process(&results); err != nil {
   304  		return nil, err
   305  	}
   306  
   307  	return results, nil
   308  }
   309  
   310  func Scp(ctx context.Context, source, destination *string, options ScpOptions) (reports.ScpReport, error) {
   311  	rep := reports.ScpReport{}
   312  
   313  	conn, err := bindings.GetClient(ctx)
   314  	if err != nil {
   315  		return rep, err
   316  	}
   317  	params, err := options.ToParams()
   318  	if err != nil {
   319  		return rep, err
   320  	}
   321  	response, err := conn.DoRequest(ctx, nil, http.MethodPost, fmt.Sprintf("/images/scp/%s", *source), params, nil)
   322  	if err != nil {
   323  		return rep, err
   324  	}
   325  	defer response.Body.Close()
   326  
   327  	return rep, response.Process(&rep)
   328  }