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 }