Merge pull request #5410 from cli/codespaces-location-optional

Make location an optional flag when creating codespaces
This commit is contained in:
Jake Shorty 2022-04-07 10:58:39 -06:00 committed by GitHub
commit 6783509d3b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 10 additions and 74 deletions

View file

@ -433,40 +433,6 @@ func (a *API) StopCodespace(ctx context.Context, codespaceName string) error {
return nil
}
type getCodespaceRegionLocationResponse struct {
Current string `json:"current"`
}
// GetCodespaceRegionLocation returns the closest codespace location for the user.
func (a *API) GetCodespaceRegionLocation(ctx context.Context) (string, error) {
req, err := http.NewRequest(http.MethodGet, a.vscsAPI+"/api/v1/locations", nil)
if err != nil {
return "", fmt.Errorf("error creating request: %w", err)
}
resp, err := a.do(ctx, req, req.URL.String())
if err != nil {
return "", fmt.Errorf("error making request: %w", err)
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
return "", api.HandleHTTPError(resp)
}
b, err := ioutil.ReadAll(resp.Body)
if err != nil {
return "", fmt.Errorf("error reading response body: %w", err)
}
var response getCodespaceRegionLocationResponse
if err := json.Unmarshal(b, &response); err != nil {
return "", fmt.Errorf("error unmarshaling response: %w", err)
}
return response.Current, nil
}
type Machine struct {
Name string `json:"name"`
DisplayName string `json:"display_name"`

View file

@ -71,7 +71,6 @@ type apiClient interface {
EditCodespace(ctx context.Context, codespaceName string, params *api.EditCodespaceParams) (*api.Codespace, error)
GetRepository(ctx context.Context, nwo string) (*api.Repository, error)
AuthorizedKeys(ctx context.Context, user string) ([]byte, error)
GetCodespaceRegionLocation(ctx context.Context) (string, error)
GetCodespacesMachines(ctx context.Context, repoID int, branch, location string) ([]*api.Machine, error)
GetCodespaceRepositoryContents(ctx context.Context, codespace *api.Codespace, path string) ([]byte, error)
GetCodespaceRepoSuggestions(ctx context.Context, partialSearch string, params api.RepoSearchParameters) ([]string, error)

View file

@ -18,6 +18,7 @@ import (
type createOptions struct {
repo string
branch string
location string
machine string
showStatus bool
permissionsOptOut bool
@ -38,6 +39,7 @@ func newCreateCmd(app *App) *cobra.Command {
createCmd.Flags().StringVarP(&opts.repo, "repo", "r", "", "repository name with owner: user/repo")
createCmd.Flags().StringVarP(&opts.branch, "branch", "b", "", "repository branch")
createCmd.Flags().StringVarP(&opts.location, "location", "l", "", "location: {EastUs|SouthEastAsia|WestEurope|WestUs2} (determined automatically if not provided)")
createCmd.Flags().StringVarP(&opts.machine, "machine", "m", "", "hardware specifications for the VM")
createCmd.Flags().BoolVarP(&opts.permissionsOptOut, "default-permissions", "", false, "do not prompt to accept additional permissions requested by the codespace")
createCmd.Flags().BoolVarP(&opts.showStatus, "status", "s", false, "show status of post-create command and dotfiles")
@ -53,14 +55,14 @@ func (a *App) Create(ctx context.Context, opts createOptions) error {
vscsTarget := os.Getenv("VSCS_TARGET")
vscsTargetUrl := os.Getenv("VSCS_TARGET_URL")
locationCh := getLocation(ctx, vscsLocation, a.apiClient)
userInputs := struct {
Repository string
Branch string
Location string
}{
Repository: opts.repo,
Branch: opts.branch,
Location: opts.location,
}
if userInputs.Repository == "" {
@ -93,6 +95,10 @@ func (a *App) Create(ctx context.Context, opts createOptions) error {
}
}
if userInputs.Location == "" && vscsLocation != "" {
userInputs.Location = vscsLocation
}
a.StartProgressIndicatorWithLabel("Fetching repository")
repository, err := a.apiClient.GetRepository(ctx, userInputs.Repository)
a.StopProgressIndicator()
@ -105,12 +111,7 @@ func (a *App) Create(ctx context.Context, opts createOptions) error {
branch = repository.DefaultBranch
}
locationResult := <-locationCh
if locationResult.Err != nil {
return fmt.Errorf("error getting codespace region location: %w", locationResult.Err)
}
machine, err := getMachineName(ctx, a.apiClient, repository.ID, opts.machine, branch, locationResult.Location)
machine, err := getMachineName(ctx, a.apiClient, repository.ID, opts.machine, branch, userInputs.Location)
if err != nil {
return fmt.Errorf("error getting machine type: %w", err)
}
@ -122,7 +123,7 @@ func (a *App) Create(ctx context.Context, opts createOptions) error {
RepositoryID: repository.ID,
Branch: branch,
Machine: machine,
Location: locationResult.Location,
Location: userInputs.Location,
VSCSTarget: vscsTarget,
VSCSTargetURL: vscsTargetUrl,
IdleTimeoutMinutes: int(opts.idleTimeout.Minutes()),
@ -293,30 +294,6 @@ func (a *App) showStatus(ctx context.Context, codespace *api.Codespace) error {
return nil
}
type locationResult struct {
Location string
Err error
}
// getLocation fetches the closest Codespace datacenter
// region/location to the user, unless the 'vscsLocationOverride' override is set
func getLocation(ctx context.Context, vscsLocationOverride string, apiClient apiClient) <-chan locationResult {
ch := make(chan locationResult, 1)
// Developer override is set, return the override
if vscsLocationOverride != "" {
ch <- locationResult{vscsLocationOverride, nil}
return ch
}
// Dynamically fetch the region location
go func() {
location, err := apiClient.GetCodespaceRegionLocation(ctx)
ch <- locationResult{location, err}
}()
return ch
}
// getMachineName prompts the user to select the machine type, or validates the machine if non-empty.
func getMachineName(ctx context.Context, apiClient apiClient, repoID int, machine, branch, location string) (string, error) {
machines, err := apiClient.GetCodespacesMachines(ctx, repoID, branch, location)

View file

@ -28,9 +28,6 @@ func TestApp_Create(t *testing.T) {
name: "create codespace with default branch and 30m idle timeout",
fields: fields{
apiClient: &apiClientMock{
GetCodespaceRegionLocationFunc: func(ctx context.Context) (string, error) {
return "EUROPE", nil
},
GetRepositoryFunc: func(ctx context.Context, nwo string) (*api.Repository, error) {
return &api.Repository{
ID: 1234,
@ -175,9 +172,6 @@ func TestApp_Create(t *testing.T) {
name: "create codespace that requires accepting additional permissions",
fields: fields{
apiClient: &apiClientMock{
GetCodespaceRegionLocationFunc: func(ctx context.Context) (string, error) {
return "EUROPE", nil
},
GetRepositoryFunc: func(ctx context.Context, nwo string) (*api.Repository, error) {
return &api.Repository{
ID: 1234,