Skip to content

Commit

Permalink
Merge branch 'main' into asb/APICLI-1219/reserved-ips
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewsomething committed Jun 15, 2022
2 parents 7a46dd9 + dfb2a1d commit a83cc58
Show file tree
Hide file tree
Showing 8 changed files with 137 additions and 24 deletions.
8 changes: 5 additions & 3 deletions commands/displayers/size.go
Expand Up @@ -32,13 +32,14 @@ func (si *Size) JSON(out io.Writer) error {

func (si *Size) Cols() []string {
return []string{
"Slug", "Memory", "VCPUs", "Disk", "PriceMonthly", "PriceHourly",
"Slug", "Description", "Memory", "VCPUs", "Disk", "PriceMonthly", "PriceHourly",
}
}

func (si *Size) ColMap() map[string]string {
return map[string]string{
"Slug": "Slug", "Memory": "Memory", "VCPUs": "VCPUs",
"Slug": "Slug", "Description": "Description",
"Memory": "Memory", "VCPUs": "VCPUs",
"Disk": "Disk", "PriceMonthly": "Price Monthly",
"PriceHourly": "Price Hourly",
}
Expand All @@ -49,7 +50,8 @@ func (si *Size) KV() []map[string]interface{} {

for _, s := range si.Sizes {
o := map[string]interface{}{
"Slug": s.Slug, "Memory": s.Memory, "VCPUs": s.Vcpus,
"Slug": s.Slug, "Description": s.Description,
"Memory": s.Memory, "VCPUs": s.Vcpus,
"Disk": s.Disk, "PriceMonthly": fmt.Sprintf("%0.2f", s.PriceMonthly),
"PriceHourly": s.PriceHourly,
}
Expand Down
5 changes: 3 additions & 2 deletions commands/functions.go
Expand Up @@ -127,10 +127,11 @@ func appendParams(c *CmdConfig, args []string) ([]string, error) {
}
for _, param := range params {
parts := strings.Split(param, ":")
if len(parts) != 2 {
if len(parts) < 2 {
return args, errors.New("values for --params must have KEY:VALUE form")
}
args = append(args, dashdashParam, parts[0], parts[1])
parts1 := strings.Join(parts[1:], ":")
args = append(args, dashdashParam, parts[0], parts1)
}
return args, nil
}
6 changes: 6 additions & 0 deletions commands/functions_test.go
Expand Up @@ -147,6 +147,12 @@ func TestFunctionsInvoke(t *testing.T) {
doctlFlags: map[string]interface{}{"param": []string{"name:world", "address:everywhere"}},
expectedNimArgs: []string{"hello", "--param", "name", "world", "--param", "address", "everywhere"},
},
{
name: "param flag colon-value",
doctlArgs: "hello",
doctlFlags: map[string]interface{}{"param": []string{"url:https://example.com"}},
expectedNimArgs: []string{"hello", "--param", "url", "https://example.com"},
},
}

for _, tt := range tests {
Expand Down
67 changes: 53 additions & 14 deletions commands/sandbox.go
Expand Up @@ -99,10 +99,10 @@ connect to the cloud component of the sandbox provided with your account). Othe
},
}

CmdBuilder(cmd, RunSandboxInstall, "install", "Installs the sandbox support",
cmdBuilderWithInit(cmd, RunSandboxInstall, "install", "Installs the sandbox support",
`This command installs additional software under `+"`"+`doctl`+"`"+` needed to make the other sandbox commands work.
The install operation is long-running, and a network connection is required.`,
Writer)
Writer, false)

CmdBuilder(cmd, RunSandboxUpgrade, "upgrade", "Upgrades sandbox support to match this version of doctl",
`This command upgrades the sandbox support software under `+"`"+`doctl`+"`"+` by installing over the existing version.
Expand Down Expand Up @@ -142,33 +142,43 @@ the entire packages are removed.`, Writer)
// RunSandboxInstall performs the network installation of the 'nim' adjunct to support sandbox development
func RunSandboxInstall(c *CmdConfig) error {
status := c.checkSandboxStatus(c)
if status == ErrSandboxNeedsUpgrade {
switch status {
case nil:
fmt.Fprintln(c.Out, "Sandbox support is already installed at an appropriate version. No action needed.")
return nil
case ErrSandboxNeedsUpgrade:
fmt.Fprintln(c.Out, "Sandbox support is already installed, but needs an upgrade for this version of `doctl`.")
fmt.Fprintln(c.Out, "Use `doctl sandbox upgrade` to upgrade the support.")
return nil
}
if status == nil {
fmt.Fprintln(c.Out, "Sandbox support is already installed at an appropriate version. No action needed.")
case ErrSandboxNotConnected:
fmt.Fprintln(c.Out, "Sandbox support is already installed at an appropriate version, but not connected to a function namespace. Use `doctl sandbox connect`.")
return nil
}

sandboxDir, _ := getSandboxDirectory()

return c.installSandbox(c, sandboxDir, false)
}

// RunSandboxUpgrade is a variant on RunSandboxInstall for installing over an existing version when
// the existing version is inadequate as detected by checkSandboxStatus()
func RunSandboxUpgrade(c *CmdConfig) error {
status := c.checkSandboxStatus(c)
if status == nil {
switch status {
case nil:
fmt.Fprintln(c.Out, "Sandbox support is already installed at an appropriate version. No action needed.")
// TODO should there be an option to upgrade beyond the minimum needed?
return nil
}
if status == ErrSandboxNotInstalled {
case ErrSandboxNotInstalled:
fmt.Fprintln(c.Out, "Sandbox support was never installed. Use `doctl sandbox install`.")
return nil
case ErrSandboxNotConnected:
fmt.Fprintln(c.Out, "Sandbox support is already installed at an appropriate version, but not connected to a function namespace. Use `doctl sandbox connect`.")
return nil
}

sandboxDir, _ := getSandboxDirectory()

return c.installSandbox(c, sandboxDir, true)
}

Expand Down Expand Up @@ -199,6 +209,19 @@ func RunSandboxConnect(c *CmdConfig) error {
if err != nil && err != ErrSandboxNotConnected {
return err
}

// Create the credentials dir if run as a snap as this might not have
// happened yet since the initial install happens on the build host.
_, isSnap := os.LookupEnv("SNAP")
if isSnap {
sandboxDir, _ := getSandboxDirectory()
credsDir := getCredentialDirectory(c, sandboxDir)
err = os.MkdirAll(credsDir, 0700)
if err != nil {
return nil
}
}

result, err := sandboxExecNoCheck(c, "auth/login", []string{"--auth", creds.Auth, "--apihost", creds.APIHost})
if err != nil {
return err
Expand Down Expand Up @@ -458,7 +481,7 @@ func InstallSandbox(c *CmdConfig, sandboxDir string, upgrading bool) error {
// Note: we don't let this be allocated in the system temporaries area because
// that might be on a separate file system, meaning that the final install step
// will require an additional copy rather than a simple rename.
tmp, err := ioutil.TempDir(defaultConfigHome(), "sbx-install")
tmp, err := ioutil.TempDir(configHome(), "sbx-install")
if err != nil {
return err
}
Expand Down Expand Up @@ -551,10 +574,16 @@ func InstallSandbox(c *CmdConfig, sandboxDir string, upgrading bool) error {
} else {
// Make new empty credentials directory
emptyCreds := filepath.Join(srcPath, credsDir)
err = os.Mkdir(emptyCreds, 0700)
err = os.MkdirAll(emptyCreds, 0700)
if err != nil {
return nil
}

// Create the sandbox directory if necessary.
err := os.MkdirAll(sandboxDir, 0755)
if err != nil {
return err
}
}
// Remove former sandboxDir before moving in the new one
err = os.RemoveAll(sandboxDir)
Expand All @@ -565,6 +594,7 @@ func InstallSandbox(c *CmdConfig, sandboxDir string, upgrading bool) error {
if err != nil {
return err
}

if nodeFileName != "" {
if goos == "win" {
srcPath = filepath.Join(tmp, nodeDir, nodeBin)
Expand Down Expand Up @@ -601,7 +631,7 @@ func preserveCreds(c *CmdConfig, stagingDir string, sandboxDir string) error {
// There was no creds directory. Check for legacy form and convert as part
// of preserving.
legacyCredPath := filepath.Join(sandboxDir, ".nimbella")
err = os.Mkdir(relocPath, 0700)
err = os.MkdirAll(relocPath, 0700)
if err != nil {
return err
}
Expand Down Expand Up @@ -674,12 +704,13 @@ func download(URL, targetFile string) error {
// (and the only one that customers are expected to use) is relative to the defaultConfigHome.
// For testing purposes, an override can be provided via an environment variable.
func getSandboxDirectory() (string, bool) {
sandboxDir := os.Getenv("sandboxDirectory")
if sandboxDir == "" {
sandboxDir, shouldOverride := os.LookupEnv("OVERRIDE_SANDBOX_DIR")
if !shouldOverride {
sandboxDir = filepath.Join(defaultConfigHome(), "sandbox")
}
_, err := os.Stat(sandboxDir)
exists := !os.IsNotExist(err)

return sandboxDir, exists
}

Expand All @@ -692,6 +723,14 @@ func getCredentialDirectory(c *CmdConfig, sandboxDir string) string {
hasher.Write([]byte(token))
sha := hasher.Sum(nil)
leafDir := hex.EncodeToString(sha[:4])

// When running as a snap, the credential are stored separately from the
// actual sandbox install. So we ignore any override of the sandboxDir here.
_, isSnap := os.LookupEnv("SNAP")
if isSnap {
sandboxDir = filepath.Join(configHome(), "sandbox")
}

return filepath.Join(sandboxDir, credsDir, leafDir)
}

Expand Down
50 changes: 50 additions & 0 deletions integration/auth_test.go
Expand Up @@ -97,6 +97,56 @@ var _ = suite("auth/init", func(t *testing.T, when spec.G, it spec.S) {
})
})

when("the --access-token flag is used", func() {
it("validates and saves the provided token non-interactively", func() {
tmpDir := t.TempDir()

testConfig := filepath.Join(tmpDir, "test-config.yml")

cmd := exec.Command(builtBinaryPath,
"-u", server.URL,
"--config", testConfig,
"auth",
"init",
"--access-token", "some-magic-token",
)

_, err := cmd.CombinedOutput()
expect.NoError(err)

fileBytes, err := ioutil.ReadFile(testConfig)
expect.NoError(err)

expect.Contains(string(fileBytes), "access-token: some-magic-token")
})

it("validates and overwrites an existing token non-interactively", func() {
var testConfigBytes = []byte(`access-token: first-token
context: default
`)

tmpDir := t.TempDir()
testConfig := filepath.Join(tmpDir, "test-config.yml")
expect.NoError(ioutil.WriteFile(testConfig, testConfigBytes, 0644))

cmd := exec.Command(builtBinaryPath,
"-u", server.URL,
"--config", testConfig,
"auth",
"init",
"--access-token", "some-magic-token",
)

_, err := cmd.CombinedOutput()
expect.NoError(err)

fileBytes, err := ioutil.ReadFile(testConfig)
expect.NoError(err)

expect.Contains(string(fileBytes), "access-token: some-magic-token")
})
})

when("no custom config is provided", func() {
it("saves the auth token to the default config path", func() {
cmd := exec.Command(builtBinaryPath,
Expand Down
12 changes: 7 additions & 5 deletions integration/size_list_test.go
Expand Up @@ -106,6 +106,7 @@ const (
{
"slug": "512mb",
"memory": 512,
"description": "Basic",
"vcpus": 1,
"disk": 20,
"transfer": 1,
Expand All @@ -119,6 +120,7 @@ const (
{
"slug": "s-1vcpu-1gb",
"memory": 1024,
"description": "Basic",
"vcpus": 1,
"disk": 25,
"transfer": 1,
Expand All @@ -137,9 +139,9 @@ const (
}
`
sizeListOutput = `
Slug Memory VCPUs Disk Price Monthly Price Hourly
512mb 512 1 20 5.00 0.007440
s-1vcpu-1gb 1024 1 25 5.00 0.007440
Slug Description Memory VCPUs Disk Price Monthly Price Hourly
512mb Basic 512 1 20 5.00 0.007440
s-1vcpu-1gb Basic 1024 1 25 5.00 0.007440
`
sizeListFormatOutput = `
Slug Price Monthly
Expand All @@ -148,7 +150,7 @@ s-1vcpu-1gb 5.00
`
sizeListNoHeaderOutput = `
512mb 512 1 20 5.00 0.007440
s-1vcpu-1gb 1024 1 25 5.00 0.007440
512mb Basic 512 1 20 5.00 0.007440
s-1vcpu-1gb Basic 1024 1 25 5.00 0.007440
`
)
4 changes: 4 additions & 0 deletions snap/local/doctl-launch
@@ -1,3 +1,7 @@
#!/bin/sh

# /snap/doctl/current/opt/sandbox
export OVERRIDE_SANDBOX_DIR="$SNAP/opt/sandbox"

real_home=$(getent passwd "$(id -u)" | cut -d ':' -f 6)
HOME=$real_home doctl.real "$@"
9 changes: 9 additions & 0 deletions snap/snapcraft.yaml
Expand Up @@ -29,6 +29,11 @@ parts:
after: [launcher]
source: .
plugin: go
build-environment:
# Results in installation to /snap/doctl/current/opt/sandbox
- OVERRIDE_SANDBOX_DIR: "$SNAPCRAFT_PART_INSTALL/opt/sandbox"
# Override to prevent 'invalid cross-device link' calling doctl
- XDG_CONFIG_HOME: "$SNAPCRAFT_PART_INSTALL/tmp/.config"
override-pull: |
git clone https://github.com/digitalocean/doctl.git .
override-build: |
Expand All @@ -49,6 +54,10 @@ parts:
chmod +x doctl
mkdir -p $SNAPCRAFT_PART_INSTALL/bin
mv doctl $SNAPCRAFT_PART_INSTALL/bin/
# Install the sandbox
$SNAPCRAFT_PART_INSTALL/bin/doctl sandbox install
rm -r $XDG_CONFIG_HOME/doctl
organize:
bin/doctl: bin/doctl.real

Expand Down

0 comments on commit a83cc58

Please sign in to comment.