Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 38 additions & 8 deletions pkg/commands/secretstoreentry/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"encoding/hex"
"fmt"
"io"
"net/http"
"os"

"github.com/fastly/go-fastly/v8/fastly"
Expand Down Expand Up @@ -57,8 +58,20 @@ func NewCreateCommand(parent cmd.Registerer, g *global.Data, m manifest.Data) *C
c.RegisterFlag(cmd.StoreIDFlag(&c.Input.ID)) // --store-id

// Optional.
c.RegisterFlag(secretFileFlag(&c.secretFile)) // --file
c.RegisterFlagBool(c.JSONFlag()) // --json
c.RegisterFlag(secretFileFlag(&c.secretFile)) // --file
c.RegisterFlagBool(c.JSONFlag()) // --json
c.RegisterFlagBool(cmd.BoolFlagOpts{
Name: "recreate",
Description: "Recreate secret by name (errors if secret doesn't already exist)",
Dst: &c.recreate,
Required: false,
})
c.RegisterFlagBool(cmd.BoolFlagOpts{
Name: "recreate-allow",
Description: "Create or recreate secret by name",
Dst: &c.recreateAllow,
Required: false,
})
c.RegisterFlagBool(secretStdinFlag(&c.secretSTDIN)) // --stdin

return &c
Expand All @@ -69,10 +82,12 @@ type CreateCommand struct {
cmd.Base
cmd.JSONOutput

Input fastly.CreateSecretInput
manifest manifest.Data
secretFile string
secretSTDIN bool
Input fastly.CreateSecretInput
manifest manifest.Data
recreate bool
recreateAllow bool
secretFile string
secretSTDIN bool
}

var errMultipleSecretValue = fsterr.RemediationError{
Expand All @@ -94,6 +109,18 @@ func (c *CreateCommand) Exec(in io.Reader, out io.Writer) error {
return errMultipleSecretValue
}

switch {
case c.recreate && c.recreateAllow:
return fsterr.RemediationError{
Inner: fmt.Errorf("invalid flag combination, --recreate and --recreate-allow"),
Remediation: "Use either --recreate or --recreate-allow, not both.",
}
case c.recreate:
c.Input.Method = http.MethodPatch
case c.recreateAllow:
c.Input.Method = http.MethodPut
}

// Read secret's value: either from STDIN, a file, or prompt.
switch {
case c.secretSTDIN:
Expand Down Expand Up @@ -165,12 +192,15 @@ func (c *CreateCommand) Exec(in io.Reader, out io.Writer) error {
return err
}

// TODO: Use this approach across the code base.
if ok, err := c.WriteJSON(out, o); ok {
return err
}

text.Success(out, "Created secret '%s' in Secret Store '%s' (digest: %s)", o.Name, c.Input.ID, hex.EncodeToString(o.Digest))
action := "Created"
if o.Recreated {
action = "Recreated"
}
text.Success(out, "%s secret '%s' in Secret Store '%s' (digest: %s)", action, o.Name, c.Input.ID, hex.EncodeToString(o.Digest))

return nil
}
61 changes: 61 additions & 0 deletions pkg/commands/secretstoreentry/secretstoreentry_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"encoding/hex"
"errors"
"fmt"
"net/http"
"os"
"path"
"runtime"
Expand Down Expand Up @@ -94,6 +95,10 @@ func TestCreateSecretCommand(t *testing.T) {
args: fmt.Sprintf("create --store-id %s --name %s --stdin", storeID, secretName),
wantError: "unable to read from STDIN",
},
{
args: fmt.Sprintf("create --store-id %s --name %s --stdin --recreate --recreate-allow", storeID, secretName),
wantError: "invalid flag combination, --recreate and --recreate-allow",
},
// Read from STDIN.
{
args: fmt.Sprintf("create --store-id %s --name %s --stdin", storeID, secretName),
Expand Down Expand Up @@ -160,6 +165,62 @@ func TestCreateSecretCommand(t *testing.T) {
Digest: []byte(secretDigest),
}),
},
// CreateOrRecreate
{
args: fmt.Sprintf("create --store-id %s --name %s --file %s --json --recreate-allow", storeID, secretName, secretFile),
api: mock.API{
CreateClientKeyFn: mockCreateClientKey,
GetSigningKeyFn: mockGetSigningKey,
CreateSecretFn: func(i *fastly.CreateSecretInput) (*fastly.Secret, error) {
if got, want := i.Method, http.MethodPut; got != want {
return nil, fmt.Errorf("got method %q, want %q", got, want)
}
if got, err := decrypt(i.Secret); err != nil {
return nil, err
} else if got != secretValue {
return nil, fmt.Errorf("invalid secret: %s", got)
}
return &fastly.Secret{
Name: i.Name,
Digest: []byte(secretDigest),
}, nil
},
},
wantAPIInvoked: true,
wantOutput: fstfmt.EncodeJSON(&fastly.Secret{
Name: secretName,
Digest: []byte(secretDigest),
}),
},
// Recreate
{
args: fmt.Sprintf("create --store-id %s --name %s --file %s --json --recreate", storeID, secretName, secretFile),
api: mock.API{
CreateClientKeyFn: mockCreateClientKey,
GetSigningKeyFn: mockGetSigningKey,
CreateSecretFn: func(i *fastly.CreateSecretInput) (*fastly.Secret, error) {
if got, want := i.Method, http.MethodPatch; got != want {
return nil, fmt.Errorf("got method %q, want %q", got, want)
}
if got, err := decrypt(i.Secret); err != nil {
return nil, err
} else if got != secretValue {
return nil, fmt.Errorf("invalid secret: %s", got)
}
return &fastly.Secret{
Name: i.Name,
Digest: []byte(secretDigest),
Recreated: true,
}, nil
},
},
wantAPIInvoked: true,
wantOutput: fstfmt.EncodeJSON(&fastly.Secret{
Name: secretName,
Digest: []byte(secretDigest),
Recreated: true,
}),
},
}

for _, testcase := range scenarios {
Expand Down