Skip to content

Commit

Permalink
feat(pkger): add ability to skip a resource within a template
Browse files Browse the repository at this point in the history
references: #18490
  • Loading branch information
jsteenb2 committed Jun 18, 2020
1 parent 0b531e8 commit a4e4be7
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 14 deletions.
85 changes: 85 additions & 0 deletions cmd/influxd/launcher/pkger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1537,6 +1537,91 @@ func TestLauncher_Pkger(t *testing.T) {
})
})

t.Run("apply with actions", func(t *testing.T) {
stack, cleanup := newStackFn(t, pkger.Stack{})
defer func() {
if t.Failed() {
cleanup()
}
}()

var (
bucketPkgName = "rucketeer-1"
checkPkgName = "checkers"
dashPkgName = "dash-of-salt"
endpointPkgName = "endzo"
labelPkgName = "labelino"
rulePkgName = "oh-doyle-rules"
taskPkgName = "tap"
telegrafPkgName = "teletype"
variablePkgName = "laces-out-dan"
)
pkg := newPkg(
newBucketObject(bucketPkgName, "", ""),
newCheckDeadmanObject(t, checkPkgName, "", time.Hour),
newDashObject(dashPkgName, "", ""),
newEndpointHTTP(endpointPkgName, "", ""),
newLabelObject(labelPkgName, "", "", ""),
newRuleObject(t, rulePkgName, "", endpointPkgName, ""),
newTaskObject(taskPkgName, "", ""),
newTelegrafObject(telegrafPkgName, "", ""),
newVariableObject(variablePkgName, "", ""),
)

impact, err := svc.Apply(ctx, l.Org.ID, l.User.ID,
pkger.ApplyWithPkg(pkg),
pkger.ApplyWithStackID(stack.ID),
pkger.ApplyWithResourceSkip(pkger.ActionSkipResource{
Kind: pkger.KindBucket,
MetaName: bucketPkgName,
}),
pkger.ApplyWithResourceSkip(pkger.ActionSkipResource{
Kind: pkger.KindCheckDeadman,
MetaName: checkPkgName,
}),
pkger.ApplyWithResourceSkip(pkger.ActionSkipResource{
Kind: pkger.KindDashboard,
MetaName: dashPkgName,
}),
pkger.ApplyWithResourceSkip(pkger.ActionSkipResource{
Kind: pkger.KindNotificationEndpointHTTP,
MetaName: endpointPkgName,
}),
pkger.ApplyWithResourceSkip(pkger.ActionSkipResource{
Kind: pkger.KindLabel,
MetaName: labelPkgName,
}),
pkger.ApplyWithResourceSkip(pkger.ActionSkipResource{
Kind: pkger.KindNotificationRule,
MetaName: rulePkgName,
}),
pkger.ApplyWithResourceSkip(pkger.ActionSkipResource{
Kind: pkger.KindTask,
MetaName: taskPkgName,
}),
pkger.ApplyWithResourceSkip(pkger.ActionSkipResource{
Kind: pkger.KindTelegraf,
MetaName: telegrafPkgName,
}),
pkger.ApplyWithResourceSkip(pkger.ActionSkipResource{
Kind: pkger.KindVariable,
MetaName: variablePkgName,
}),
)
require.NoError(t, err)

summary := impact.Summary
assert.Empty(t, summary.Buckets)
assert.Empty(t, summary.Checks)
assert.Empty(t, summary.Dashboards)
assert.Empty(t, summary.NotificationEndpoints)
assert.Empty(t, summary.Labels)
assert.Empty(t, summary.NotificationRules, 0)
assert.Empty(t, summary.Tasks)
assert.Empty(t, summary.TelegrafConfigs)
assert.Empty(t, summary.Variables)
})

t.Run("exporting the existing state of stack resources to a pkg", func(t *testing.T) {
testStackApplyFn := func(t *testing.T) (pkger.Summary, pkger.Stack, func()) {
t.Helper()
Expand Down
17 changes: 17 additions & 0 deletions http/swagger.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7691,6 +7691,23 @@ components:
contentType:
type: string
required: ["url"]
actions:
type: array
items:
oneOf:
- type: object
properties:
action:
type: string
enum: ["skipResource"]
properties:
type: object
properties:
kind:
type: string
resourceTemplateName:
type: string
required: ["kind", "resourceTemplateName"]
PkgCreateKind:
type: string
enum:
Expand Down
12 changes: 12 additions & 0 deletions pkger/http_remote_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package pkger

import (
"context"
"encoding/json"
"net/http"

"github.com/influxdata/influxdb/v2"
Expand Down Expand Up @@ -214,6 +215,17 @@ func (s *HTTPRemoteService) apply(ctx context.Context, orgID influxdb.ID, dryRun
reqBody.StackID = &stackID
}

for act := range opt.ResourcesToSkip {
b, err := json.Marshal(act)
if err != nil {
return PkgImpactSummary{}, influxErr(influxdb.EInvalid, err)
}
reqBody.RawActions = append(reqBody.RawActions, ReqRawAction{
Action: string(ActionTypeSkipResource),
Properties: b,
})
}

var resp RespApplyPkg
err := s.Client.
PostJSON(reqBody, RoutePrefix, "/apply").
Expand Down
66 changes: 59 additions & 7 deletions pkger/http_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,13 @@ func (p ReqRawPkg) Encoding() Encoding {
return convertEncoding(p.ContentType, source)
}

// ReqRawAction is a raw action consumers can provide to change the behavior
// of the application of a template.
type ReqRawAction struct {
Action string `json:"action"`
Properties json.RawMessage `json:"properties"`
}

// ReqApplyPkg is the request body for a json or yaml body for the apply pkg endpoint.
type ReqApplyPkg struct {
DryRun bool `json:"dryRun" yaml:"dryRun"`
Expand All @@ -489,6 +496,8 @@ type ReqApplyPkg struct {

EnvRefs map[string]string `json:"envRefs"`
Secrets map[string]string `json:"secrets"`

RawActions []ReqRawAction `json:"actions"`
}

// Pkgs returns all pkgs associated with the request.
Expand Down Expand Up @@ -545,6 +554,40 @@ func (r ReqApplyPkg) Pkgs(encoding Encoding) (*Pkg, error) {
return Combine(rawPkgs, ValidWithoutResources(), ValidSkipParseError())
}

type actionType string

const (
ActionTypeSkipResource actionType = "skipResource"
)

func (r ReqApplyPkg) validActions() (struct {
SkipResources []ActionSkipResource
}, error) {
type actions struct {
SkipResources []ActionSkipResource
}

var out actions
for _, rawAct := range r.RawActions {
switch a := rawAct.Action; actionType(a) {
case ActionTypeSkipResource:
var asr ActionSkipResource
if err := json.Unmarshal(rawAct.Properties, &asr); err != nil {
return actions{}, influxErr(influxdb.EInvalid, err)
}
if err := asr.Kind.OK(); err != nil {
return actions{}, influxErr(influxdb.EInvalid, err)
}
out.SkipResources = append(out.SkipResources, asr)
default:
msg := fmt.Sprintf("invalid action type provided %q; Must be one of [%s]", a, ActionTypeSkipResource)
return actions{}, influxErr(influxdb.EInvalid, msg)
}
}

return out, nil
}

// RespApplyPkg is the response body for the apply pkg endpoint.
type RespApplyPkg struct {
Sources []string `json:"sources" yaml:"sources"`
Expand Down Expand Up @@ -583,13 +626,6 @@ func (s *HTTPServer) applyPkg(w http.ResponseWriter, r *http.Request) {
}
}

auth, err := pctx.GetAuthorizer(r.Context())
if err != nil {
s.api.Err(w, r, err)
return
}
userID := auth.GetUserID()

parsedPkg, err := reqBody.Pkgs(encoding)
if err != nil {
s.api.Err(w, r, &influxdb.Error{
Expand All @@ -599,11 +635,27 @@ func (s *HTTPServer) applyPkg(w http.ResponseWriter, r *http.Request) {
return
}

actions, err := reqBody.validActions()
if err != nil {
s.api.Err(w, r, err)
return
}

applyOpts := []ApplyOptFn{
ApplyWithEnvRefs(reqBody.EnvRefs),
ApplyWithPkg(parsedPkg),
ApplyWithStackID(stackID),
}
for _, a := range actions.SkipResources {
applyOpts = append(applyOpts, ApplyWithResourceSkip(a))
}

auth, err := pctx.GetAuthorizer(r.Context())
if err != nil {
s.api.Err(w, r, err)
return
}
userID := auth.GetUserID()

if reqBody.DryRun {
impact, err := s.svc.DryRun(r.Context(), *orgID, userID, applyOpts...)
Expand Down
25 changes: 18 additions & 7 deletions pkger/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -295,7 +295,7 @@ func (s *Service) InitStack(ctx context.Context, userID influxdb.ID, stack Stack
if _, err := s.orgSVC.FindOrganizationByID(ctx, stack.OrgID); err != nil {
if influxdb.ErrorCode(err) == influxdb.ENotFound {
msg := fmt.Sprintf("organization dependency does not exist for id[%q]", stack.OrgID.String())
return Stack{}, toInfluxError(influxdb.EConflict, msg)
return Stack{}, influxErr(influxdb.EConflict, msg)
}
return Stack{}, internalErr(err)
}
Expand Down Expand Up @@ -1377,7 +1377,7 @@ type (
}

// ActionSkipResource provides an action from the consumer to use the pkg with
// modifications to the actual state that is applied.
// modifications to the resource kind and pkg name that will be applied.
ActionSkipResource struct {
Kind Kind `json:"kind"`
MetaName string `json:"resourceTemplateName"`
Expand Down Expand Up @@ -3519,7 +3519,7 @@ func validURLs(urls []string) error {
for _, u := range urls {
if _, err := url.Parse(u); err != nil {
msg := fmt.Sprintf("url invalid for entry %q", u)
return toInfluxError(influxdb.EInvalid, msg)
return influxErr(influxdb.EInvalid, msg)
}
}
return nil
Expand All @@ -3544,12 +3544,23 @@ func internalErr(err error) error {
if err == nil {
return nil
}
return toInfluxError(influxdb.EInternal, err.Error())
return influxErr(influxdb.EInternal, err)
}

func toInfluxError(code string, msg string) *influxdb.Error {
return &influxdb.Error{
func influxErr(code string, errArg interface{}, rest ...interface{}) *influxdb.Error {
err := &influxdb.Error{
Code: code,
Msg: msg,
}
for _, a := range append(rest, errArg) {
switch v := a.(type) {
case string:
err.Msg = v
case error:
err.Err = v
case nil:
case interface{ String() string }:
err.Msg = v.String()
}
}
return err
}

0 comments on commit a4e4be7

Please sign in to comment.