feat(pkger): extend HTTP API to enable users to submit multiple pkgs in one call
parent
ec13042c57
commit
684f7b82ad
|
@ -7145,18 +7145,24 @@ components:
|
|||
type: string
|
||||
package:
|
||||
$ref: "#/components/schemas/Pkg"
|
||||
packages:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/Pkg"
|
||||
secrets:
|
||||
type: object
|
||||
additionalProperties:
|
||||
type: string
|
||||
remote:
|
||||
type: object
|
||||
properties:
|
||||
url:
|
||||
type: string
|
||||
contentType:
|
||||
type: string
|
||||
required: ["url"]
|
||||
remotes:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
properties:
|
||||
url:
|
||||
type: string
|
||||
contentType:
|
||||
type: string
|
||||
required: ["url"]
|
||||
PkgCreate:
|
||||
type: object
|
||||
properties:
|
||||
|
|
|
@ -152,19 +152,45 @@ func (p PkgRemote) Encoding() Encoding {
|
|||
type ReqApplyPkg struct {
|
||||
DryRun bool `json:"dryRun" yaml:"dryRun"`
|
||||
OrgID string `json:"orgID" yaml:"orgID"`
|
||||
Remote PkgRemote `json:"remote" yaml:"remote"`
|
||||
Remotes []PkgRemote `json:"remotes" yaml:"remotes"`
|
||||
RawPkgs []json.RawMessage `json:"packages" yaml:"packages"`
|
||||
RawPkg json.RawMessage `json:"package" yaml:"package"`
|
||||
EnvRefs map[string]string `json:"envRefs"`
|
||||
Secrets map[string]string `json:"secrets"`
|
||||
}
|
||||
|
||||
// Pkg returns a pkg parsed and validated from the RawPkg field.
|
||||
func (r ReqApplyPkg) Pkg(encoding Encoding) (*Pkg, error) {
|
||||
if r.Remote.URL != "" {
|
||||
return Parse(r.Remote.Encoding(), FromHTTPRequest(r.Remote.URL))
|
||||
// Pkgs returns all pkgs associated with the request.
|
||||
func (r ReqApplyPkg) Pkgs(encoding Encoding) (*Pkg, error) {
|
||||
var rawPkgs []*Pkg
|
||||
for _, rem := range r.Remotes {
|
||||
if rem.URL == "" {
|
||||
continue
|
||||
}
|
||||
pkg, err := Parse(rem.Encoding(), FromHTTPRequest(rem.URL), ValidSkipParseError())
|
||||
if err != nil {
|
||||
return nil, &influxdb.Error{
|
||||
Code: influxdb.EUnprocessableEntity,
|
||||
Msg: fmt.Sprintf("pkg from url[%s] had an issue: %s", rem.URL, err.Error()),
|
||||
}
|
||||
}
|
||||
rawPkgs = append(rawPkgs, pkg)
|
||||
}
|
||||
|
||||
return Parse(encoding, FromReader(bytes.NewReader(r.RawPkg)))
|
||||
for i, rawPkg := range append(r.RawPkgs, r.RawPkg) {
|
||||
if rawPkg == nil {
|
||||
continue
|
||||
}
|
||||
pkg, err := Parse(encoding, FromReader(bytes.NewReader(rawPkg)), ValidSkipParseError())
|
||||
if err != nil {
|
||||
return nil, &influxdb.Error{
|
||||
Code: influxdb.EUnprocessableEntity,
|
||||
Msg: fmt.Sprintf("pkg [%d] had an issue: %s", i, err.Error()),
|
||||
}
|
||||
}
|
||||
rawPkgs = append(rawPkgs, pkg)
|
||||
}
|
||||
|
||||
return Combine(rawPkgs...)
|
||||
}
|
||||
|
||||
// RespApplyPkg is the response body for the apply pkg endpoint.
|
||||
|
@ -199,10 +225,10 @@ func (s *HTTPServer) applyPkg(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
userID := auth.GetUserID()
|
||||
|
||||
parsedPkg, err := reqBody.Pkg(encoding)
|
||||
parsedPkg, err := reqBody.Pkgs(encoding)
|
||||
if err != nil {
|
||||
s.api.Err(w, &influxdb.Error{
|
||||
Code: influxdb.EInvalid,
|
||||
Code: influxdb.EUnprocessableEntity,
|
||||
Err: err,
|
||||
})
|
||||
return
|
||||
|
@ -302,7 +328,7 @@ func convertParseErr(err error) []ValidationErr {
|
|||
|
||||
func newDecodeErr(encoding string, err error) *influxdb.Error {
|
||||
return &influxdb.Error{
|
||||
Msg: fmt.Sprintf("unable to unmarshal %s; Err: %v", encoding, err),
|
||||
Msg: fmt.Sprintf("unable to unmarshal %s", encoding),
|
||||
Code: influxdb.EInvalid,
|
||||
Err: err,
|
||||
}
|
||||
|
|
|
@ -103,9 +103,18 @@ func TestPkgerHTTPServer(t *testing.T) {
|
|||
reqBody: pkger.ReqApplyPkg{
|
||||
DryRun: true,
|
||||
OrgID: influxdb.ID(9000).String(),
|
||||
Remote: pkger.PkgRemote{
|
||||
Remotes: []pkger.PkgRemote{{
|
||||
URL: "https://gist.githubusercontent.com/jsteenb2/3a3b2b5fcbd6179b2494c2b54aa2feb0/raw/989d361db7a851a3c388eaed0b59dce7fca7fdf3/bucket_pkg.json",
|
||||
},
|
||||
}},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "app jsonnet",
|
||||
contentType: "application/x-jsonnet",
|
||||
reqBody: pkger.ReqApplyPkg{
|
||||
DryRun: true,
|
||||
OrgID: influxdb.ID(9000).String(),
|
||||
RawPkg: bucketPkgKinds(t, pkger.EncodingJsonnet),
|
||||
},
|
||||
},
|
||||
{
|
||||
|
@ -213,6 +222,107 @@ func TestPkgerHTTPServer(t *testing.T) {
|
|||
t.Run(tt.name, fn)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("with multiple pkgs", func(t *testing.T) {
|
||||
newBktPkg := func(t *testing.T, bktName string) json.RawMessage {
|
||||
t.Helper()
|
||||
|
||||
pkgStr := fmt.Sprintf(`[
|
||||
{
|
||||
"apiVersion": "%[1]s",
|
||||
"kind": "Bucket",
|
||||
"metadata": {
|
||||
"name": %q
|
||||
},
|
||||
"spec": {}
|
||||
}
|
||||
]`, pkger.APIVersion, bktName)
|
||||
|
||||
pkg, err := pkger.Parse(pkger.EncodingJSON, pkger.FromString(pkgStr))
|
||||
require.NoError(t, err)
|
||||
|
||||
pkgBytes, err := pkg.Encode(pkger.EncodingJSON)
|
||||
require.NoError(t, err)
|
||||
return pkgBytes
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
reqBody pkger.ReqApplyPkg
|
||||
expectedBkts []string
|
||||
}{
|
||||
{
|
||||
name: "retrieves package from a URL and raw pkgs",
|
||||
reqBody: pkger.ReqApplyPkg{
|
||||
DryRun: true,
|
||||
OrgID: influxdb.ID(9000).String(),
|
||||
Remotes: []pkger.PkgRemote{{
|
||||
ContentType: "json",
|
||||
URL: "https://gist.githubusercontent.com/jsteenb2/3a3b2b5fcbd6179b2494c2b54aa2feb0/raw/989d361db7a851a3c388eaed0b59dce7fca7fdf3/bucket_pkg.json",
|
||||
}},
|
||||
RawPkgs: []json.RawMessage{
|
||||
newBktPkg(t, "bkt1"),
|
||||
newBktPkg(t, "bkt2"),
|
||||
newBktPkg(t, "bkt3"),
|
||||
},
|
||||
},
|
||||
expectedBkts: []string{"bkt1", "bkt2", "bkt3", "rucket_11"},
|
||||
},
|
||||
{
|
||||
name: "retrieves packages from raw single and list",
|
||||
reqBody: pkger.ReqApplyPkg{
|
||||
DryRun: true,
|
||||
OrgID: influxdb.ID(9000).String(),
|
||||
RawPkg: newBktPkg(t, "bkt4"),
|
||||
RawPkgs: []json.RawMessage{
|
||||
newBktPkg(t, "bkt1"),
|
||||
newBktPkg(t, "bkt2"),
|
||||
newBktPkg(t, "bkt3"),
|
||||
},
|
||||
},
|
||||
expectedBkts: []string{"bkt1", "bkt2", "bkt3", "bkt4"},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
fn := func(t *testing.T) {
|
||||
svc := &fakeSVC{
|
||||
DryRunFn: func(ctx context.Context, orgID, userID influxdb.ID, pkg *pkger.Pkg, opts ...pkger.ApplyOptFn) (pkger.Summary, pkger.Diff, error) {
|
||||
if err := pkg.Validate(); err != nil {
|
||||
return pkger.Summary{}, pkger.Diff{}, err
|
||||
}
|
||||
sum := pkg.Summary()
|
||||
var diff pkger.Diff
|
||||
for _, b := range sum.Buckets {
|
||||
diff.Buckets = append(diff.Buckets, pkger.DiffBucket{
|
||||
Name: b.Name,
|
||||
})
|
||||
}
|
||||
return sum, diff, nil
|
||||
},
|
||||
}
|
||||
|
||||
pkgHandler := pkger.NewHTTPServer(zap.NewNop(), svc)
|
||||
svr := newMountedHandler(pkgHandler, 1)
|
||||
|
||||
testttp.
|
||||
PostJSON(t, "/api/v2/packages/apply", tt.reqBody).
|
||||
Do(svr).
|
||||
ExpectStatus(http.StatusOK).
|
||||
ExpectBody(func(buf *bytes.Buffer) {
|
||||
var resp pkger.RespApplyPkg
|
||||
decodeBody(t, buf, &resp)
|
||||
|
||||
require.Len(t, resp.Summary.Buckets, len(tt.expectedBkts))
|
||||
for i, expected := range tt.expectedBkts {
|
||||
assert.Equal(t, expected, resp.Summary.Buckets[i].Name)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
t.Run(tt.name, fn)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
t.Run("apply a pkg", func(t *testing.T) {
|
||||
|
|
Loading…
Reference in New Issue