Disallow any port operations when codespace has pending operation

Since all of the port operations require the codespace to be running, we
need to disallow these operations when there's a pending op since we
can't start the codespace in this state.

Since the API already disallows this, this is basically cleaning up the
error messages that the user sees in this state

Old error message:

```
$ gh cs ports forward 80:80
? Choose codespace: redacted
Starting codespace ⣻error connecting to codespace: error starting codespace: HTTP 422: your codespace has an operation pending: updating to a sku with a different amount of storage; please wait until this operation is complete (https://api.github.com/user/codespaces/cwndrws-redacted/start)
```

New error message:

```
$ gh cs ports forward 80:80
? Choose codespace: redacted
codespace is disabled while it has a pending operation: Changing machine types...
exit status 1
```
This commit is contained in:
Charlie Andrews 2022-03-15 15:24:35 -04:00
parent da99a1b59b
commit 5ffe838dce

View file

@ -46,13 +46,9 @@ func newPortsCmd(app *App) *cobra.Command {
// ListPorts lists known ports in a codespace.
func (a *App) ListPorts(ctx context.Context, codespaceName string, exporter cmdutil.Exporter) (err error) {
codespace, err := getOrChooseCodespace(ctx, a.apiClient, codespaceName)
codespace, err := getCodespaceForPorts(ctx, a.apiClient, codespaceName)
if err != nil {
// TODO(josebalius): remove special handling of this error here and it other places
if err == errNoCodespaces {
return err
}
return fmt.Errorf("error choosing codespace: %w", err)
return err
}
devContainerCh := getDevContainer(ctx, a.apiClient, codespace)
@ -235,12 +231,9 @@ func (a *App) UpdatePortVisibility(ctx context.Context, codespaceName string, ar
return fmt.Errorf("error parsing port arguments: %w", err)
}
codespace, err := getOrChooseCodespace(ctx, a.apiClient, codespaceName)
codespace, err := getCodespaceForPorts(ctx, a.apiClient, codespaceName)
if err != nil {
if err == errNoCodespaces {
return err
}
return fmt.Errorf("error getting codespace: %w", err)
return err
}
session, err := codespaces.ConnectToLiveshare(ctx, a, noopLogger(), a.apiClient, codespace)
@ -311,12 +304,9 @@ func (a *App) ForwardPorts(ctx context.Context, codespaceName string, ports []st
return fmt.Errorf("get port pairs: %w", err)
}
codespace, err := getOrChooseCodespace(ctx, a.apiClient, codespaceName)
codespace, err := getCodespaceForPorts(ctx, a.apiClient, codespaceName)
if err != nil {
if err == errNoCodespaces {
return err
}
return fmt.Errorf("error getting codespace: %w", err)
return err
}
session, err := codespaces.ConnectToLiveshare(ctx, a, noopLogger(), a.apiClient, codespace)
@ -380,3 +370,23 @@ func normalizeJSON(j []byte) []byte {
// remove trailing commas
return bytes.ReplaceAll(j, []byte("},}"), []byte("}}"))
}
func getCodespaceForPorts(ctx context.Context, apiClient apiClient, codespaceName string) (*api.Codespace, error) {
codespace, err := getOrChooseCodespace(ctx, apiClient, codespaceName)
if err != nil {
// TODO(josebalius): remove special handling of this error here and it other places
if err == errNoCodespaces {
return nil, err
}
return nil, fmt.Errorf("error choosing codespace: %w", err)
}
if codespace.PendingOperation {
return nil, fmt.Errorf(
"codespace is disabled while it has a pending operation: %s",
codespace.PendingOperationDisabledReason,
)
}
return codespace, nil
}