aboutsummaryrefslogtreecommitdiff
path: root/pkg/bindings/manifests/manifests.go
blob: 6aa4961f1dedba682ba2e66771cbb91fb25b7a70 (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
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
package manifests

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

	"github.com/containers/image/v5/manifest"
	"github.com/containers/podman/v3/pkg/api/handlers"
	"github.com/containers/podman/v3/pkg/bindings"
	"github.com/containers/podman/v3/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
	}
	defer response.Body.Close()

	return idr.ID, response.Process(&idr)
}

// Exists returns true if a given manifest list exists
func Exists(ctx context.Context, name string, options *ExistsOptions) (bool, error) {
	conn, err := bindings.GetClient(ctx)
	if err != nil {
		return false, err
	}
	response, err := conn.DoRequest(nil, http.MethodGet, "/manifests/%s/exists", nil, nil, name)
	if err != nil {
		return false, err
	}
	defer response.Body.Close()

	return response.IsSuccess(), nil
}

// 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
	}
	defer response.Body.Close()

	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
	}
	defer response.Body.Close()

	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
	}
	defer response.Body.Close()

	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)
	response, err := conn.DoRequest(nil, http.MethodPost, "/manifests/%s/push", params, nil, name)
	if err != nil {
		return "", err
	}
	defer response.Body.Close()

	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
//	}
//  defer response.Body.Close()
//	return idr.ID, response.Process(&idr)
//}