summaryrefslogtreecommitdiff
path: root/pkg/bindings/manifests/manifests.go
blob: b6db64b0231eccebcb3a9ef79bb294f3a0d0d6ab (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
package manifests

import (
	"context"
	"errors"
	"net/http"
	"net/url"
	"strconv"
	"strings"

	"github.com/containers/image/v5/manifest"
	"github.com/containers/podman/v2/pkg/api/handlers"
	"github.com/containers/podman/v2/pkg/bindings"
	"github.com/containers/podman/v2/pkg/bindings/images"
	jsoniter "github.com/json-iterator/go"
)

// Create creates a manifest for the given name.  Optional images to be associated with
// the new manifest can also be specified.  The all boolean specifies to add all entries
// of a list if the name provided is a manifest list.  The ID of the new manifest list
// is returned as a string.
func Create(ctx context.Context, names, images []string, options *CreateOptions) (string, error) {
	var idr handlers.IDResponse
	if options == nil {
		options = new(CreateOptions)
	}
	conn, err := bindings.GetClient(ctx)
	if err != nil {
		return "", err
	}
	if len(names) < 1 {
		return "", errors.New("creating a manifest requires at least one name argument")
	}
	params, err := options.ToParams()
	if err != nil {
		return "", err
	}
	for _, name := range names {
		params.Add("name", name)
	}
	for _, i := range images {
		params.Add("image", i)
	}

	response, err := conn.DoRequest(nil, http.MethodPost, "/manifests/create", params, nil)
	if err != nil {
		return "", err
	}
	return idr.ID, response.Process(&idr)
}

// Inspect returns a manifest list for a given name.
func Inspect(ctx context.Context, name string, options *InspectOptions) (*manifest.Schema2List, error) {
	var list manifest.Schema2List
	if options == nil {
		options = new(InspectOptions)
	}
	_ = options
	conn, err := bindings.GetClient(ctx)
	if err != nil {
		return nil, err
	}
	response, err := conn.DoRequest(nil, http.MethodGet, "/manifests/%s/json", nil, nil, name)
	if err != nil {
		return nil, err
	}
	return &list, response.Process(&list)
}

// Add adds a manifest to a given manifest list.  Additional options for the manifest
// can also be specified.  The ID of the new manifest list is returned as a string
func Add(ctx context.Context, name string, options *AddOptions) (string, error) {
	var idr handlers.IDResponse
	if options == nil {
		options = new(AddOptions)
	}
	conn, err := bindings.GetClient(ctx)
	if err != nil {
		return "", err
	}
	optionsString, err := jsoniter.MarshalToString(options)
	if err != nil {
		return "", err
	}
	stringReader := strings.NewReader(optionsString)
	response, err := conn.DoRequest(stringReader, http.MethodPost, "/manifests/%s/add", nil, nil, name)
	if err != nil {
		return "", err
	}
	return idr.ID, response.Process(&idr)
}

// Remove deletes a manifest entry from a manifest list.  Both name and the digest to be
// removed are mandatory inputs.  The ID of the new manifest list is returned as a string.
func Remove(ctx context.Context, name, digest string, options *RemoveOptions) (string, error) {
	var idr handlers.IDResponse
	if options == nil {
		options = new(RemoveOptions)
	}
	_ = options
	conn, err := bindings.GetClient(ctx)
	if err != nil {
		return "", err
	}
	params := url.Values{}
	params.Set("digest", digest)
	response, err := conn.DoRequest(nil, http.MethodDelete, "/manifests/%s", params, nil, name)
	if err != nil {
		return "", err
	}
	return idr.ID, response.Process(&idr)
}

// Push takes a manifest list and pushes to a destination.  If the destination is not specified,
// the name will be used instead.  If the optional all boolean is specified, all images specified
// in the list will be pushed as well.
func Push(ctx context.Context, name, destination string, options *images.PushOptions) (string, error) {
	var (
		idr handlers.IDResponse
	)
	if options == nil {
		options = new(images.PushOptions)
	}
	if len(destination) < 1 {
		destination = name
	}
	conn, err := bindings.GetClient(ctx)
	if err != nil {
		return "", err
	}
	params, err := options.ToParams()
	if err != nil {
		return "", err
	}
	//SkipTLSVerify is special.  We need to delete the param added by
	//toparams and change the key and flip the bool
	if options.SkipTLSVerify != nil {
		params.Del("SkipTLSVerify")
		params.Set("tlsVerify", strconv.FormatBool(!options.GetSkipTLSVerify()))
	}
	params.Set("image", name)
	params.Set("destination", destination)
	params.Set("format", *options.Format)
	_, err = conn.DoRequest(nil, http.MethodPost, "/manifests/%s/push", params, nil, name)
	if err != nil {
		return "", err
	}
	return idr.ID, err
}

// There is NO annotate endpoint.  this binding could never work
// Annotate updates the image configuration of a given manifest list
//func Annotate(ctx context.Context, name, digest string, options image.ManifestAnnotateOpts) (string, error) {
//	var idr handlers.IDResponse
//	conn, err := bindings.GetClient(ctx)
//	if err != nil {
//		return "", err
//	}
//	params := url.Values{}
//	params.Set("digest", digest)
//	optionsString, err := jsoniter.MarshalToString(options)
//	if err != nil {
//		return "", err
//	}
//	stringReader := strings.NewReader(optionsString)
//	response, err := conn.DoRequest(stringReader, http.MethodPost, "/manifests/%s/annotate", params, name)
//	if err != nil {
//		return "", err
//	}
//	return idr.ID, response.Process(&idr)
//}