From 9b00e2e97bd9ff079118949fa95bdadc03f553b1 Mon Sep 17 00:00:00 2001 From: Brandon Croft Date: Mon, 20 Jun 2022 16:52:06 -0600 Subject: [PATCH 1/9] refactor: encapsulate client request --- admin_organization.go | 24 +-- admin_run.go | 8 +- admin_setting_cost_estimation.go | 8 +- admin_setting_customization.go | 8 +- admin_setting_general.go | 8 +- admin_setting_saml.go | 12 +- admin_setting_smtp.go | 8 +- admin_setting_twilio.go | 12 +- admin_terraform_version.go | 20 +-- admin_user.go | 28 ++-- admin_workspace.go | 12 +- agent_pool.go | 20 +-- agent_token.go | 16 +- apply.go | 4 +- comment.go | 12 +- configuration_version.go | 24 +-- cost_estimate.go | 8 +- docs/CONTRIBUTING.md | 26 ++-- gpg_key.go | 16 +- helper_test.go | 8 +- ip_ranges.go | 4 +- notification_configuration.go | 24 +-- oauth_client.go | 20 +-- oauth_token.go | 16 +- organization.go | 32 ++-- organization_membership.go | 16 +- organization_tags.go | 12 +- organization_token.go | 12 +- plan.go | 8 +- plan_export.go | 16 +- policy.go | 28 ++-- policy_check.go | 16 +- policy_set.go | 36 ++--- policy_set_parameter.go | 20 +-- policy_set_version.go | 12 +- registry_module.go | 36 ++--- registry_provider.go | 16 +- registry_provider_platform.go | 22 +-- registry_provider_version.go | 20 +-- request.go | 104 +++++++++++++ run.go | 28 ++-- run_task.go | 20 +-- run_trigger.go | 16 +- ssh_key.go | 20 +-- state_version.go | 24 +-- state_version_output.go | 8 +- task_result.go | 4 +- task_stages.go | 8 +- team.go | 20 +-- team_access.go | 20 +-- team_member.go | 26 ++-- team_token.go | 12 +- testing.go | 2 +- tfe.go | 241 +++++++++---------------------- tfe_integration_test.go | 8 +- tfe_test.go | 4 +- user.go | 8 +- user_token.go | 16 +- variable.go | 20 +-- variable_set.go | 32 ++-- variable_set_variable.go | 20 +-- workspace.go | 92 ++++++------ workspace_run_task.go | 20 +-- 63 files changed, 712 insertions(+), 709 deletions(-) create mode 100644 request.go diff --git a/admin_organization.go b/admin_organization.go index 600e68315..abb03da88 100644 --- a/admin_organization.go +++ b/admin_organization.go @@ -107,13 +107,13 @@ func (s *adminOrganizations) List(ctx context.Context, options *AdminOrganizatio return nil, err } u := "admin/organizations" - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } orgl := &AdminOrganizationList{} - err = s.client.do(ctx, req, orgl) + err = req.Do(ctx, orgl) if err != nil { return nil, err } @@ -129,13 +129,13 @@ func (s *adminOrganizations) ListModuleConsumers(ctx context.Context, organizati u := fmt.Sprintf("admin/organizations/%s/relationships/module-consumers", url.QueryEscape(organization)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } orgl := &AdminOrganizationList{} - err = s.client.do(ctx, req, orgl) + err = req.Do(ctx, orgl) if err != nil { return nil, err } @@ -150,13 +150,13 @@ func (s *adminOrganizations) Read(ctx context.Context, organization string) (*Ad } u := fmt.Sprintf("admin/organizations/%s", url.QueryEscape(organization)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } org := &AdminOrganization{} - err = s.client.do(ctx, req, org) + err = req.Do(ctx, org) if err != nil { return nil, err } @@ -171,13 +171,13 @@ func (s *adminOrganizations) Update(ctx context.Context, organization string, op } u := fmt.Sprintf("admin/organizations/%s", url.QueryEscape(organization)) - req, err := s.client.newRequest("PATCH", u, &options) + req, err := s.client.NewRequest("PATCH", u, &options) if err != nil { return nil, err } org := &AdminOrganization{} - err = s.client.do(ctx, req, org) + err = req.Do(ctx, org) if err != nil { return nil, err } @@ -201,12 +201,12 @@ func (s *adminOrganizations) UpdateModuleConsumers(ctx context.Context, organiza organizations = append(organizations, &AdminOrganizationID{ID: id}) } - req, err := s.client.newRequest("PATCH", u, organizations) + req, err := s.client.NewRequest("PATCH", u, organizations) if err != nil { return err } - err = s.client.do(ctx, req, nil) + err = req.Do(ctx, nil) if err != nil { return err } @@ -221,12 +221,12 @@ func (s *adminOrganizations) Delete(ctx context.Context, organization string) er } u := fmt.Sprintf("admin/organizations/%s", url.QueryEscape(organization)) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (o *AdminOrganizationListOptions) valid() error { diff --git a/admin_run.go b/admin_run.go index b0467aa67..6d4a65709 100644 --- a/admin_run.go +++ b/admin_run.go @@ -78,13 +78,13 @@ func (s *adminRuns) List(ctx context.Context, options *AdminRunsListOptions) (*A } u := "admin/runs" - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } rl := &AdminRunsList{} - err = s.client.do(ctx, req, rl) + err = req.Do(ctx, rl) if err != nil { return nil, err } @@ -107,12 +107,12 @@ func (s *adminRuns) ForceCancel(ctx context.Context, runID string, options Admin } u := fmt.Sprintf("admin/runs/%s/actions/force-cancel", url.QueryEscape(runID)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (o *AdminRunsListOptions) valid() error { diff --git a/admin_setting_cost_estimation.go b/admin_setting_cost_estimation.go index e291a25f0..a9bd2a7fe 100644 --- a/admin_setting_cost_estimation.go +++ b/admin_setting_cost_estimation.go @@ -54,13 +54,13 @@ type AdminCostEstimationSettingOptions struct { // Read returns the cost estimation settings. func (a *adminCostEstimationSettings) Read(ctx context.Context) (*AdminCostEstimationSetting, error) { - req, err := a.client.newRequest("GET", "admin/cost-estimation-settings", nil) + req, err := a.client.NewRequest("GET", "admin/cost-estimation-settings", nil) if err != nil { return nil, err } ace := &AdminCostEstimationSetting{} - err = a.client.do(ctx, req, ace) + err = req.Do(ctx, ace) if err != nil { return nil, err } @@ -70,13 +70,13 @@ func (a *adminCostEstimationSettings) Read(ctx context.Context) (*AdminCostEstim // Update updates the cost-estimation settings. func (a *adminCostEstimationSettings) Update(ctx context.Context, options AdminCostEstimationSettingOptions) (*AdminCostEstimationSetting, error) { - req, err := a.client.newRequest("PATCH", "admin/cost-estimation-settings", &options) + req, err := a.client.NewRequest("PATCH", "admin/cost-estimation-settings", &options) if err != nil { return nil, err } ace := &AdminCostEstimationSetting{} - err = a.client.do(ctx, req, ace) + err = req.Do(ctx, ace) if err != nil { return nil, err } diff --git a/admin_setting_customization.go b/admin_setting_customization.go index d429a5e99..5c869c9f3 100644 --- a/admin_setting_customization.go +++ b/admin_setting_customization.go @@ -33,13 +33,13 @@ type AdminCustomizationSetting struct { // Read returns the Customization settings. func (a *adminCustomizationSettings) Read(ctx context.Context) (*AdminCustomizationSetting, error) { - req, err := a.client.newRequest("GET", "admin/customization-settings", nil) + req, err := a.client.NewRequest("GET", "admin/customization-settings", nil) if err != nil { return nil, err } cs := &AdminCustomizationSetting{} - err = a.client.do(ctx, req, cs) + err = req.Do(ctx, cs) if err != nil { return nil, err } @@ -60,13 +60,13 @@ type AdminCustomizationSettingsUpdateOptions struct { // Update updates the customization settings. func (a *adminCustomizationSettings) Update(ctx context.Context, options AdminCustomizationSettingsUpdateOptions) (*AdminCustomizationSetting, error) { - req, err := a.client.newRequest("PATCH", "admin/customization-settings", &options) + req, err := a.client.NewRequest("PATCH", "admin/customization-settings", &options) if err != nil { return nil, err } cs := &AdminCustomizationSetting{} - err = a.client.do(ctx, req, cs) + err = req.Do(ctx, cs) if err != nil { return nil, err } diff --git a/admin_setting_general.go b/admin_setting_general.go index 31124fd6b..2dc4827f8 100644 --- a/admin_setting_general.go +++ b/admin_setting_general.go @@ -54,13 +54,13 @@ type AdminGeneralSettingsUpdateOptions struct { // Read returns the general settings. func (a *adminGeneralSettings) Read(ctx context.Context) (*AdminGeneralSetting, error) { - req, err := a.client.newRequest("GET", "admin/general-settings", nil) + req, err := a.client.NewRequest("GET", "admin/general-settings", nil) if err != nil { return nil, err } ags := &AdminGeneralSetting{} - err = a.client.do(ctx, req, ags) + err = req.Do(ctx, ags) if err != nil { return nil, err } @@ -70,13 +70,13 @@ func (a *adminGeneralSettings) Read(ctx context.Context) (*AdminGeneralSetting, // Update updates the general settings. func (a *adminGeneralSettings) Update(ctx context.Context, options AdminGeneralSettingsUpdateOptions) (*AdminGeneralSetting, error) { - req, err := a.client.newRequest("PATCH", "admin/general-settings", &options) + req, err := a.client.NewRequest("PATCH", "admin/general-settings", &options) if err != nil { return nil, err } ags := &AdminGeneralSetting{} - err = a.client.do(ctx, req, ags) + err = req.Do(ctx, ags) if err != nil { return nil, err } diff --git a/admin_setting_saml.go b/admin_setting_saml.go index 8ea59aed1..2aa857f92 100644 --- a/admin_setting_saml.go +++ b/admin_setting_saml.go @@ -50,13 +50,13 @@ type AdminSAMLSetting struct { // Read returns the SAML settings. func (a *adminSAMLSettings) Read(ctx context.Context) (*AdminSAMLSetting, error) { - req, err := a.client.newRequest("GET", "admin/saml-settings", nil) + req, err := a.client.NewRequest("GET", "admin/saml-settings", nil) if err != nil { return nil, err } saml := &AdminSAMLSetting{} - err = a.client.do(ctx, req, saml) + err = req.Do(ctx, saml) if err != nil { return nil, err } @@ -82,13 +82,13 @@ type AdminSAMLSettingsUpdateOptions struct { // Update updates the SAML settings. func (a *adminSAMLSettings) Update(ctx context.Context, options AdminSAMLSettingsUpdateOptions) (*AdminSAMLSetting, error) { - req, err := a.client.newRequest("PATCH", "admin/saml-settings", &options) + req, err := a.client.NewRequest("PATCH", "admin/saml-settings", &options) if err != nil { return nil, err } saml := &AdminSAMLSetting{} - err = a.client.do(ctx, req, saml) + err = req.Do(ctx, saml) if err != nil { return nil, err } @@ -99,13 +99,13 @@ func (a *adminSAMLSettings) Update(ctx context.Context, options AdminSAMLSetting // RevokeIdpCert revokes the older IdP certificate when the new IdP // certificate is known to be functioning correctly. func (a *adminSAMLSettings) RevokeIdpCert(ctx context.Context) (*AdminSAMLSetting, error) { - req, err := a.client.newRequest("POST", "admin/saml-settings/actions/revoke-old-certificate", nil) + req, err := a.client.NewRequest("POST", "admin/saml-settings/actions/revoke-old-certificate", nil) if err != nil { return nil, err } saml := &AdminSAMLSetting{} - err = a.client.do(ctx, req, saml) + err = req.Do(ctx, saml) if err != nil { return nil, err } diff --git a/admin_setting_smtp.go b/admin_setting_smtp.go index 4cb6046ed..8f04c5a6d 100644 --- a/admin_setting_smtp.go +++ b/admin_setting_smtp.go @@ -43,13 +43,13 @@ type AdminSMTPSetting struct { // Read returns the SMTP settings. func (a *adminSMTPSettings) Read(ctx context.Context) (*AdminSMTPSetting, error) { - req, err := a.client.newRequest("GET", "admin/smtp-settings", nil) + req, err := a.client.NewRequest("GET", "admin/smtp-settings", nil) if err != nil { return nil, err } smtp := &AdminSMTPSetting{} - err = a.client.do(ctx, req, smtp) + err = req.Do(ctx, smtp) if err != nil { return nil, err } @@ -77,13 +77,13 @@ func (a *adminSMTPSettings) Update(ctx context.Context, options AdminSMTPSetting return nil, err } - req, err := a.client.newRequest("PATCH", "admin/smtp-settings", &options) + req, err := a.client.NewRequest("PATCH", "admin/smtp-settings", &options) if err != nil { return nil, err } smtp := &AdminSMTPSetting{} - err = a.client.do(ctx, req, smtp) + err = req.Do(ctx, smtp) if err != nil { return nil, err } diff --git a/admin_setting_twilio.go b/admin_setting_twilio.go index 6913f2048..5593bd0ff 100644 --- a/admin_setting_twilio.go +++ b/admin_setting_twilio.go @@ -34,13 +34,13 @@ type AdminTwilioSetting struct { // Read returns the Twilio settings. func (a *adminTwilioSettings) Read(ctx context.Context) (*AdminTwilioSetting, error) { - req, err := a.client.newRequest("GET", "admin/twilio-settings", nil) + req, err := a.client.NewRequest("GET", "admin/twilio-settings", nil) if err != nil { return nil, err } twilio := &AdminTwilioSetting{} - err = a.client.do(ctx, req, twilio) + err = req.Do(ctx, twilio) if err != nil { return nil, err } @@ -66,13 +66,13 @@ type AdminTwilioSettingsVerifyOptions struct { // Update updates the Twilio settings. func (a *adminTwilioSettings) Update(ctx context.Context, options AdminTwilioSettingsUpdateOptions) (*AdminTwilioSetting, error) { - req, err := a.client.newRequest("PATCH", "admin/twilio-settings", &options) + req, err := a.client.NewRequest("PATCH", "admin/twilio-settings", &options) if err != nil { return nil, err } twilio := &AdminTwilioSetting{} - err = a.client.do(ctx, req, twilio) + err = req.Do(ctx, twilio) if err != nil { return nil, err } @@ -85,12 +85,12 @@ func (a *adminTwilioSettings) Verify(ctx context.Context, options AdminTwilioSet if err := options.valid(); err != nil { return err } - req, err := a.client.newRequest("PATCH", "admin/twilio-settings/verify", &options) + req, err := a.client.NewRequest("PATCH", "admin/twilio-settings/verify", &options) if err != nil { return err } - return a.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (o AdminTwilioSettingsVerifyOptions) valid() error { diff --git a/admin_terraform_version.go b/admin_terraform_version.go index 10eb9e12e..b2c92de9e 100644 --- a/admin_terraform_version.go +++ b/admin_terraform_version.go @@ -100,13 +100,13 @@ type AdminTerraformVersionsList struct { // List all the terraform versions. func (a *adminTerraformVersions) List(ctx context.Context, options *AdminTerraformVersionsListOptions) (*AdminTerraformVersionsList, error) { - req, err := a.client.newRequest("GET", "admin/terraform-versions", options) + req, err := a.client.NewRequest("GET", "admin/terraform-versions", options) if err != nil { return nil, err } tvl := &AdminTerraformVersionsList{} - err = a.client.do(ctx, req, tvl) + err = req.Do(ctx, tvl) if err != nil { return nil, err } @@ -121,13 +121,13 @@ func (a *adminTerraformVersions) Read(ctx context.Context, id string) (*AdminTer } u := fmt.Sprintf("admin/terraform-versions/%s", url.QueryEscape(id)) - req, err := a.client.newRequest("GET", u, nil) + req, err := a.client.NewRequest("GET", u, nil) if err != nil { return nil, err } tfv := &AdminTerraformVersion{} - err = a.client.do(ctx, req, tfv) + err = req.Do(ctx, tfv) if err != nil { return nil, err } @@ -140,13 +140,13 @@ func (a *adminTerraformVersions) Create(ctx context.Context, options AdminTerraf if err := options.valid(); err != nil { return nil, err } - req, err := a.client.newRequest("POST", "admin/terraform-versions", &options) + req, err := a.client.NewRequest("POST", "admin/terraform-versions", &options) if err != nil { return nil, err } tfv := &AdminTerraformVersion{} - err = a.client.do(ctx, req, tfv) + err = req.Do(ctx, tfv) if err != nil { return nil, err } @@ -161,13 +161,13 @@ func (a *adminTerraformVersions) Update(ctx context.Context, id string, options } u := fmt.Sprintf("admin/terraform-versions/%s", url.QueryEscape(id)) - req, err := a.client.newRequest("PATCH", u, &options) + req, err := a.client.NewRequest("PATCH", u, &options) if err != nil { return nil, err } tfv := &AdminTerraformVersion{} - err = a.client.do(ctx, req, tfv) + err = req.Do(ctx, tfv) if err != nil { return nil, err } @@ -182,12 +182,12 @@ func (a *adminTerraformVersions) Delete(ctx context.Context, id string) error { } u := fmt.Sprintf("admin/terraform-versions/%s", url.QueryEscape(id)) - req, err := a.client.newRequest("DELETE", u, nil) + req, err := a.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return a.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (o AdminTerraformVersionCreateOptions) valid() error { diff --git a/admin_user.go b/admin_user.go index 80fc6ab71..c955bf56d 100644 --- a/admin_user.go +++ b/admin_user.go @@ -96,13 +96,13 @@ func (a *adminUsers) List(ctx context.Context, options *AdminUserListOptions) (* } u := "admin/users" - req, err := a.client.newRequest("GET", u, options) + req, err := a.client.NewRequest("GET", u, options) if err != nil { return nil, err } aul := &AdminUserList{} - err = a.client.do(ctx, req, aul) + err = req.Do(ctx, aul) if err != nil { return nil, err } @@ -117,12 +117,12 @@ func (a *adminUsers) Delete(ctx context.Context, userID string) error { } u := fmt.Sprintf("admin/users/%s", url.QueryEscape(userID)) - req, err := a.client.newRequest("DELETE", u, nil) + req, err := a.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return a.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // Suspend a user by its ID. @@ -132,13 +132,13 @@ func (a *adminUsers) Suspend(ctx context.Context, userID string) (*AdminUser, er } u := fmt.Sprintf("admin/users/%s/actions/suspend", url.QueryEscape(userID)) - req, err := a.client.newRequest("POST", u, nil) + req, err := a.client.NewRequest("POST", u, nil) if err != nil { return nil, err } au := &AdminUser{} - err = a.client.do(ctx, req, au) + err = req.Do(ctx, au) if err != nil { return nil, err } @@ -153,13 +153,13 @@ func (a *adminUsers) Unsuspend(ctx context.Context, userID string) (*AdminUser, } u := fmt.Sprintf("admin/users/%s/actions/unsuspend", url.QueryEscape(userID)) - req, err := a.client.newRequest("POST", u, nil) + req, err := a.client.NewRequest("POST", u, nil) if err != nil { return nil, err } au := &AdminUser{} - err = a.client.do(ctx, req, au) + err = req.Do(ctx, au) if err != nil { return nil, err } @@ -174,13 +174,13 @@ func (a *adminUsers) GrantAdmin(ctx context.Context, userID string) (*AdminUser, } u := fmt.Sprintf("admin/users/%s/actions/grant_admin", url.QueryEscape(userID)) - req, err := a.client.newRequest("POST", u, nil) + req, err := a.client.NewRequest("POST", u, nil) if err != nil { return nil, err } au := &AdminUser{} - err = a.client.do(ctx, req, au) + err = req.Do(ctx, au) if err != nil { return nil, err } @@ -195,13 +195,13 @@ func (a *adminUsers) RevokeAdmin(ctx context.Context, userID string) (*AdminUser } u := fmt.Sprintf("admin/users/%s/actions/revoke_admin", url.QueryEscape(userID)) - req, err := a.client.newRequest("POST", u, nil) + req, err := a.client.NewRequest("POST", u, nil) if err != nil { return nil, err } au := &AdminUser{} - err = a.client.do(ctx, req, au) + err = req.Do(ctx, au) if err != nil { return nil, err } @@ -217,13 +217,13 @@ func (a *adminUsers) Disable2FA(ctx context.Context, userID string) (*AdminUser, } u := fmt.Sprintf("admin/users/%s/actions/disable_two_factor", url.QueryEscape(userID)) - req, err := a.client.newRequest("POST", u, nil) + req, err := a.client.NewRequest("POST", u, nil) if err != nil { return nil, err } au := &AdminUser{} - err = a.client.do(ctx, req, au) + err = req.Do(ctx, au) if err != nil { return nil, err } diff --git a/admin_workspace.go b/admin_workspace.go index 1fcfc90d1..b5e9b98e1 100644 --- a/admin_workspace.go +++ b/admin_workspace.go @@ -81,13 +81,13 @@ func (s *adminWorkspaces) List(ctx context.Context, options *AdminWorkspaceListO } u := "admin/workspaces" - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } awl := &AdminWorkspaceList{} - err = s.client.do(ctx, req, awl) + err = req.Do(ctx, awl) if err != nil { return nil, err } @@ -102,13 +102,13 @@ func (s *adminWorkspaces) Read(ctx context.Context, workspaceID string) (*AdminW } u := fmt.Sprintf("admin/workspaces/%s", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } aw := &AdminWorkspace{} - err = s.client.do(ctx, req, aw) + err = req.Do(ctx, aw) if err != nil { return nil, err } @@ -123,12 +123,12 @@ func (s *adminWorkspaces) Delete(ctx context.Context, workspaceID string) error } u := fmt.Sprintf("admin/workspaces/%s", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (o *AdminWorkspaceListOptions) valid() error { diff --git a/agent_pool.go b/agent_pool.go index f2913efb7..a5db842a6 100644 --- a/agent_pool.go +++ b/agent_pool.go @@ -94,13 +94,13 @@ func (s *agentPools) List(ctx context.Context, organization string, options *Age } u := fmt.Sprintf("organizations/%s/agent-pools", url.QueryEscape(organization)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } poolList := &AgentPoolList{} - err = s.client.do(ctx, req, poolList) + err = req.Do(ctx, poolList) if err != nil { return nil, err } @@ -119,13 +119,13 @@ func (s *agentPools) Create(ctx context.Context, organization string, options Ag } u := fmt.Sprintf("organizations/%s/agent-pools", url.QueryEscape(organization)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return nil, err } pool := &AgentPool{} - err = s.client.do(ctx, req, pool) + err = req.Do(ctx, pool) if err != nil { return nil, err } @@ -148,13 +148,13 @@ func (s *agentPools) ReadWithOptions(ctx context.Context, agentpoolID string, op } u := fmt.Sprintf("agent-pools/%s", url.QueryEscape(agentpoolID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } pool := &AgentPool{} - err = s.client.do(ctx, req, pool) + err = req.Do(ctx, pool) if err != nil { return nil, err } @@ -185,13 +185,13 @@ func (s *agentPools) Update(ctx context.Context, agentPoolID string, options Age } u := fmt.Sprintf("agent-pools/%s", url.QueryEscape(agentPoolID)) - req, err := s.client.newRequest("PATCH", u, &options) + req, err := s.client.NewRequest("PATCH", u, &options) if err != nil { return nil, err } k := &AgentPool{} - err = s.client.do(ctx, req, k) + err = req.Do(ctx, k) if err != nil { return nil, err } @@ -206,12 +206,12 @@ func (s *agentPools) Delete(ctx context.Context, agentPoolID string) error { } u := fmt.Sprintf("agent-pools/%s", url.QueryEscape(agentPoolID)) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (o AgentPoolCreateOptions) valid() error { diff --git a/agent_token.go b/agent_token.go index aa74ae3ba..f7c1ed260 100644 --- a/agent_token.go +++ b/agent_token.go @@ -68,13 +68,13 @@ func (s *agentTokens) List(ctx context.Context, agentPoolID string) (*AgentToken } u := fmt.Sprintf("agent-pools/%s/authentication-tokens", url.QueryEscape(agentPoolID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } tokenList := &AgentTokenList{} - err = s.client.do(ctx, req, tokenList) + err = req.Do(ctx, tokenList) if err != nil { return nil, err } @@ -93,13 +93,13 @@ func (s *agentTokens) Create(ctx context.Context, agentPoolID string, options Ag } u := fmt.Sprintf("agent-pools/%s/authentication-tokens", url.QueryEscape(agentPoolID)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return nil, err } at := &AgentToken{} - err = s.client.do(ctx, req, at) + err = req.Do(ctx, at) if err != nil { return nil, err } @@ -114,13 +114,13 @@ func (s *agentTokens) Read(ctx context.Context, agentTokenID string) (*AgentToke } u := fmt.Sprintf("authentication-tokens/%s", url.QueryEscape(agentTokenID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } at := &AgentToken{} - err = s.client.do(ctx, req, at) + err = req.Do(ctx, at) if err != nil { return nil, err } @@ -135,10 +135,10 @@ func (s *agentTokens) Delete(ctx context.Context, agentTokenID string) error { } u := fmt.Sprintf("authentication-tokens/%s", url.QueryEscape(agentTokenID)) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } diff --git a/apply.go b/apply.go index b18680f07..103153b10 100644 --- a/apply.go +++ b/apply.go @@ -72,13 +72,13 @@ func (s *applies) Read(ctx context.Context, applyID string) (*Apply, error) { } u := fmt.Sprintf("applies/%s", url.QueryEscape(applyID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } a := &Apply{} - err = s.client.do(ctx, req, a) + err = req.Do(ctx, a) if err != nil { return nil, err } diff --git a/comment.go b/comment.go index 0f1a069a8..9b8ab0973 100644 --- a/comment.go +++ b/comment.go @@ -60,13 +60,13 @@ func (s *comments) List(ctx context.Context, runID string) (*CommentList, error) } u := fmt.Sprintf("runs/%s/comments", url.QueryEscape(runID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } cl := &CommentList{} - err = s.client.do(ctx, req, cl) + err = req.Do(ctx, cl) if err != nil { return nil, err } @@ -85,13 +85,13 @@ func (s *comments) Create(ctx context.Context, runID string, options CommentCrea } u := fmt.Sprintf("runs/%s/comments", url.QueryEscape(runID)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return nil, err } comm := &Comment{} - err = s.client.do(ctx, req, comm) + err = req.Do(ctx, comm) if err != nil { return nil, err } @@ -106,13 +106,13 @@ func (s *comments) Read(ctx context.Context, commentID string) (*Comment, error) } u := fmt.Sprintf("comments/%s", url.QueryEscape(commentID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } comm := &Comment{} - err = s.client.do(ctx, req, comm) + err = req.Do(ctx, comm) if err != nil { return nil, err } diff --git a/configuration_version.go b/configuration_version.go index ad4a8a375..f6c629016 100644 --- a/configuration_version.go +++ b/configuration_version.go @@ -188,13 +188,13 @@ func (s *configurationVersions) List(ctx context.Context, workspaceID string, op } u := fmt.Sprintf("workspaces/%s/configuration-versions", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } cvl := &ConfigurationVersionList{} - err = s.client.do(ctx, req, cvl) + err = req.Do(ctx, cvl) if err != nil { return nil, err } @@ -210,13 +210,13 @@ func (s *configurationVersions) Create(ctx context.Context, workspaceID string, } u := fmt.Sprintf("workspaces/%s/configuration-versions", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return nil, err } cv := &ConfigurationVersion{} - err = s.client.do(ctx, req, cv) + err = req.Do(ctx, cv) if err != nil { return nil, err } @@ -239,13 +239,13 @@ func (s *configurationVersions) ReadWithOptions(ctx context.Context, cvID string } u := fmt.Sprintf("configuration-versions/%s", url.QueryEscape(cvID)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } cv := &ConfigurationVersion{} - err = s.client.do(ctx, req, cv) + err = req.Do(ctx, cv) if err != nil { return nil, err } @@ -277,12 +277,12 @@ func (s *configurationVersions) Upload(ctx context.Context, u, path string) erro return err } - req, err := s.client.newRequest("PUT", u, body) + req, err := s.client.NewRequest("PUT", u, body) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // Archive a configuration version. This can only be done on configuration versions that @@ -295,12 +295,12 @@ func (s *configurationVersions) Archive(ctx context.Context, cvID string) error body := bytes.NewBuffer(nil) u := fmt.Sprintf("configuration-versions/%s/actions/archive", url.QueryEscape(cvID)) - req, err := s.client.newRequest("POST", u, body) + req, err := s.client.NewRequest("POST", u, body) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (o *ConfigurationVersionReadOptions) valid() error { @@ -347,13 +347,13 @@ func (s *configurationVersions) Download(ctx context.Context, cvID string) ([]by } u := fmt.Sprintf("configuration-versions/%s/download", url.QueryEscape(cvID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } var buf bytes.Buffer - err = s.client.do(ctx, req, &buf) + err = req.Do(ctx, &buf) if err != nil { return nil, err } diff --git a/cost_estimate.go b/cost_estimate.go index 9dca920df..163f340e5 100644 --- a/cost_estimate.go +++ b/cost_estimate.go @@ -73,13 +73,13 @@ func (s *costEstimates) Read(ctx context.Context, costEstimateID string) (*CostE } u := fmt.Sprintf("cost-estimates/%s", url.QueryEscape(costEstimateID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } ce := &CostEstimate{} - err = s.client.do(ctx, req, ce) + err = req.Do(ctx, ce) if err != nil { return nil, err } @@ -114,13 +114,13 @@ func (s *costEstimates) Logs(ctx context.Context, costEstimateID string) (io.Rea } u := fmt.Sprintf("cost-estimates/%s/output", url.QueryEscape(costEstimateID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } logs := bytes.NewBuffer(nil) - err = s.client.do(ctx, req, logs) + err = req.Do(ctx, logs) if err != nil { return nil, err } diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 23eb340d9..ed89ede0b 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -10,11 +10,11 @@ If you are making relevant changes that is worth communicating to our users, ple CHANGELOG.md should have the next minor version listed as `# v1.X.0 (Unreleased)` and any changes can go under there. But if you feel that your changes are better suited for a patch version (like a critical bug fix), you may list a new section for this version. You should repeat the same formatting style introduced by previous versions. -### Scoping pull requests that add new resources +### Scoping pull requests that add new resources -There are instances where several new resources being added (i.e Workspace Run Tasks and Organization Run Tasks) are coalesced into one PR. In order to keep the review process as efficient and least error prone as possible, we ask that you please scope each PR to an individual resource even if the multiple resources you're adding share similarities. If joining multiple related PRs into one single PR makes more sense logistically, we'd ask that you organize your commit history by resource. A general convention for this repository is one commit for the implementation of the resource's methods, one for the integration test, and one for cleanup and housekeeping (e.g modifying the changelog/docs, generating mocks, etc). +There are instances where several new resources being added (i.e Workspace Run Tasks and Organization Run Tasks) are coalesced into one PR. In order to keep the review process as efficient and least error prone as possible, we ask that you please scope each PR to an individual resource even if the multiple resources you're adding share similarities. If joining multiple related PRs into one single PR makes more sense logistically, we'd ask that you organize your commit history by resource. A general convention for this repository is one commit for the implementation of the resource's methods, one for the integration test, and one for cleanup and housekeeping (e.g modifying the changelog/docs, generating mocks, etc). -**Note HashiCorp Employees Only:** When submitting a new set of endpoints please ensure that one of your respective team members approves the changes as well before merging. +**Note HashiCorp Employees Only:** When submitting a new set of endpoints please ensure that one of your respective team members approves the changes as well before merging. ## Running the Linters Locally @@ -198,13 +198,13 @@ func (s *example) Create(ctx context.Context, organization string, options Examp } u := fmt.Sprintf("organizations/%s/tasks", url.QueryEscape(organization)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return nil, err } r := &Example{} - err = s.client.do(ctx, req, r) + err = req.Do(ctx, r) if err != nil { return nil, err } @@ -222,13 +222,13 @@ func (s *example) List(ctx context.Context, organization string, options *Exampl } u := fmt.Sprintf("organizations/%s/examples", url.QueryEscape(organization)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } el := &ExampleList{} - err = s.client.do(ctx, req, el) + err = req.Do(ctx, el) if err != nil { return nil, err } @@ -251,13 +251,13 @@ func (s *example) ReadWithOptions(ctx context.Context, exampleID string, options } u := fmt.Sprintf("examples/%s", url.QueryEscape(exampleID)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } e := &Example{} - err = s.client.do(ctx, req, e) + err = req.Do(ctx, e) if err != nil { return nil, err } @@ -276,13 +276,13 @@ func (s *example) Update(ctx context.Context, exampleID string, options ExampleU } u := fmt.Sprintf("examples/%s", url.QueryEscape(exampleID)) - req, err := s.client.newRequest("PATCH", u, &options) + req, err := s.client.NewRequest("PATCH", u, &options) if err != nil { return nil, err } r := &Example{} - err = s.client.do(ctx, req, r) + err = req.Do(ctx, r) if err != nil { return nil, err } @@ -297,12 +297,12 @@ func (s *example) Delete(ctx context.Context, exampleID string) error { } u := fmt.Sprintf("examples/%s", exampleID) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (o *ExampleUpdateOptions) valid() error { diff --git a/gpg_key.go b/gpg_key.go index a56b11156..656074aee 100644 --- a/gpg_key.go +++ b/gpg_key.go @@ -76,13 +76,13 @@ func (s *gpgKeys) Create(ctx context.Context, registryName RegistryName, options } u := fmt.Sprintf("/api/registry/%s/v2/gpg-keys", url.QueryEscape(string(registryName))) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return nil, err } g := &GPGKey{} - err = s.client.do(ctx, req, g) + err = req.Do(ctx, g) if err != nil { return nil, err } @@ -100,13 +100,13 @@ func (s *gpgKeys) Read(ctx context.Context, keyID GPGKeyID) (*GPGKey, error) { url.QueryEscape(keyID.Namespace), url.QueryEscape(keyID.KeyID), ) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } g := &GPGKey{} - err = s.client.do(ctx, req, g) + err = req.Do(ctx, g) if err != nil { return nil, err } @@ -128,13 +128,13 @@ func (s *gpgKeys) Update(ctx context.Context, keyID GPGKeyID, options GPGKeyUpda url.QueryEscape(keyID.Namespace), url.QueryEscape(keyID.KeyID), ) - req, err := s.client.newRequest("PATCH", u, &options) + req, err := s.client.NewRequest("PATCH", u, &options) if err != nil { return nil, err } g := &GPGKey{} - err = s.client.do(ctx, req, g) + err = req.Do(ctx, g) if err != nil { if strings.Contains(err.Error(), "namespace not authorized") { return nil, ErrNamespaceNotAuthorized @@ -155,12 +155,12 @@ func (s *gpgKeys) Delete(ctx context.Context, keyID GPGKeyID) error { url.QueryEscape(keyID.Namespace), url.QueryEscape(keyID.KeyID), ) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (o GPGKeyID) valid() error { diff --git a/helper_test.go b/helper_test.go index 0bac9fb1a..839ed407f 100644 --- a/helper_test.go +++ b/helper_test.go @@ -1437,7 +1437,7 @@ func upgradeOrganizationSubscription(t *testing.T, client *Client, organization t.Skip("Can not upgrade an organization's subscription when enterprise is enabled. Set ENABLE_TFE=0 to run.") } - req, err := client.newRequest("GET", "admin/feature-sets", featureSetListOptions{ + req, err := client.NewRequest("GET", "admin/feature-sets", featureSetListOptions{ Q: "Business", }) if err != nil { @@ -1446,7 +1446,7 @@ func upgradeOrganizationSubscription(t *testing.T, client *Client, organization } fsl := &featureSetList{} - err = client.do(context.Background(), req, fsl) + err = req.Do(context.Background(), fsl) if err != nil { t.Fatalf("failed to enumerate feature sets: %v", err) return @@ -1464,13 +1464,13 @@ func upgradeOrganizationSubscription(t *testing.T, client *Client, organization } u := fmt.Sprintf("admin/organizations/%s/subscription", url.QueryEscape(organization.Name)) - req, err = client.newRequest("POST", u, &opts) + req, err = client.NewRequest("POST", u, &opts) if err != nil { t.Fatalf("Failed to create request: %v", err) return } - err = client.do(context.Background(), req, nil) + err = req.Do(context.Background(), nil) if err != nil { t.Fatalf("Failed to upgrade subscription: %v", err) } diff --git a/ip_ranges.go b/ip_ranges.go index c03e3fd1f..07fc61956 100644 --- a/ip_ranges.go +++ b/ip_ranges.go @@ -37,7 +37,7 @@ type IPRange struct { // Read an IPRange that was not modified since the specified date. func (i *ipRanges) Read(ctx context.Context, modifiedSince string) (*IPRange, error) { - req, err := i.client.newRequest("GET", "/api/meta/ip-ranges", nil) + req, err := i.client.NewRequest("GET", "/api/meta/ip-ranges", nil) if err != nil { return nil, err } @@ -47,7 +47,7 @@ func (i *ipRanges) Read(ctx context.Context, modifiedSince string) (*IPRange, er } ir := &IPRange{} - err = i.customDo(ctx, req, ir) + err = req.doIpRanges(ctx, ir) if err != nil { return nil, err } diff --git a/notification_configuration.go b/notification_configuration.go index 97f8da196..0805ee147 100644 --- a/notification_configuration.go +++ b/notification_configuration.go @@ -183,13 +183,13 @@ func (s *notificationConfigurations) List(ctx context.Context, workspaceID strin } u := fmt.Sprintf("workspaces/%s/notification-configurations", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } ncl := &NotificationConfigurationList{} - err = s.client.do(ctx, req, ncl) + err = req.Do(ctx, ncl) if err != nil { return nil, err } @@ -207,13 +207,13 @@ func (s *notificationConfigurations) Create(ctx context.Context, workspaceID str } u := fmt.Sprintf("workspaces/%s/notification-configurations", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return nil, err } nc := &NotificationConfiguration{} - err = s.client.do(ctx, req, nc) + err = req.Do(ctx, nc) if err != nil { return nil, err } @@ -228,13 +228,13 @@ func (s *notificationConfigurations) Read(ctx context.Context, notificationConfi } u := fmt.Sprintf("notification-configurations/%s", url.QueryEscape(notificationConfigurationID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } nc := &NotificationConfiguration{} - err = s.client.do(ctx, req, nc) + err = req.Do(ctx, nc) if err != nil { return nil, err } @@ -253,13 +253,13 @@ func (s *notificationConfigurations) Update(ctx context.Context, notificationCon } u := fmt.Sprintf("notification-configurations/%s", url.QueryEscape(notificationConfigurationID)) - req, err := s.client.newRequest("PATCH", u, &options) + req, err := s.client.NewRequest("PATCH", u, &options) if err != nil { return nil, err } nc := &NotificationConfiguration{} - err = s.client.do(ctx, req, nc) + err = req.Do(ctx, nc) if err != nil { return nil, err } @@ -274,12 +274,12 @@ func (s *notificationConfigurations) Delete(ctx context.Context, notificationCon } u := fmt.Sprintf("notification-configurations/%s", url.QueryEscape(notificationConfigurationID)) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // Verify a notification configuration by delivering a verification @@ -291,13 +291,13 @@ func (s *notificationConfigurations) Verify(ctx context.Context, notificationCon u := fmt.Sprintf( "notification-configurations/%s/actions/verify", url.QueryEscape(notificationConfigurationID)) - req, err := s.client.newRequest("POST", u, nil) + req, err := s.client.NewRequest("POST", u, nil) if err != nil { return nil, err } nc := &NotificationConfiguration{} - err = s.client.do(ctx, req, nc) + err = req.Do(ctx, nc) if err != nil { return nil, err } diff --git a/oauth_client.go b/oauth_client.go index 4be2321af..e0034417c 100644 --- a/oauth_client.go +++ b/oauth_client.go @@ -167,13 +167,13 @@ func (s *oAuthClients) List(ctx context.Context, organization string, options *O } u := fmt.Sprintf("organizations/%s/oauth-clients", url.QueryEscape(organization)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } ocl := &OAuthClientList{} - err = s.client.do(ctx, req, ocl) + err = req.Do(ctx, ocl) if err != nil { return nil, err } @@ -191,13 +191,13 @@ func (s *oAuthClients) Create(ctx context.Context, organization string, options } u := fmt.Sprintf("organizations/%s/oauth-clients", url.QueryEscape(organization)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return nil, err } oc := &OAuthClient{} - err = s.client.do(ctx, req, oc) + err = req.Do(ctx, oc) if err != nil { return nil, err } @@ -212,13 +212,13 @@ func (s *oAuthClients) Read(ctx context.Context, oAuthClientID string) (*OAuthCl } u := fmt.Sprintf("oauth-clients/%s", url.QueryEscape(oAuthClientID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } oc := &OAuthClient{} - err = s.client.do(ctx, req, oc) + err = req.Do(ctx, oc) if err != nil { return nil, err } @@ -233,13 +233,13 @@ func (s *oAuthClients) Update(ctx context.Context, oAuthClientID string, options } u := fmt.Sprintf("oauth-clients/%s", url.QueryEscape(oAuthClientID)) - req, err := s.client.newRequest("PATCH", u, &options) + req, err := s.client.NewRequest("PATCH", u, &options) if err != nil { return nil, err } oc := &OAuthClient{} - err = s.client.do(ctx, req, oc) + err = req.Do(ctx, oc) if err != nil { return nil, err } @@ -254,12 +254,12 @@ func (s *oAuthClients) Delete(ctx context.Context, oAuthClientID string) error { } u := fmt.Sprintf("oauth-clients/%s", url.QueryEscape(oAuthClientID)) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (o OAuthClientCreateOptions) valid() error { diff --git a/oauth_token.go b/oauth_token.go index 2c882498c..ddefc23a7 100644 --- a/oauth_token.go +++ b/oauth_token.go @@ -77,13 +77,13 @@ func (s *oAuthTokens) List(ctx context.Context, organization string, options *OA } u := fmt.Sprintf("organizations/%s/oauth-tokens", url.QueryEscape(organization)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } otl := &OAuthTokenList{} - err = s.client.do(ctx, req, otl) + err = req.Do(ctx, otl) if err != nil { return nil, err } @@ -98,13 +98,13 @@ func (s *oAuthTokens) Read(ctx context.Context, oAuthTokenID string) (*OAuthToke } u := fmt.Sprintf("oauth-tokens/%s", url.QueryEscape(oAuthTokenID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } ot := &OAuthToken{} - err = s.client.do(ctx, req, ot) + err = req.Do(ctx, ot) if err != nil { return nil, err } @@ -119,13 +119,13 @@ func (s *oAuthTokens) Update(ctx context.Context, oAuthTokenID string, options O } u := fmt.Sprintf("oauth-tokens/%s", url.QueryEscape(oAuthTokenID)) - req, err := s.client.newRequest("PATCH", u, &options) + req, err := s.client.NewRequest("PATCH", u, &options) if err != nil { return nil, err } ot := &OAuthToken{} - err = s.client.do(ctx, req, ot) + err = req.Do(ctx, ot) if err != nil { return nil, err } @@ -140,10 +140,10 @@ func (s *oAuthTokens) Delete(ctx context.Context, oAuthTokenID string) error { } u := fmt.Sprintf("oauth-tokens/%s", url.QueryEscape(oAuthTokenID)) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } diff --git a/organization.go b/organization.go index 8b3b3941b..6d1d31b45 100644 --- a/organization.go +++ b/organization.go @@ -200,13 +200,13 @@ type ReadRunQueueOptions struct { // List all the organizations visible to the current user. func (s *organizations) List(ctx context.Context, options *OrganizationListOptions) (*OrganizationList, error) { - req, err := s.client.newRequest("GET", "organizations", options) + req, err := s.client.NewRequest("GET", "organizations", options) if err != nil { return nil, err } orgl := &OrganizationList{} - err = s.client.do(ctx, req, orgl) + err = req.Do(ctx, orgl) if err != nil { return nil, err } @@ -220,13 +220,13 @@ func (s *organizations) Create(ctx context.Context, options OrganizationCreateOp return nil, err } - req, err := s.client.newRequest("POST", "organizations", &options) + req, err := s.client.NewRequest("POST", "organizations", &options) if err != nil { return nil, err } org := &Organization{} - err = s.client.do(ctx, req, org) + err = req.Do(ctx, org) if err != nil { return nil, err } @@ -241,13 +241,13 @@ func (s *organizations) Read(ctx context.Context, organization string) (*Organiz } u := fmt.Sprintf("organizations/%s", url.QueryEscape(organization)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } org := &Organization{} - err = s.client.do(ctx, req, org) + err = req.Do(ctx, org) if err != nil { return nil, err } @@ -262,13 +262,13 @@ func (s *organizations) Update(ctx context.Context, organization string, options } u := fmt.Sprintf("organizations/%s", url.QueryEscape(organization)) - req, err := s.client.newRequest("PATCH", u, &options) + req, err := s.client.NewRequest("PATCH", u, &options) if err != nil { return nil, err } org := &Organization{} - err = s.client.do(ctx, req, org) + err = req.Do(ctx, org) if err != nil { return nil, err } @@ -283,12 +283,12 @@ func (s *organizations) Delete(ctx context.Context, organization string) error { } u := fmt.Sprintf("organizations/%s", url.QueryEscape(organization)) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // ReadCapacity shows the currently used capacity of an organization. @@ -298,13 +298,13 @@ func (s *organizations) ReadCapacity(ctx context.Context, organization string) ( } u := fmt.Sprintf("organizations/%s/capacity", url.QueryEscape(organization)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } c := &Capacity{} - err = s.client.do(ctx, req, c) + err = req.Do(ctx, c) if err != nil { return nil, err } @@ -319,13 +319,13 @@ func (s *organizations) ReadEntitlements(ctx context.Context, organization strin } u := fmt.Sprintf("organizations/%s/entitlement-set", url.QueryEscape(organization)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } e := &Entitlements{} - err = s.client.do(ctx, req, e) + err = req.Do(ctx, e) if err != nil { return nil, err } @@ -340,13 +340,13 @@ func (s *organizations) ReadRunQueue(ctx context.Context, organization string, o } u := fmt.Sprintf("organizations/%s/runs/queue", url.QueryEscape(organization)) - req, err := s.client.newRequest("GET", u, &options) + req, err := s.client.NewRequest("GET", u, &options) if err != nil { return nil, err } rq := &RunQueue{} - err = s.client.do(ctx, req, rq) + err = req.Do(ctx, rq) if err != nil { return nil, err } diff --git a/organization_membership.go b/organization_membership.go index aab19eea5..396b3a94a 100644 --- a/organization_membership.go +++ b/organization_membership.go @@ -111,13 +111,13 @@ func (s *organizationMemberships) List(ctx context.Context, organization string, } u := fmt.Sprintf("organizations/%s/organization-memberships", url.QueryEscape(organization)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } ml := &OrganizationMembershipList{} - err = s.client.do(ctx, req, ml) + err = req.Do(ctx, ml) if err != nil { return nil, err } @@ -135,13 +135,13 @@ func (s *organizationMemberships) Create(ctx context.Context, organization strin } u := fmt.Sprintf("organizations/%s/organization-memberships", url.QueryEscape(organization)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return nil, err } m := &OrganizationMembership{} - err = s.client.do(ctx, req, m) + err = req.Do(ctx, m) if err != nil { return nil, err } @@ -164,13 +164,13 @@ func (s *organizationMemberships) ReadWithOptions(ctx context.Context, organizat } u := fmt.Sprintf("organization-memberships/%s", url.QueryEscape(organizationMembershipID)) - req, err := s.client.newRequest("GET", u, &options) + req, err := s.client.NewRequest("GET", u, &options) if err != nil { return nil, err } mem := &OrganizationMembership{} - err = s.client.do(ctx, req, mem) + err = req.Do(ctx, mem) if err != nil { return nil, err } @@ -185,12 +185,12 @@ func (s *organizationMemberships) Delete(ctx context.Context, organizationMember } u := fmt.Sprintf("organization-memberships/%s", url.QueryEscape(organizationMembershipID)) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (o OrganizationMembershipCreateOptions) valid() error { diff --git a/organization_tags.go b/organization_tags.go index bbf756f74..81e688e4a 100644 --- a/organization_tags.go +++ b/organization_tags.go @@ -82,13 +82,13 @@ func (s *organizationTags) List(ctx context.Context, organization string, option } u := fmt.Sprintf("organizations/%s/tags", url.QueryEscape(organization)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } tags := &OrganizationTagsList{} - err = s.client.do(ctx, req, tags) + err = req.Do(ctx, tags) if err != nil { return nil, err } @@ -112,12 +112,12 @@ func (s *organizationTags) Delete(ctx context.Context, organization string, opti tagsToRemove = append(tagsToRemove, &tagID{ID: id}) } - req, err := s.client.newRequest("DELETE", u, tagsToRemove) + req, err := s.client.NewRequest("DELETE", u, tagsToRemove) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // Add workspaces to a tag @@ -136,12 +136,12 @@ func (s *organizationTags) AddWorkspaces(ctx context.Context, tag string, option } u := fmt.Sprintf("tags/%s/relationships/workspaces", url.QueryEscape(tag)) - req, err := s.client.newRequest("POST", u, workspaces) + req, err := s.client.NewRequest("POST", u, workspaces) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (opts *OrganizationTagsDeleteOptions) valid() error { diff --git a/organization_token.go b/organization_token.go index 263f38cf7..241541dce 100644 --- a/organization_token.go +++ b/organization_token.go @@ -47,13 +47,13 @@ func (s *organizationTokens) Create(ctx context.Context, organization string) (* } u := fmt.Sprintf("organizations/%s/authentication-token", url.QueryEscape(organization)) - req, err := s.client.newRequest("POST", u, nil) + req, err := s.client.NewRequest("POST", u, nil) if err != nil { return nil, err } ot := &OrganizationToken{} - err = s.client.do(ctx, req, ot) + err = req.Do(ctx, ot) if err != nil { return nil, err } @@ -68,13 +68,13 @@ func (s *organizationTokens) Read(ctx context.Context, organization string) (*Or } u := fmt.Sprintf("organizations/%s/authentication-token", url.QueryEscape(organization)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } ot := &OrganizationToken{} - err = s.client.do(ctx, req, ot) + err = req.Do(ctx, ot) if err != nil { return nil, err } @@ -89,10 +89,10 @@ func (s *organizationTokens) Delete(ctx context.Context, organization string) er } u := fmt.Sprintf("organizations/%s/authentication-token", url.QueryEscape(organization)) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } diff --git a/plan.go b/plan.go index 67674be87..993f875aa 100644 --- a/plan.go +++ b/plan.go @@ -80,13 +80,13 @@ func (s *plans) Read(ctx context.Context, planID string) (*Plan, error) { } u := fmt.Sprintf("plans/%s", url.QueryEscape(planID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } p := &Plan{} - err = s.client.do(ctx, req, p) + err = req.Do(ctx, p) if err != nil { return nil, err } @@ -145,13 +145,13 @@ func (s *plans) ReadJSONOutput(ctx context.Context, planID string) ([]byte, erro } u := fmt.Sprintf("plans/%s/json-output", url.QueryEscape(planID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } var buf bytes.Buffer - err = s.client.do(ctx, req, &buf) + err = req.Do(ctx, &buf) if err != nil { return nil, err } diff --git a/plan_export.go b/plan_export.go index 35dc907b1..8151f619d 100644 --- a/plan_export.go +++ b/plan_export.go @@ -93,13 +93,13 @@ func (s *planExports) Create(ctx context.Context, options PlanExportCreateOption return nil, err } - req, err := s.client.newRequest("POST", "plan-exports", &options) + req, err := s.client.NewRequest("POST", "plan-exports", &options) if err != nil { return nil, err } pe := &PlanExport{} - err = s.client.do(ctx, req, pe) + err = req.Do(ctx, pe) if err != nil { return nil, err } @@ -114,13 +114,13 @@ func (s *planExports) Read(ctx context.Context, planExportID string) (*PlanExpor } u := fmt.Sprintf("plan-exports/%s", url.QueryEscape(planExportID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } pe := &PlanExport{} - err = s.client.do(ctx, req, pe) + err = req.Do(ctx, pe) if err != nil { return nil, err } @@ -135,12 +135,12 @@ func (s *planExports) Delete(ctx context.Context, planExportID string) error { } u := fmt.Sprintf("plan-exports/%s", url.QueryEscape(planExportID)) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // Download a plan export's data. Data is exported in a .tar.gz format. @@ -150,13 +150,13 @@ func (s *planExports) Download(ctx context.Context, planExportID string) ([]byte } u := fmt.Sprintf("plan-exports/%s/download", url.QueryEscape(planExportID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } var buf bytes.Buffer - err = s.client.do(ctx, req, &buf) + err = req.Do(ctx, &buf) if err != nil { return nil, err } diff --git a/policy.go b/policy.go index 49a293a5a..3443cb21a 100644 --- a/policy.go +++ b/policy.go @@ -132,13 +132,13 @@ func (s *policies) List(ctx context.Context, organization string, options *Polic } u := fmt.Sprintf("organizations/%s/policies", url.QueryEscape(organization)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } pl := &PolicyList{} - err = s.client.do(ctx, req, pl) + err = req.Do(ctx, pl) if err != nil { return nil, err } @@ -156,13 +156,13 @@ func (s *policies) Create(ctx context.Context, organization string, options Poli } u := fmt.Sprintf("organizations/%s/policies", url.QueryEscape(organization)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return nil, err } p := &Policy{} - err = s.client.do(ctx, req, p) + err = req.Do(ctx, p) if err != nil { return nil, err } @@ -177,13 +177,13 @@ func (s *policies) Read(ctx context.Context, policyID string) (*Policy, error) { } u := fmt.Sprintf("policies/%s", url.QueryEscape(policyID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } p := &Policy{} - err = s.client.do(ctx, req, p) + err = req.Do(ctx, p) if err != nil { return nil, err } @@ -198,13 +198,13 @@ func (s *policies) Update(ctx context.Context, policyID string, options PolicyUp } u := fmt.Sprintf("policies/%s", url.QueryEscape(policyID)) - req, err := s.client.newRequest("PATCH", u, &options) + req, err := s.client.NewRequest("PATCH", u, &options) if err != nil { return nil, err } p := &Policy{} - err = s.client.do(ctx, req, p) + err = req.Do(ctx, p) if err != nil { return nil, err } @@ -219,12 +219,12 @@ func (s *policies) Delete(ctx context.Context, policyID string) error { } u := fmt.Sprintf("policies/%s", url.QueryEscape(policyID)) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // Upload the policy content of the policy. @@ -234,12 +234,12 @@ func (s *policies) Upload(ctx context.Context, policyID string, content []byte) } u := fmt.Sprintf("policies/%s/upload", url.QueryEscape(policyID)) - req, err := s.client.newRequest("PUT", u, content) + req, err := s.client.NewRequest("PUT", u, content) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // Download the policy content of the policy. @@ -249,13 +249,13 @@ func (s *policies) Download(ctx context.Context, policyID string) ([]byte, error } u := fmt.Sprintf("policies/%s/download", url.QueryEscape(policyID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } var buf bytes.Buffer - err = s.client.do(ctx, req, &buf) + err = req.Do(ctx, &buf) if err != nil { return nil, err } diff --git a/policy_check.go b/policy_check.go index 0a1dea114..549da79a5 100644 --- a/policy_check.go +++ b/policy_check.go @@ -138,13 +138,13 @@ func (s *policyChecks) List(ctx context.Context, runID string, options *PolicyCh } u := fmt.Sprintf("runs/%s/policy-checks", url.QueryEscape(runID)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } pcl := &PolicyCheckList{} - err = s.client.do(ctx, req, pcl) + err = req.Do(ctx, pcl) if err != nil { return nil, err } @@ -159,13 +159,13 @@ func (s *policyChecks) Read(ctx context.Context, policyCheckID string) (*PolicyC } u := fmt.Sprintf("policy-checks/%s", url.QueryEscape(policyCheckID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } pc := &PolicyCheck{} - err = s.client.do(ctx, req, pc) + err = req.Do(ctx, pc) if err != nil { return nil, err } @@ -180,13 +180,13 @@ func (s *policyChecks) Override(ctx context.Context, policyCheckID string) (*Pol } u := fmt.Sprintf("policy-checks/%s/actions/override", url.QueryEscape(policyCheckID)) - req, err := s.client.newRequest("POST", u, nil) + req, err := s.client.NewRequest("POST", u, nil) if err != nil { return nil, err } pc := &PolicyCheck{} - err = s.client.do(ctx, req, pc) + err = req.Do(ctx, pc) if err != nil { return nil, err } @@ -220,13 +220,13 @@ func (s *policyChecks) Logs(ctx context.Context, policyCheckID string) (io.Reade } u := fmt.Sprintf("policy-checks/%s/output", url.QueryEscape(policyCheckID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } logs := bytes.NewBuffer(nil) - err = s.client.do(ctx, req, logs) + err = req.Do(ctx, logs) if err != nil { return nil, err } diff --git a/policy_set.go b/policy_set.go index ff0e021a3..b2157b0f7 100644 --- a/policy_set.go +++ b/policy_set.go @@ -217,13 +217,13 @@ func (s *policySets) List(ctx context.Context, organization string, options *Pol } u := fmt.Sprintf("organizations/%s/policy-sets", url.QueryEscape(organization)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } psl := &PolicySetList{} - err = s.client.do(ctx, req, psl) + err = req.Do(ctx, psl) if err != nil { return nil, err } @@ -241,13 +241,13 @@ func (s *policySets) Create(ctx context.Context, organization string, options Po } u := fmt.Sprintf("organizations/%s/policy-sets", url.QueryEscape(organization)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return nil, err } ps := &PolicySet{} - err = s.client.do(ctx, req, ps) + err = req.Do(ctx, ps) if err != nil { return nil, err } @@ -270,13 +270,13 @@ func (s *policySets) ReadWithOptions(ctx context.Context, policySetID string, op } u := fmt.Sprintf("policy-sets/%s", url.QueryEscape(policySetID)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } ps := &PolicySet{} - err = s.client.do(ctx, req, ps) + err = req.Do(ctx, ps) if err != nil { return nil, err } @@ -294,13 +294,13 @@ func (s *policySets) Update(ctx context.Context, policySetID string, options Pol } u := fmt.Sprintf("policy-sets/%s", url.QueryEscape(policySetID)) - req, err := s.client.newRequest("PATCH", u, &options) + req, err := s.client.NewRequest("PATCH", u, &options) if err != nil { return nil, err } ps := &PolicySet{} - err = s.client.do(ctx, req, ps) + err = req.Do(ctx, ps) if err != nil { return nil, err } @@ -318,12 +318,12 @@ func (s *policySets) AddPolicies(ctx context.Context, policySetID string, option } u := fmt.Sprintf("policy-sets/%s/relationships/policies", url.QueryEscape(policySetID)) - req, err := s.client.newRequest("POST", u, options.Policies) + req, err := s.client.NewRequest("POST", u, options.Policies) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // RemovePolicies remove policies from a policy set @@ -336,12 +336,12 @@ func (s *policySets) RemovePolicies(ctx context.Context, policySetID string, opt } u := fmt.Sprintf("policy-sets/%s/relationships/policies", url.QueryEscape(policySetID)) - req, err := s.client.newRequest("DELETE", u, options.Policies) + req, err := s.client.NewRequest("DELETE", u, options.Policies) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // Addworkspaces adds workspaces to a policy set. @@ -354,12 +354,12 @@ func (s *policySets) AddWorkspaces(ctx context.Context, policySetID string, opti } u := fmt.Sprintf("policy-sets/%s/relationships/workspaces", url.QueryEscape(policySetID)) - req, err := s.client.newRequest("POST", u, options.Workspaces) + req, err := s.client.NewRequest("POST", u, options.Workspaces) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // RemoveWorkspaces removes workspaces from a policy set. @@ -372,12 +372,12 @@ func (s *policySets) RemoveWorkspaces(ctx context.Context, policySetID string, o } u := fmt.Sprintf("policy-sets/%s/relationships/workspaces", url.QueryEscape(policySetID)) - req, err := s.client.newRequest("DELETE", u, options.Workspaces) + req, err := s.client.NewRequest("DELETE", u, options.Workspaces) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // Delete a policy set by its ID. @@ -387,12 +387,12 @@ func (s *policySets) Delete(ctx context.Context, policySetID string) error { } u := fmt.Sprintf("policy-sets/%s", url.QueryEscape(policySetID)) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (o PolicySetCreateOptions) valid() error { diff --git a/policy_set_parameter.go b/policy_set_parameter.go index 5d5201756..ca2be27c0 100644 --- a/policy_set_parameter.go +++ b/policy_set_parameter.go @@ -104,13 +104,13 @@ func (s *policySetParameters) List(ctx context.Context, policySetID string, opti } u := fmt.Sprintf("policy-sets/%s/parameters", policySetID) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } vl := &PolicySetParameterList{} - err = s.client.do(ctx, req, vl) + err = req.Do(ctx, vl) if err != nil { return nil, err } @@ -128,13 +128,13 @@ func (s *policySetParameters) Create(ctx context.Context, policySetID string, op } u := fmt.Sprintf("policy-sets/%s/parameters", url.QueryEscape(policySetID)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return nil, err } p := &PolicySetParameter{} - err = s.client.do(ctx, req, p) + err = req.Do(ctx, p) if err != nil { return nil, err } @@ -152,13 +152,13 @@ func (s *policySetParameters) Read(ctx context.Context, policySetID, parameterID } u := fmt.Sprintf("policy-sets/%s/parameters/%s", url.QueryEscape(policySetID), url.QueryEscape(parameterID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } p := &PolicySetParameter{} - err = s.client.do(ctx, req, p) + err = req.Do(ctx, p) if err != nil { return nil, err } @@ -176,13 +176,13 @@ func (s *policySetParameters) Update(ctx context.Context, policySetID, parameter } u := fmt.Sprintf("policy-sets/%s/parameters/%s", url.QueryEscape(policySetID), url.QueryEscape(parameterID)) - req, err := s.client.newRequest("PATCH", u, &options) + req, err := s.client.NewRequest("PATCH", u, &options) if err != nil { return nil, err } p := &PolicySetParameter{} - err = s.client.do(ctx, req, p) + err = req.Do(ctx, p) if err != nil { return nil, err } @@ -200,12 +200,12 @@ func (s *policySetParameters) Delete(ctx context.Context, policySetID, parameter } u := fmt.Sprintf("policy-sets/%s/parameters/%s", url.QueryEscape(policySetID), url.QueryEscape(parameterID)) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (o PolicySetParameterCreateOptions) valid() error { diff --git a/policy_set_version.go b/policy_set_version.go index 6d31ae876..b1d075507 100644 --- a/policy_set_version.go +++ b/policy_set_version.go @@ -102,13 +102,13 @@ func (p *policySetVersions) Create(ctx context.Context, policySetID string) (*Po } u := fmt.Sprintf("policy-sets/%s/versions", url.QueryEscape(policySetID)) - req, err := p.client.newRequest("POST", u, nil) + req, err := p.client.NewRequest("POST", u, nil) if err != nil { return nil, err } psv := &PolicySetVersion{} - err = p.client.do(ctx, req, psv) + err = req.Do(ctx, psv) if err != nil { return nil, err } @@ -123,13 +123,13 @@ func (p *policySetVersions) Read(ctx context.Context, policySetVersionID string) } u := fmt.Sprintf("policy-set-versions/%s", url.QueryEscape(policySetVersionID)) - req, err := p.client.newRequest("GET", u, nil) + req, err := p.client.NewRequest("GET", u, nil) if err != nil { return nil, err } psv := &PolicySetVersion{} - err = p.client.do(ctx, req, psv) + err = req.Do(ctx, psv) if err != nil { return nil, err } @@ -151,10 +151,10 @@ func (p *policySetVersions) Upload(ctx context.Context, psv PolicySetVersion, pa return err } - req, err := p.client.newRequest("PUT", uploadURL, body) + req, err := p.client.NewRequest("PUT", uploadURL, body) if err != nil { return err } - return p.client.do(ctx, req, nil) + return req.Do(ctx, nil) } diff --git a/registry_module.go b/registry_module.go index 1e0605f3d..56e753092 100644 --- a/registry_module.go +++ b/registry_module.go @@ -188,13 +188,13 @@ func (s *registryModules) List(ctx context.Context, organization string, options } u := fmt.Sprintf("organizations/%s/registry-modules", url.QueryEscape(organization)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } ml := &RegistryModuleList{} - err = s.client.do(ctx, req, ml) + err = req.Do(ctx, ml) if err != nil { return nil, err } @@ -216,12 +216,12 @@ func (r *registryModules) Upload(ctx context.Context, rmv RegistryModuleVersion, return err } - req, err := r.client.newRequest("PUT", uploadURL, body) + req, err := r.client.NewRequest("PUT", uploadURL, body) if err != nil { return err } - return r.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // Create a new registry module without a VCS repo @@ -237,13 +237,13 @@ func (r *registryModules) Create(ctx context.Context, organization string, optio "organizations/%s/registry-modules", url.QueryEscape(organization), ) - req, err := r.client.newRequest("POST", u, &options) + req, err := r.client.NewRequest("POST", u, &options) if err != nil { return nil, err } rm := &RegistryModule{} - err = r.client.do(ctx, req, rm) + err = req.Do(ctx, rm) if err != nil { return nil, err } @@ -267,13 +267,13 @@ func (r *registryModules) CreateVersion(ctx context.Context, moduleID RegistryMo url.QueryEscape(moduleID.Name), url.QueryEscape(moduleID.Provider), ) - req, err := r.client.newRequest("POST", u, &options) + req, err := r.client.NewRequest("POST", u, &options) if err != nil { return nil, err } rmv := &RegistryModuleVersion{} - err = r.client.do(ctx, req, rmv) + err = req.Do(ctx, rmv) if err != nil { return nil, err } @@ -287,13 +287,13 @@ func (r *registryModules) CreateWithVCSConnection(ctx context.Context, options R return nil, err } - req, err := r.client.newRequest("POST", "registry-modules", &options) + req, err := r.client.NewRequest("POST", "registry-modules", &options) if err != nil { return nil, err } rm := &RegistryModule{} - err = r.client.do(ctx, req, rm) + err = req.Do(ctx, rm) if err != nil { return nil, err } @@ -313,13 +313,13 @@ func (r *registryModules) Read(ctx context.Context, moduleID RegistryModuleID) ( url.QueryEscape(moduleID.Name), url.QueryEscape(moduleID.Provider), ) - req, err := r.client.newRequest("GET", u, nil) + req, err := r.client.NewRequest("GET", u, nil) if err != nil { return nil, err } rm := &RegistryModule{} - err = r.client.do(ctx, req, rm) + err = req.Do(ctx, rm) if err != nil { return nil, err } @@ -344,12 +344,12 @@ func (r *registryModules) Delete(ctx context.Context, organization, name string) url.QueryEscape(organization), url.QueryEscape(name), ) - req, err := r.client.newRequest("POST", u, nil) + req, err := r.client.NewRequest("POST", u, nil) if err != nil { return err } - return r.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // DeleteProvider is used to delete the specific registry module provider @@ -364,12 +364,12 @@ func (r *registryModules) DeleteProvider(ctx context.Context, moduleID RegistryM url.QueryEscape(moduleID.Name), url.QueryEscape(moduleID.Provider), ) - req, err := r.client.newRequest("POST", u, nil) + req, err := r.client.NewRequest("POST", u, nil) if err != nil { return err } - return r.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // DeleteVersion is used to delete the specific registry module version @@ -391,12 +391,12 @@ func (r *registryModules) DeleteVersion(ctx context.Context, moduleID RegistryMo url.QueryEscape(moduleID.Provider), url.QueryEscape(version), ) - req, err := r.client.newRequest("POST", u, nil) + req, err := r.client.NewRequest("POST", u, nil) if err != nil { return err } - return r.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (o RegistryModuleID) valid() error { diff --git a/registry_provider.go b/registry_provider.go index db32da997..43dd9fced 100644 --- a/registry_provider.go +++ b/registry_provider.go @@ -132,13 +132,13 @@ func (r *registryProviders) List(ctx context.Context, organization string, optio } u := fmt.Sprintf("organizations/%s/registry-providers", url.QueryEscape(organization)) - req, err := r.client.newRequest("GET", u, options) + req, err := r.client.NewRequest("GET", u, options) if err != nil { return nil, err } pl := &RegistryProviderList{} - err = r.client.do(ctx, req, pl) + err = req.Do(ctx, pl) if err != nil { return nil, err } @@ -159,13 +159,13 @@ func (r *registryProviders) Create(ctx context.Context, organization string, opt "organizations/%s/registry-providers", url.QueryEscape(organization), ) - req, err := r.client.newRequest("POST", u, &options) + req, err := r.client.NewRequest("POST", u, &options) if err != nil { return nil, err } prv := &RegistryProvider{} - err = r.client.do(ctx, req, prv) + err = req.Do(ctx, prv) if err != nil { return nil, err } @@ -185,13 +185,13 @@ func (r *registryProviders) Read(ctx context.Context, providerID RegistryProvide url.QueryEscape(providerID.Namespace), url.QueryEscape(providerID.Name), ) - req, err := r.client.newRequest("GET", u, options) + req, err := r.client.NewRequest("GET", u, options) if err != nil { return nil, err } prv := &RegistryProvider{} - err = r.client.do(ctx, req, prv) + err = req.Do(ctx, prv) if err != nil { return nil, err } @@ -211,12 +211,12 @@ func (r *registryProviders) Delete(ctx context.Context, providerID RegistryProvi url.QueryEscape(providerID.Namespace), url.QueryEscape(providerID.Name), ) - req, err := r.client.newRequest("DELETE", u, nil) + req, err := r.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return r.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (o RegistryProviderCreateOptions) valid() error { diff --git a/registry_provider_platform.go b/registry_provider_platform.go index 9f2d99756..c64ce84bc 100644 --- a/registry_provider_platform.go +++ b/registry_provider_platform.go @@ -56,13 +56,13 @@ type RegistryProviderPlatformID struct { // RegistryProviderPlatformCreateOptions represents the set of options for creating a registry provider platform type RegistryProviderPlatformCreateOptions struct { // Required: A valid operating system string - OS string `jsonapi:"attr,os"` + OS string `jsonapi:"attr,os"` // Required: A valid architecture string - Arch string `jsonapi:"attr,arch"` + Arch string `jsonapi:"attr,arch"` // Required: A valid shasum string - Shasum string `jsonapi:"attr,shasum"` + Shasum string `jsonapi:"attr,shasum"` // Required: A valid filename string Filename string `jsonapi:"attr,filename"` @@ -96,13 +96,13 @@ func (r *registryProviderPlatforms) Create(ctx context.Context, versionID Regist url.QueryEscape(versionID.Name), url.QueryEscape(versionID.Version), ) - req, err := r.client.newRequest("POST", u, &options) + req, err := r.client.NewRequest("POST", u, &options) if err != nil { return nil, err } rpp := &RegistryProviderPlatform{} - err = r.client.do(ctx, req, rpp) + err = req.Do(ctx, rpp) if err != nil { return nil, err } @@ -128,13 +128,13 @@ func (r *registryProviderPlatforms) List(ctx context.Context, versionID Registry url.QueryEscape(versionID.RegistryProviderID.Name), url.QueryEscape(versionID.Version), ) - req, err := r.client.newRequest("GET", u, options) + req, err := r.client.NewRequest("GET", u, options) if err != nil { return nil, err } ppl := &RegistryProviderPlatformList{} - err = r.client.do(ctx, req, ppl) + err = req.Do(ctx, ppl) if err != nil { return nil, err } @@ -159,13 +159,13 @@ func (r *registryProviderPlatforms) Read(ctx context.Context, platformID Registr url.QueryEscape(platformID.OS), url.QueryEscape(platformID.Arch), ) - req, err := r.client.newRequest("GET", u, nil) + req, err := r.client.NewRequest("GET", u, nil) if err != nil { return nil, err } rpp := &RegistryProviderPlatform{} - err = r.client.do(ctx, req, rpp) + err = req.Do(ctx, rpp) if err != nil { return nil, err @@ -191,12 +191,12 @@ func (r *registryProviderPlatforms) Delete(ctx context.Context, platformID Regis url.QueryEscape(platformID.OS), url.QueryEscape(platformID.Arch), ) - req, err := r.client.newRequest("DELETE", u, nil) + req, err := r.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return r.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (id RegistryProviderPlatformID) valid() error { diff --git a/registry_provider_version.go b/registry_provider_version.go index f84554854..57c696156 100644 --- a/registry_provider_version.go +++ b/registry_provider_version.go @@ -74,10 +74,10 @@ type RegistryProviderVersionListOptions struct { type RegistryProviderVersionCreateOptions struct { // Required: A valid semver version string. - Version string `jsonapi:"attr,version"` + Version string `jsonapi:"attr,version"` // Required: A valid gpg-key string. - KeyID string `jsonapi:"attr,key-id"` + KeyID string `jsonapi:"attr,key-id"` // Required: An array of Terraform provider API versions that this version supports. Protocols []string `jsonapi:"attr,protocols"` @@ -99,13 +99,13 @@ func (r *registryProviderVersions) List(ctx context.Context, providerID Registry url.QueryEscape(providerID.Namespace), url.QueryEscape(providerID.Name), ) - req, err := r.client.newRequest("GET", u, options) + req, err := r.client.NewRequest("GET", u, options) if err != nil { return nil, err } pvl := &RegistryProviderVersionList{} - err = r.client.do(ctx, req, pvl) + err = req.Do(ctx, pvl) if err != nil { return nil, err } @@ -134,13 +134,13 @@ func (r *registryProviderVersions) Create(ctx context.Context, providerID Regist url.QueryEscape(providerID.Namespace), url.QueryEscape(providerID.Name), ) - req, err := r.client.newRequest("POST", u, &options) + req, err := r.client.NewRequest("POST", u, &options) if err != nil { return nil, err } prvv := &RegistryProviderVersion{} - err = r.client.do(ctx, req, prvv) + err = req.Do(ctx, prvv) if err != nil { return nil, err } @@ -162,13 +162,13 @@ func (r *registryProviderVersions) Read(ctx context.Context, versionID RegistryP url.QueryEscape(versionID.Name), url.QueryEscape(versionID.Version), ) - req, err := r.client.newRequest("GET", u, nil) + req, err := r.client.NewRequest("GET", u, nil) if err != nil { return nil, err } prvv := &RegistryProviderVersion{} - err = r.client.do(ctx, req, prvv) + err = req.Do(ctx, prvv) if err != nil { return nil, err } @@ -190,12 +190,12 @@ func (r *registryProviderVersions) Delete(ctx context.Context, versionID Registr url.QueryEscape(versionID.Name), url.QueryEscape(versionID.Version), ) - req, err := r.client.newRequest("DELETE", u, nil) + req, err := r.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return r.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // ShasumsUploadURL returns the upload URL to upload shasums if one is available diff --git a/request.go b/request.go new file mode 100644 index 000000000..a84ccfc37 --- /dev/null +++ b/request.go @@ -0,0 +1,104 @@ +package tfe + +import ( + "context" + "encoding/json" + "fmt" + "io" + "net/http" + + retryablehttp "github.com/hashicorp/go-retryablehttp" + "golang.org/x/time/rate" +) + +// ClientRequest encapsulates a request sent by the Client +type ClientRequest struct { + retryableRequest *retryablehttp.Request + http *retryablehttp.Client + limiter *rate.Limiter + + // Header are the headers that will be sent in this request + Header http.Header +} + +func (r ClientRequest) Do(ctx context.Context, model interface{}) error { + // Wait will block until the limiter can obtain a new token + // or returns an error if the given context is canceled. + if err := r.limiter.Wait(ctx); err != nil { + return err + } + + // Add the context to the request. + reqWithCxt := r.retryableRequest.WithContext(ctx) + + // Execute the request and check the response. + resp, err := r.http.Do(reqWithCxt) + if err != nil { + // If we got an error, and the context has been canceled, + // the context's error is probably more useful. + select { + case <-ctx.Done(): + return ctx.Err() + default: + return err + } + } + defer resp.Body.Close() + + // Basic response checking. + if err := checkResponseCode(resp); err != nil { + return err + } + + // Return here if decoding the response isn't needed. + if model == nil { + return nil + } + + // If v implements io.Writer, write the raw response body. + if w, ok := model.(io.Writer); ok { + _, err := io.Copy(w, resp.Body) + return err + } + + return unmarshalResponse(resp.Body, model) +} + +// doIpRanges is similar to Do except that The IP ranges API is not returning jsonapi +// like every other endpoint which means we need to handle it differently. +func (r *ClientRequest) doIpRanges(ctx context.Context, ir *IPRange) error { + // Wait will block until the limiter can obtain a new token + // or returns an error if the given context is canceled. + if err := r.limiter.Wait(ctx); err != nil { + return err + } + + // Add the context to the request. + contextReq := r.retryableRequest.WithContext(ctx) + + // Execute the request and check the response. + resp, err := r.http.Do(contextReq) + if err != nil { + // If we got an error, and the context has been canceled, + // the context's error is probably more useful. + select { + case <-ctx.Done(): + return ctx.Err() + default: + return err + } + } + defer resp.Body.Close() + + if resp.StatusCode < 200 && resp.StatusCode >= 400 { + return fmt.Errorf("error HTTP response while retrieving IP ranges: %d", resp.StatusCode) + } else if resp.StatusCode == 304 { + return nil + } + + err = json.NewDecoder(resp.Body).Decode(ir) + if err != nil { + return err + } + return nil +} diff --git a/run.go b/run.go index 0e67486dc..93b90d890 100644 --- a/run.go +++ b/run.go @@ -325,13 +325,13 @@ func (s *runs) List(ctx context.Context, workspaceID string, options *RunListOpt } u := fmt.Sprintf("workspaces/%s/runs", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } rl := &RunList{} - err = s.client.do(ctx, req, rl) + err = req.Do(ctx, rl) if err != nil { return nil, err } @@ -345,13 +345,13 @@ func (s *runs) Create(ctx context.Context, options RunCreateOptions) (*Run, erro return nil, err } - req, err := s.client.newRequest("POST", "runs", &options) + req, err := s.client.NewRequest("POST", "runs", &options) if err != nil { return nil, err } r := &Run{} - err = s.client.do(ctx, req, r) + err = req.Do(ctx, r) if err != nil { return nil, err } @@ -374,13 +374,13 @@ func (s *runs) ReadWithOptions(ctx context.Context, runID string, options *RunRe } u := fmt.Sprintf("runs/%s", url.QueryEscape(runID)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } r := &Run{} - err = s.client.do(ctx, req, r) + err = req.Do(ctx, r) if err != nil { return nil, err } @@ -395,12 +395,12 @@ func (s *runs) Apply(ctx context.Context, runID string, options RunApplyOptions) } u := fmt.Sprintf("runs/%s/actions/apply", url.QueryEscape(runID)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // Cancel a run by its ID. @@ -410,12 +410,12 @@ func (s *runs) Cancel(ctx context.Context, runID string, options RunCancelOption } u := fmt.Sprintf("runs/%s/actions/cancel", url.QueryEscape(runID)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // ForceCancel is used to forcefully cancel a run by its ID. @@ -425,12 +425,12 @@ func (s *runs) ForceCancel(ctx context.Context, runID string, options RunForceCa } u := fmt.Sprintf("runs/%s/actions/force-cancel", url.QueryEscape(runID)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // Discard a run by its ID. @@ -440,12 +440,12 @@ func (s *runs) Discard(ctx context.Context, runID string, options RunDiscardOpti } u := fmt.Sprintf("runs/%s/actions/discard", url.QueryEscape(runID)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (o RunCreateOptions) valid() error { diff --git a/run_task.go b/run_task.go index ffbaf0d17..d7bb97c7d 100644 --- a/run_task.go +++ b/run_task.go @@ -143,13 +143,13 @@ func (s *runTasks) Create(ctx context.Context, organization string, options RunT } u := fmt.Sprintf("organizations/%s/tasks", url.QueryEscape(organization)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return nil, err } r := &RunTask{} - err = s.client.do(ctx, req, r) + err = req.Do(ctx, r) if err != nil { return nil, err } @@ -167,13 +167,13 @@ func (s *runTasks) List(ctx context.Context, organization string, options *RunTa } u := fmt.Sprintf("organizations/%s/tasks", url.QueryEscape(organization)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } rl := &RunTaskList{} - err = s.client.do(ctx, req, rl) + err = req.Do(ctx, rl) if err != nil { return nil, err } @@ -196,13 +196,13 @@ func (s *runTasks) ReadWithOptions(ctx context.Context, runTaskID string, option } u := fmt.Sprintf("tasks/%s", url.QueryEscape(runTaskID)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } r := &RunTask{} - err = s.client.do(ctx, req, r) + err = req.Do(ctx, r) if err != nil { return nil, err } @@ -221,13 +221,13 @@ func (s *runTasks) Update(ctx context.Context, runTaskID string, options RunTask } u := fmt.Sprintf("tasks/%s", url.QueryEscape(runTaskID)) - req, err := s.client.newRequest("PATCH", u, &options) + req, err := s.client.NewRequest("PATCH", u, &options) if err != nil { return nil, err } r := &RunTask{} - err = s.client.do(ctx, req, r) + err = req.Do(ctx, r) if err != nil { return nil, err } @@ -242,12 +242,12 @@ func (s *runTasks) Delete(ctx context.Context, runTaskID string) error { } u := fmt.Sprintf("tasks/%s", runTaskID) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // AttachToWorkspace is a convenient method to attach a run task to a workspace. See: WorkspaceRunTasks.Create() diff --git a/run_trigger.go b/run_trigger.go index f0c77730c..f16173f5c 100644 --- a/run_trigger.go +++ b/run_trigger.go @@ -101,13 +101,13 @@ func (s *runTriggers) List(ctx context.Context, workspaceID string, options *Run } u := fmt.Sprintf("workspaces/%s/run-triggers", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } rtl := &RunTriggerList{} - err = s.client.do(ctx, req, rtl) + err = req.Do(ctx, rtl) if err != nil { return nil, err } @@ -125,13 +125,13 @@ func (s *runTriggers) Create(ctx context.Context, workspaceID string, options Ru } u := fmt.Sprintf("workspaces/%s/run-triggers", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return nil, err } rt := &RunTrigger{} - err = s.client.do(ctx, req, rt) + err = req.Do(ctx, rt) if err != nil { return nil, err } @@ -146,13 +146,13 @@ func (s *runTriggers) Read(ctx context.Context, runTriggerID string) (*RunTrigge } u := fmt.Sprintf("run-triggers/%s", url.QueryEscape(runTriggerID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } rt := &RunTrigger{} - err = s.client.do(ctx, req, rt) + err = req.Do(ctx, rt) if err != nil { return nil, err } @@ -167,12 +167,12 @@ func (s *runTriggers) Delete(ctx context.Context, runTriggerID string) error { } u := fmt.Sprintf("run-triggers/%s", url.QueryEscape(runTriggerID)) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (o RunTriggerCreateOptions) valid() error { diff --git a/ssh_key.go b/ssh_key.go index d2faea2d4..f4d248bea 100644 --- a/ssh_key.go +++ b/ssh_key.go @@ -84,13 +84,13 @@ func (s *sshKeys) List(ctx context.Context, organization string, options *SSHKey } u := fmt.Sprintf("organizations/%s/ssh-keys", url.QueryEscape(organization)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } kl := &SSHKeyList{} - err = s.client.do(ctx, req, kl) + err = req.Do(ctx, kl) if err != nil { return nil, err } @@ -109,13 +109,13 @@ func (s *sshKeys) Create(ctx context.Context, organization string, options SSHKe } u := fmt.Sprintf("organizations/%s/ssh-keys", url.QueryEscape(organization)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return nil, err } k := &SSHKey{} - err = s.client.do(ctx, req, k) + err = req.Do(ctx, k) if err != nil { return nil, err } @@ -130,13 +130,13 @@ func (s *sshKeys) Read(ctx context.Context, sshKeyID string) (*SSHKey, error) { } u := fmt.Sprintf("ssh-keys/%s", url.QueryEscape(sshKeyID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } k := &SSHKey{} - err = s.client.do(ctx, req, k) + err = req.Do(ctx, k) if err != nil { return nil, err } @@ -151,13 +151,13 @@ func (s *sshKeys) Update(ctx context.Context, sshKeyID string, options SSHKeyUpd } u := fmt.Sprintf("ssh-keys/%s", url.QueryEscape(sshKeyID)) - req, err := s.client.newRequest("PATCH", u, &options) + req, err := s.client.NewRequest("PATCH", u, &options) if err != nil { return nil, err } k := &SSHKey{} - err = s.client.do(ctx, req, k) + err = req.Do(ctx, k) if err != nil { return nil, err } @@ -172,12 +172,12 @@ func (s *sshKeys) Delete(ctx context.Context, sshKeyID string) error { } u := fmt.Sprintf("ssh-keys/%s", url.QueryEscape(sshKeyID)) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (o SSHKeyCreateOptions) valid() error { diff --git a/state_version.go b/state_version.go index 225e0a3e0..078d3e177 100644 --- a/state_version.go +++ b/state_version.go @@ -154,13 +154,13 @@ func (s *stateVersions) List(ctx context.Context, options *StateVersionListOptio return nil, err } - req, err := s.client.newRequest("GET", "state-versions", options) + req, err := s.client.NewRequest("GET", "state-versions", options) if err != nil { return nil, err } svl := &StateVersionList{} - err = s.client.do(ctx, req, svl) + err = req.Do(ctx, svl) if err != nil { return nil, err } @@ -178,13 +178,13 @@ func (s *stateVersions) Create(ctx context.Context, workspaceID string, options } u := fmt.Sprintf("workspaces/%s/state-versions", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return nil, err } sv := &StateVersion{} - err = s.client.do(ctx, req, sv) + err = req.Do(ctx, sv) if err != nil { return nil, err } @@ -202,13 +202,13 @@ func (s *stateVersions) ReadWithOptions(ctx context.Context, svID string, option } u := fmt.Sprintf("state-versions/%s", url.QueryEscape(svID)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } sv := &StateVersion{} - err = s.client.do(ctx, req, sv) + err = req.Do(ctx, sv) if err != nil { return nil, err } @@ -231,13 +231,13 @@ func (s *stateVersions) ReadCurrentWithOptions(ctx context.Context, workspaceID } u := fmt.Sprintf("workspaces/%s/current-state-version", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } sv := &StateVersion{} - err = s.client.do(ctx, req, sv) + err = req.Do(ctx, sv) if err != nil { return nil, err } @@ -252,14 +252,14 @@ func (s *stateVersions) ReadCurrent(ctx context.Context, workspaceID string) (*S // Download retrieves the actual stored state of a state version func (s *stateVersions) Download(ctx context.Context, u string) ([]byte, error) { - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } req.Header.Set("Accept", "application/json") var buf bytes.Buffer - err = s.client.do(ctx, req, &buf) + err = req.Do(ctx, &buf) if err != nil { return nil, err } @@ -274,13 +274,13 @@ func (s *stateVersions) ListOutputs(ctx context.Context, svID string, options *S } u := fmt.Sprintf("state-versions/%s/outputs", url.QueryEscape(svID)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } sv := &StateVersionOutputsList{} - err = s.client.do(ctx, req, sv) + err = req.Do(ctx, sv) if err != nil { return nil, err } diff --git a/state_version_output.go b/state_version_output.go index e6a86cbed..47ac71335 100644 --- a/state_version_output.go +++ b/state_version_output.go @@ -40,13 +40,13 @@ func (s *stateVersionOutputs) ReadCurrent(ctx context.Context, workspaceID strin } u := fmt.Sprintf("workspaces/%s/current-state-version-outputs", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } so := &StateVersionOutputsList{} - err = s.client.do(ctx, req, so) + err = req.Do(ctx, so) if err != nil { return nil, err } @@ -61,13 +61,13 @@ func (s *stateVersionOutputs) Read(ctx context.Context, outputID string) (*State } u := fmt.Sprintf("state-version-outputs/%s", url.QueryEscape(outputID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } so := &StateVersionOutput{} - err = s.client.do(ctx, req, so) + err = req.Do(ctx, so) if err != nil { return nil, err } diff --git a/task_result.go b/task_result.go index 4abc36706..b7676b6db 100644 --- a/task_result.go +++ b/task_result.go @@ -75,13 +75,13 @@ func (t *taskResults) Read(ctx context.Context, taskResultID string) (*TaskResul } u := fmt.Sprintf("task-results/%s", taskResultID) - req, err := t.client.newRequest("GET", u, nil) + req, err := t.client.NewRequest("GET", u, nil) if err != nil { return nil, err } r := &TaskResult{} - err = t.client.do(ctx, req, r) + err = req.Do(ctx, r) if err != nil { return nil, err } diff --git a/task_stages.go b/task_stages.go index d6699a452..4c659deb9 100644 --- a/task_stages.go +++ b/task_stages.go @@ -85,13 +85,13 @@ func (s *taskStages) Read(ctx context.Context, taskStageID string, options *Task } u := fmt.Sprintf("task-stages/%s", taskStageID) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } t := &TaskStage{} - err = s.client.do(ctx, req, t) + err = req.Do(ctx, t) if err != nil { return nil, err } @@ -106,14 +106,14 @@ func (s *taskStages) List(ctx context.Context, runID string, options *TaskStageL } u := fmt.Sprintf("runs/%s/task-stages", runID) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } tlist := &TaskStageList{} - err = s.client.do(ctx, req, tlist) + err = req.Do(ctx, tlist) if err != nil { return nil, err } diff --git a/team.go b/team.go index a9c08244a..1e31380a9 100644 --- a/team.go +++ b/team.go @@ -155,13 +155,13 @@ func (s *teams) List(ctx context.Context, organization string, options *TeamList return nil, err } u := fmt.Sprintf("organizations/%s/teams", url.QueryEscape(organization)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } tl := &TeamList{} - err = s.client.do(ctx, req, tl) + err = req.Do(ctx, tl) if err != nil { return nil, err } @@ -179,13 +179,13 @@ func (s *teams) Create(ctx context.Context, organization string, options TeamCre } u := fmt.Sprintf("organizations/%s/teams", url.QueryEscape(organization)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return nil, err } t := &Team{} - err = s.client.do(ctx, req, t) + err = req.Do(ctx, t) if err != nil { return nil, err } @@ -200,13 +200,13 @@ func (s *teams) Read(ctx context.Context, teamID string) (*Team, error) { } u := fmt.Sprintf("teams/%s", url.QueryEscape(teamID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } t := &Team{} - err = s.client.do(ctx, req, t) + err = req.Do(ctx, t) if err != nil { return nil, err } @@ -221,13 +221,13 @@ func (s *teams) Update(ctx context.Context, teamID string, options TeamUpdateOpt } u := fmt.Sprintf("teams/%s", url.QueryEscape(teamID)) - req, err := s.client.newRequest("PATCH", u, &options) + req, err := s.client.NewRequest("PATCH", u, &options) if err != nil { return nil, err } t := &Team{} - err = s.client.do(ctx, req, t) + err = req.Do(ctx, t) if err != nil { return nil, err } @@ -242,12 +242,12 @@ func (s *teams) Delete(ctx context.Context, teamID string) error { } u := fmt.Sprintf("teams/%s", url.QueryEscape(teamID)) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (o TeamCreateOptions) valid() error { diff --git a/team_access.go b/team_access.go index 0f56b3ebe..d1c380923 100644 --- a/team_access.go +++ b/team_access.go @@ -165,13 +165,13 @@ func (s *teamAccesses) List(ctx context.Context, options *TeamAccessListOptions) return nil, err } - req, err := s.client.newRequest("GET", "team-workspaces", options) + req, err := s.client.NewRequest("GET", "team-workspaces", options) if err != nil { return nil, err } tal := &TeamAccessList{} - err = s.client.do(ctx, req, tal) + err = req.Do(ctx, tal) if err != nil { return nil, err } @@ -185,13 +185,13 @@ func (s *teamAccesses) Add(ctx context.Context, options TeamAccessAddOptions) (* return nil, err } - req, err := s.client.newRequest("POST", "team-workspaces", &options) + req, err := s.client.NewRequest("POST", "team-workspaces", &options) if err != nil { return nil, err } ta := &TeamAccess{} - err = s.client.do(ctx, req, ta) + err = req.Do(ctx, ta) if err != nil { return nil, err } @@ -206,13 +206,13 @@ func (s *teamAccesses) Read(ctx context.Context, teamAccessID string) (*TeamAcce } u := fmt.Sprintf("team-workspaces/%s", url.QueryEscape(teamAccessID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } ta := &TeamAccess{} - err = s.client.do(ctx, req, ta) + err = req.Do(ctx, ta) if err != nil { return nil, err } @@ -227,13 +227,13 @@ func (s *teamAccesses) Update(ctx context.Context, teamAccessID string, options } u := fmt.Sprintf("team-workspaces/%s", url.QueryEscape(teamAccessID)) - req, err := s.client.newRequest("PATCH", u, &options) + req, err := s.client.NewRequest("PATCH", u, &options) if err != nil { return nil, err } ta := &TeamAccess{} - err = s.client.do(ctx, req, ta) + err = req.Do(ctx, ta) if err != nil { return nil, err } @@ -248,12 +248,12 @@ func (s *teamAccesses) Remove(ctx context.Context, teamAccessID string) error { } u := fmt.Sprintf("team-workspaces/%s", url.QueryEscape(teamAccessID)) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (o *TeamAccessListOptions) valid() error { diff --git a/team_member.go b/team_member.go index c52c60161..06c6eba1f 100644 --- a/team_member.go +++ b/team_member.go @@ -4,8 +4,6 @@ import ( "context" "fmt" "net/url" - - retryablehttp "github.com/hashicorp/go-retryablehttp" ) // Compile-time proof of interface implementation. @@ -80,13 +78,13 @@ func (s *teamMembers) ListUsers(ctx context.Context, teamID string) ([]*User, er } u := fmt.Sprintf("teams/%s", url.QueryEscape(teamID)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } t := &Team{} - err = s.client.do(ctx, req, t) + err = req.Do(ctx, t) if err != nil { return nil, err } @@ -107,13 +105,13 @@ func (s *teamMembers) ListOrganizationMemberships(ctx context.Context, teamID st } u := fmt.Sprintf("teams/%s", url.QueryEscape(teamID)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } t := &Team{} - err = s.client.do(ctx, req, t) + err = req.Do(ctx, t) if err != nil { return nil, err } @@ -133,7 +131,7 @@ func (s *teamMembers) Add(ctx context.Context, teamID string, options TeamMember usersOrMemberships := options.kind() u := fmt.Sprintf("teams/%s/relationships/%s", url.QueryEscape(teamID), usersOrMemberships) - var req *retryablehttp.Request + var req *ClientRequest if usersOrMemberships == "users" { var err error @@ -141,7 +139,7 @@ func (s *teamMembers) Add(ctx context.Context, teamID string, options TeamMember for _, name := range options.Usernames { members = append(members, &teamMemberUser{Username: name}) } - req, err = s.client.newRequest("POST", u, members) + req, err = s.client.NewRequest("POST", u, members) if err != nil { return err } @@ -151,13 +149,13 @@ func (s *teamMembers) Add(ctx context.Context, teamID string, options TeamMember for _, ID := range options.OrganizationMembershipIDs { members = append(members, &teamMemberOrgMembership{ID: ID}) } - req, err = s.client.newRequest("POST", u, members) + req, err = s.client.NewRequest("POST", u, members) if err != nil { return err } } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // Remove multiple users from a team. @@ -172,7 +170,7 @@ func (s *teamMembers) Remove(ctx context.Context, teamID string, options TeamMem usersOrMemberships := options.kind() u := fmt.Sprintf("teams/%s/relationships/%s", url.QueryEscape(teamID), usersOrMemberships) - var req *retryablehttp.Request + var req *ClientRequest if usersOrMemberships == "users" { var err error @@ -180,7 +178,7 @@ func (s *teamMembers) Remove(ctx context.Context, teamID string, options TeamMem for _, name := range options.Usernames { members = append(members, &teamMemberUser{Username: name}) } - req, err = s.client.newRequest("DELETE", u, members) + req, err = s.client.NewRequest("DELETE", u, members) if err != nil { return err } @@ -190,13 +188,13 @@ func (s *teamMembers) Remove(ctx context.Context, teamID string, options TeamMem for _, ID := range options.OrganizationMembershipIDs { members = append(members, &teamMemberOrgMembership{ID: ID}) } - req, err = s.client.newRequest("DELETE", u, members) + req, err = s.client.NewRequest("DELETE", u, members) if err != nil { return err } } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // kind returns "users" or "organization-memberships" diff --git a/team_token.go b/team_token.go index d299f93c8..e350b1119 100644 --- a/team_token.go +++ b/team_token.go @@ -47,13 +47,13 @@ func (s *teamTokens) Create(ctx context.Context, teamID string) (*TeamToken, err } u := fmt.Sprintf("teams/%s/authentication-token", url.QueryEscape(teamID)) - req, err := s.client.newRequest("POST", u, nil) + req, err := s.client.NewRequest("POST", u, nil) if err != nil { return nil, err } tt := &TeamToken{} - err = s.client.do(ctx, req, tt) + err = req.Do(ctx, tt) if err != nil { return nil, err } @@ -68,13 +68,13 @@ func (s *teamTokens) Read(ctx context.Context, teamID string) (*TeamToken, error } u := fmt.Sprintf("teams/%s/authentication-token", url.QueryEscape(teamID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } tt := &TeamToken{} - err = s.client.do(ctx, req, tt) + err = req.Do(ctx, tt) if err != nil { return nil, err } @@ -89,10 +89,10 @@ func (s *teamTokens) Delete(ctx context.Context, teamID string) error { } u := fmt.Sprintf("teams/%s/authentication-token", url.QueryEscape(teamID)) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } diff --git a/testing.go b/testing.go index 66485fb56..63e392f36 100644 --- a/testing.go +++ b/testing.go @@ -22,7 +22,7 @@ type TestAccountDetails struct { // address associated with the token used to run the tests. func FetchTestAccountDetails(t *testing.T, client *Client) *TestAccountDetails { tad := &TestAccountDetails{} - req, err := client.newRequest("GET", "account/details", nil) + req, err := client.NewRequest("GET", "account/details", nil) if err != nil { t.Fatalf("could not create account details request: %v", err) } diff --git a/tfe.go b/tfe.go index 953ac6bfc..fb63406bc 100644 --- a/tfe.go +++ b/tfe.go @@ -183,6 +183,75 @@ type Meta struct { IPRanges IPRanges } +func (c *Client) NewRequest(method, path string, reqAttr interface{}) (*ClientRequest, error) { + var u *url.URL + var err error + if strings.Contains(path, "/api/registry/") { + u, err = c.registryBaseURL.Parse(path) + if err != nil { + return nil, err + } + } else { + u, err = c.baseURL.Parse(path) + if err != nil { + return nil, err + } + } + + // Create a request specific headers map. + reqHeaders := make(http.Header) + reqHeaders.Set("Authorization", "Bearer "+c.token) + + var body interface{} + switch method { + case "GET": + reqHeaders.Set("Accept", "application/vnd.api+json") + + if reqAttr != nil { + q, err := query.Values(reqAttr) + if err != nil { + return nil, err + } + u.RawQuery = encodeQueryParams(q) + } + case "DELETE", "PATCH", "POST": + reqHeaders.Set("Accept", "application/vnd.api+json") + reqHeaders.Set("Content-Type", "application/vnd.api+json") + + if reqAttr != nil { + if body, err = serializeRequestBody(reqAttr); err != nil { + return nil, err + } + } + case "PUT": + reqHeaders.Set("Accept", "application/json") + reqHeaders.Set("Content-Type", "application/octet-stream") + body = reqAttr + } + + req, err := retryablehttp.NewRequest(method, u.String(), body) + if err != nil { + return nil, err + } + + // Set the default headers. + for k, v := range c.headers { + req.Header[k] = v + } + + // Set the request specific headers. + for k, v := range reqHeaders { + req.Header[k] = v + } + + return &ClientRequest{ + retryableRequest: req, + http: c.http, + limiter: c.limiter, + Header: req.Header, + }, nil +} + // NewClient creates a new Terraform Enterprise API client. func NewClient(cfg *Config) (*Client, error) { config := DefaultConfig() @@ -508,82 +577,8 @@ func (c *Client) configureLimiter(rawLimit string) { c.limiter = rate.NewLimiter(limit, burst) } -// newRequest creates an API request with proper headers and serialization. -// -// A relative URL path can be provided, in which case it is resolved relative to the baseURL -// of the Client. Relative URL paths should always be specified without a preceding slash. Adding a -// preceding slash allows for ignoring the configured baseURL for non-standard endpoints. -// -// If v is supplied, the value will be JSONAPI encoded and included as the -// request body. If the method is GET, the value will be parsed and added as -// query parameters. -func (c *Client) newRequest(method, path string, v interface{}) (*retryablehttp.Request, error) { - var u *url.URL - var err error - if strings.Contains(path, "/api/registry/") { - u, err = c.registryBaseURL.Parse(path) - if err != nil { - return nil, err - } - } else { - u, err = c.baseURL.Parse(path) - if err != nil { - return nil, err - } - } - - // Create a request specific headers map. - reqHeaders := make(http.Header) - reqHeaders.Set("Authorization", "Bearer "+c.token) - - var body interface{} - switch method { - case "GET": - reqHeaders.Set("Accept", "application/vnd.api+json") - - if v != nil { - q, err := query.Values(v) - if err != nil { - return nil, err - } - u.RawQuery = encodeQueryParams(q) - } - case "DELETE", "PATCH", "POST": - reqHeaders.Set("Accept", "application/vnd.api+json") - reqHeaders.Set("Content-Type", "application/vnd.api+json") - - if v != nil { - if body, err = serializeRequestBody(v); err != nil { - return nil, err - } - } - case "PUT": - reqHeaders.Set("Accept", "application/json") - reqHeaders.Set("Content-Type", "application/octet-stream") - body = v - } - - req, err := retryablehttp.NewRequest(method, u.String(), body) - if err != nil { - return nil, err - } - - // Set the default headers. - for k, v := range c.headers { - req.Header[k] = v - } - - // Set the request specific headers. - for k, v := range reqHeaders { - req.Header[k] = v - } - - return req, nil -} - -// Encode encodes the values into ``URL encoded'' form +// encodeQueryParams encodes the values into ``URL encoded'' form // ("bar=baz&foo=quux") sorted by key. - func encodeQueryParams(v url.Values) string { if v == nil { return "" @@ -615,10 +610,9 @@ func encodeQueryParams(v url.Values) string { return buf.String() } -// Helper method that serializes the given ptr or ptr slice into a JSON +// serializeRequestBody serializes the given ptr or ptr slice into a JSON // request. It automatically uses jsonapi or json serialization, depending // on the body type's tags. - func serializeRequestBody(v interface{}) (interface{}, error) { // The body can be a slice of pointers or a pointer. In either // case we want to choose the serialization type based on the @@ -673,99 +667,6 @@ func serializeRequestBody(v interface{}) (interface{}, error) { return buf, nil } -// do sends an API request and returns the API response. The API response -// is JSONAPI decoded and the document's primary data is stored in the value -// pointed to by v, or returned as an error if an API error has occurred. - -// If v implements the io.Writer interface, the raw response body will be -// written to v, without attempting to first decode it. -// -// The provided ctx must be non-nil. If it is canceled or times out, ctx.Err() -// will be returned. - -func (c *Client) do(ctx context.Context, req *retryablehttp.Request, v interface{}) error { - // Wait will block until the limiter can obtain a new token - // or returns an error if the given context is canceled. - if err := c.limiter.Wait(ctx); err != nil { - return err - } - - // Add the context to the request. - reqWithCxt := req.WithContext(ctx) - - // Execute the request and check the response. - resp, err := c.http.Do(reqWithCxt) - if err != nil { - // If we got an error, and the context has been canceled, - // the context's error is probably more useful. - select { - case <-ctx.Done(): - return ctx.Err() - default: - return err - } - } - defer resp.Body.Close() - - // Basic response checking. - if err := checkResponseCode(resp); err != nil { - return err - } - - // Return here if decoding the response isn't needed. - if v == nil { - return nil - } - - // If v implements io.Writer, write the raw response body. - if w, ok := v.(io.Writer); ok { - _, err := io.Copy(w, resp.Body) - return err - } - - return unmarshalResponse(resp.Body, v) -} - -// customDo is similar to func (c *Client) do(ctx context.Context, req *retryablehttp.Request, v interface{}) error. Except that The IP ranges API is not returning jsonapi like every other endpoint -// which means we need to handle it differently. - -func (i *ipRanges) customDo(ctx context.Context, req *retryablehttp.Request, ir *IPRange) error { - // Wait will block until the limiter can obtain a new token - // or returns an error if the given context is canceled. - if err := i.client.limiter.Wait(ctx); err != nil { - return err - } - - // Add the context to the request. - req = req.WithContext(ctx) - - // Execute the request and check the response. - resp, err := i.client.http.Do(req) - if err != nil { - // If we got an error, and the context has been canceled, - // the context's error is probably more useful. - select { - case <-ctx.Done(): - return ctx.Err() - default: - return err - } - } - defer resp.Body.Close() - - if resp.StatusCode < 200 && resp.StatusCode >= 400 { - return fmt.Errorf("error HTTP response while retrieving IP ranges: %d", resp.StatusCode) - } else if resp.StatusCode == 304 { - return nil - } - - err = json.NewDecoder(resp.Body).Decode(ir) - if err != nil { - return err - } - return nil -} - func unmarshalResponse(responseBody io.Reader, model interface{}) error { // Get the value of model so we can test if it's a struct. dst := reflect.Indirect(reflect.ValueOf(model)) diff --git a/tfe_integration_test.go b/tfe_integration_test.go index c57a642f8..b574d66d9 100644 --- a/tfe_integration_test.go +++ b/tfe_integration_test.go @@ -379,15 +379,15 @@ func createRequest(v interface{}) (*retryablehttp.Request, []byte, error) { return nil, nil, err } - request, err := client.newRequest("POST", "/bar", v) + request, err := client.NewRequest("POST", "/bar", v) if err != nil { return nil, nil, err } - body, err := request.BodyBytes() + body, err := request.retryableRequest.BodyBytes() if err != nil { - return request, nil, err + return request.retryableRequest, nil, err } - return request, body, nil + return request.retryableRequest, body, nil } func TestClient_configureLimiter(t *testing.T) { diff --git a/tfe_test.go b/tfe_test.go index eef419463..1fe614cf8 100644 --- a/tfe_test.go +++ b/tfe_test.go @@ -141,10 +141,10 @@ func Test_RegistryBasePath(t *testing.T) { t.Run("ensures client creates a request with registry base path", func(t *testing.T) { path := "/api/registry/some/path/to/resource" - req, err := client.newRequest("GET", path, nil) + req, err := client.NewRequest("GET", path, nil) require.NoError(t, err) expected := os.Getenv("TFE_ADDRESS") + path - assert.Equal(t, req.URL.String(), expected) + assert.Equal(t, req.retryableRequest.URL.String(), expected) }) } diff --git a/user.go b/user.go index 0795f5032..f7b8f5b3c 100644 --- a/user.go +++ b/user.go @@ -62,13 +62,13 @@ type UserUpdateOptions struct { // ReadCurrent reads the details of the currently authenticated user. func (s *users) ReadCurrent(ctx context.Context) (*User, error) { - req, err := s.client.newRequest("GET", "account/details", nil) + req, err := s.client.NewRequest("GET", "account/details", nil) if err != nil { return nil, err } u := &User{} - err = s.client.do(ctx, req, u) + err = req.Do(ctx, u) if err != nil { return nil, err } @@ -78,13 +78,13 @@ func (s *users) ReadCurrent(ctx context.Context) (*User, error) { // UpdateCurrent updates attributes of the currently authenticated user. func (s *users) UpdateCurrent(ctx context.Context, options UserUpdateOptions) (*User, error) { - req, err := s.client.newRequest("PATCH", "account/update", &options) + req, err := s.client.NewRequest("PATCH", "account/update", &options) if err != nil { return nil, err } u := &User{} - err = s.client.do(ctx, req, u) + err = req.Do(ctx, u) if err != nil { return nil, err } diff --git a/user_token.go b/user_token.go index 56de5b859..d27feacd4 100644 --- a/user_token.go +++ b/user_token.go @@ -62,13 +62,13 @@ func (s *userTokens) Create(ctx context.Context, userID string, options UserToke } u := fmt.Sprintf("users/%s/authentication-tokens", url.QueryEscape(userID)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return nil, err } ut := &UserToken{} - err = s.client.do(ctx, req, ut) + err = req.Do(ctx, ut) if err != nil { return nil, err } @@ -83,13 +83,13 @@ func (s *userTokens) List(ctx context.Context, userID string) (*UserTokenList, e } u := fmt.Sprintf("users/%s/authentication-tokens", url.QueryEscape(userID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } tl := &UserTokenList{} - err = s.client.do(ctx, req, tl) + err = req.Do(ctx, tl) if err != nil { return nil, err } @@ -104,13 +104,13 @@ func (s *userTokens) Read(ctx context.Context, tokenID string) (*UserToken, erro } u := fmt.Sprintf("authentication-tokens/%s", url.QueryEscape(tokenID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } tt := &UserToken{} - err = s.client.do(ctx, req, tt) + err = req.Do(ctx, tt) if err != nil { return nil, err } @@ -125,10 +125,10 @@ func (s *userTokens) Delete(ctx context.Context, tokenID string) error { } u := fmt.Sprintf("authentication-tokens/%s", url.QueryEscape(tokenID)) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } diff --git a/variable.go b/variable.go index 53ea17458..c18975a8e 100644 --- a/variable.go +++ b/variable.go @@ -131,13 +131,13 @@ func (s *variables) List(ctx context.Context, workspaceID string, options *Varia } u := fmt.Sprintf("workspaces/%s/vars", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } vl := &VariableList{} - err = s.client.do(ctx, req, vl) + err = req.Do(ctx, vl) if err != nil { return nil, err } @@ -155,13 +155,13 @@ func (s *variables) Create(ctx context.Context, workspaceID string, options Vari } u := fmt.Sprintf("workspaces/%s/vars", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return nil, err } v := &Variable{} - err = s.client.do(ctx, req, v) + err = req.Do(ctx, v) if err != nil { return nil, err } @@ -179,13 +179,13 @@ func (s *variables) Read(ctx context.Context, workspaceID, variableID string) (* } u := fmt.Sprintf("workspaces/%s/vars/%s", url.QueryEscape(workspaceID), url.QueryEscape(variableID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } v := &Variable{} - err = s.client.do(ctx, req, v) + err = req.Do(ctx, v) if err != nil { return nil, err } @@ -203,13 +203,13 @@ func (s *variables) Update(ctx context.Context, workspaceID, variableID string, } u := fmt.Sprintf("workspaces/%s/vars/%s", url.QueryEscape(workspaceID), url.QueryEscape(variableID)) - req, err := s.client.newRequest("PATCH", u, &options) + req, err := s.client.NewRequest("PATCH", u, &options) if err != nil { return nil, err } v := &Variable{} - err = s.client.do(ctx, req, v) + err = req.Do(ctx, v) if err != nil { return nil, err } @@ -227,12 +227,12 @@ func (s *variables) Delete(ctx context.Context, workspaceID, variableID string) } u := fmt.Sprintf("workspaces/%s/vars/%s", url.QueryEscape(workspaceID), url.QueryEscape(variableID)) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (o VariableCreateOptions) valid() error { diff --git a/variable_set.go b/variable_set.go index d666dae66..3a9a1f9ec 100644 --- a/variable_set.go +++ b/variable_set.go @@ -165,13 +165,13 @@ func (s *variableSets) List(ctx context.Context, organization string, options *V } u := fmt.Sprintf("organizations/%s/varsets", url.QueryEscape(organization)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } vl := &VariableSetList{} - err = s.client.do(ctx, req, vl) + err = req.Do(ctx, vl) if err != nil { return nil, err } @@ -189,13 +189,13 @@ func (s *variableSets) Create(ctx context.Context, organization string, options } u := fmt.Sprintf("organizations/%s/varsets", url.QueryEscape(organization)) - req, err := s.client.newRequest("POST", u, options) + req, err := s.client.NewRequest("POST", u, options) if err != nil { return nil, err } vl := &VariableSet{} - err = s.client.do(ctx, req, vl) + err = req.Do(ctx, vl) if err != nil { return nil, err } @@ -210,13 +210,13 @@ func (s *variableSets) Read(ctx context.Context, variableSetID string, options * } u := fmt.Sprintf("varsets/%s", url.QueryEscape(variableSetID)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } vs := &VariableSet{} - err = s.client.do(ctx, req, vs) + err = req.Do(ctx, vs) if err != nil { return nil, err } @@ -231,13 +231,13 @@ func (s *variableSets) Update(ctx context.Context, variableSetID string, options } u := fmt.Sprintf("varsets/%s", url.QueryEscape(variableSetID)) - req, err := s.client.newRequest("PATCH", u, options) + req, err := s.client.NewRequest("PATCH", u, options) if err != nil { return nil, err } v := &VariableSet{} - err = s.client.do(ctx, req, v) + err = req.Do(ctx, v) if err != nil { return nil, err } @@ -252,12 +252,12 @@ func (s *variableSets) Delete(ctx context.Context, variableSetID string) error { } u := fmt.Sprintf("varsets/%s", url.QueryEscape(variableSetID)) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // Apply variable set to workspaces in the supplied list. @@ -271,12 +271,12 @@ func (s *variableSets) ApplyToWorkspaces(ctx context.Context, variableSetID stri } u := fmt.Sprintf("varsets/%s/relationships/workspaces", url.QueryEscape(variableSetID)) - req, err := s.client.newRequest("POST", u, options.Workspaces) + req, err := s.client.NewRequest("POST", u, options.Workspaces) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // Remove variable set from workspaces in the supplied list. @@ -290,12 +290,12 @@ func (s *variableSets) RemoveFromWorkspaces(ctx context.Context, variableSetID s } u := fmt.Sprintf("varsets/%s/relationships/workspaces", url.QueryEscape(variableSetID)) - req, err := s.client.newRequest("DELETE", u, options.Workspaces) + req, err := s.client.NewRequest("DELETE", u, options.Workspaces) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // Update variable set to be applied to only the workspaces in the supplied list. @@ -312,13 +312,13 @@ func (s *variableSets) UpdateWorkspaces(ctx context.Context, variableSetID strin // We force inclusion of workspaces as that is the primary data for which we are concerned with confirming changes. u := fmt.Sprintf("varsets/%s?include=%s", url.QueryEscape(variableSetID), VariableSetWorkspaces) - req, err := s.client.newRequest("PATCH", u, &o) + req, err := s.client.NewRequest("PATCH", u, &o) if err != nil { return nil, err } v := &VariableSet{} - err = s.client.do(ctx, req, v) + err = req.Do(ctx, v) if err != nil { return nil, err } diff --git a/variable_set_variable.go b/variable_set_variable.go index dea5835ff..5f98399c7 100644 --- a/variable_set_variable.go +++ b/variable_set_variable.go @@ -72,13 +72,13 @@ func (s *variableSetVariables) List(ctx context.Context, variableSetID string, o } u := fmt.Sprintf("varsets/%s/relationships/vars", url.QueryEscape(variableSetID)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } vl := &VariableSetVariableList{} - err = s.client.do(ctx, req, vl) + err = req.Do(ctx, vl) if err != nil { return nil, err } @@ -135,13 +135,13 @@ func (s *variableSetVariables) Create(ctx context.Context, variableSetID string, } u := fmt.Sprintf("varsets/%s/relationships/vars", url.QueryEscape(variableSetID)) - req, err := s.client.newRequest("POST", u, options) + req, err := s.client.NewRequest("POST", u, options) if err != nil { return nil, err } v := &VariableSetVariable{} - err = s.client.do(ctx, req, v) + err = req.Do(ctx, v) if err != nil { return nil, err } @@ -159,14 +159,14 @@ func (s *variableSetVariables) Read(ctx context.Context, variableSetID, variable } u := fmt.Sprintf("varsets/%s/relationships/vars/%s", url.QueryEscape(variableSetID), url.QueryEscape(variableID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } v := &VariableSetVariable{} - err = s.client.do(ctx, req, v) + err = req.Do(ctx, v) if err != nil { return nil, err } @@ -208,13 +208,13 @@ func (s *variableSetVariables) Update(ctx context.Context, variableSetID, variab } u := fmt.Sprintf("varsets/%s/relationships/vars/%s", url.QueryEscape(variableSetID), url.QueryEscape(variableID)) - req, err := s.client.newRequest("PATCH", u, options) + req, err := s.client.NewRequest("PATCH", u, options) if err != nil { return nil, err } v := &VariableSetVariable{} - err = s.client.do(ctx, req, v) + err = req.Do(ctx, v) if err != nil { return nil, err } @@ -232,10 +232,10 @@ func (s *variableSetVariables) Delete(ctx context.Context, variableSetID, variab } u := fmt.Sprintf("varsets/%s/relationships/vars/%s", url.QueryEscape(variableSetID), url.QueryEscape(variableID)) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } diff --git a/workspace.go b/workspace.go index eb8f9c9b8..a24ff345a 100644 --- a/workspace.go +++ b/workspace.go @@ -536,13 +536,13 @@ func (s *workspaces) List(ctx context.Context, organization string, options *Wor } u := fmt.Sprintf("organizations/%s/workspaces", url.QueryEscape(organization)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } wl := &WorkspaceList{} - err = s.client.do(ctx, req, wl) + err = req.Do(ctx, wl) if err != nil { return nil, err } @@ -560,13 +560,13 @@ func (s *workspaces) Create(ctx context.Context, organization string, options Wo } u := fmt.Sprintf("organizations/%s/workspaces", url.QueryEscape(organization)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return nil, err } w := &Workspace{} - err = s.client.do(ctx, req, w) + err = req.Do(ctx, w) if err != nil { return nil, err } @@ -596,13 +596,13 @@ func (s *workspaces) ReadWithOptions(ctx context.Context, organization, workspac url.QueryEscape(organization), url.QueryEscape(workspace), ) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } w := &Workspace{} - err = s.client.do(ctx, req, w) + err = req.Do(ctx, w) if err != nil { return nil, err } @@ -626,13 +626,13 @@ func (s *workspaces) ReadByIDWithOptions(ctx context.Context, workspaceID string } u := fmt.Sprintf("workspaces/%s", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } w := &Workspace{} - err = s.client.do(ctx, req, w) + err = req.Do(ctx, w) if err != nil { return nil, err } @@ -651,13 +651,13 @@ func (s *workspaces) Readme(ctx context.Context, workspaceID string) (io.Reader, } u := fmt.Sprintf("workspaces/%s?include=readme", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } r := &workspaceWithReadme{} - err = s.client.do(ctx, req, r) + err = req.Do(ctx, r) if err != nil { return nil, err } @@ -685,13 +685,13 @@ func (s *workspaces) Update(ctx context.Context, organization, workspace string, url.QueryEscape(organization), url.QueryEscape(workspace), ) - req, err := s.client.newRequest("PATCH", u, &options) + req, err := s.client.NewRequest("PATCH", u, &options) if err != nil { return nil, err } w := &Workspace{} - err = s.client.do(ctx, req, w) + err = req.Do(ctx, w) if err != nil { return nil, err } @@ -706,13 +706,13 @@ func (s *workspaces) UpdateByID(ctx context.Context, workspaceID string, options } u := fmt.Sprintf("workspaces/%s", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("PATCH", u, &options) + req, err := s.client.NewRequest("PATCH", u, &options) if err != nil { return nil, err } w := &Workspace{} - err = s.client.do(ctx, req, w) + err = req.Do(ctx, w) if err != nil { return nil, err } @@ -734,12 +734,12 @@ func (s *workspaces) Delete(ctx context.Context, organization, workspace string) url.QueryEscape(organization), url.QueryEscape(workspace), ) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // DeleteByID deletes a workspace by its ID. @@ -749,12 +749,12 @@ func (s *workspaces) DeleteByID(ctx context.Context, workspaceID string) error { } u := fmt.Sprintf("workspaces/%s", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // RemoveVCSConnection from a workspace. @@ -772,13 +772,13 @@ func (s *workspaces) RemoveVCSConnection(ctx context.Context, organization, work url.QueryEscape(workspace), ) - req, err := s.client.newRequest("PATCH", u, &workspaceRemoveVCSConnectionOptions{}) + req, err := s.client.NewRequest("PATCH", u, &workspaceRemoveVCSConnectionOptions{}) if err != nil { return nil, err } w := &Workspace{} - err = s.client.do(ctx, req, w) + err = req.Do(ctx, w) if err != nil { return nil, err } @@ -794,13 +794,13 @@ func (s *workspaces) RemoveVCSConnectionByID(ctx context.Context, workspaceID st u := fmt.Sprintf("workspaces/%s", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("PATCH", u, &workspaceRemoveVCSConnectionOptions{}) + req, err := s.client.NewRequest("PATCH", u, &workspaceRemoveVCSConnectionOptions{}) if err != nil { return nil, err } w := &Workspace{} - err = s.client.do(ctx, req, w) + err = req.Do(ctx, w) if err != nil { return nil, err } @@ -815,13 +815,13 @@ func (s *workspaces) Lock(ctx context.Context, workspaceID string, options Works } u := fmt.Sprintf("workspaces/%s/actions/lock", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return nil, err } w := &Workspace{} - err = s.client.do(ctx, req, w) + err = req.Do(ctx, w) if err != nil { return nil, err } @@ -836,13 +836,13 @@ func (s *workspaces) Unlock(ctx context.Context, workspaceID string) (*Workspace } u := fmt.Sprintf("workspaces/%s/actions/unlock", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("POST", u, nil) + req, err := s.client.NewRequest("POST", u, nil) if err != nil { return nil, err } w := &Workspace{} - err = s.client.do(ctx, req, w) + err = req.Do(ctx, w) if err != nil { return nil, err } @@ -857,13 +857,13 @@ func (s *workspaces) ForceUnlock(ctx context.Context, workspaceID string) (*Work } u := fmt.Sprintf("workspaces/%s/actions/force-unlock", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("POST", u, nil) + req, err := s.client.NewRequest("POST", u, nil) if err != nil { return nil, err } w := &Workspace{} - err = s.client.do(ctx, req, w) + err = req.Do(ctx, w) if err != nil { return nil, err } @@ -881,13 +881,13 @@ func (s *workspaces) AssignSSHKey(ctx context.Context, workspaceID string, optio } u := fmt.Sprintf("workspaces/%s/relationships/ssh-key", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("PATCH", u, &options) + req, err := s.client.NewRequest("PATCH", u, &options) if err != nil { return nil, err } w := &Workspace{} - err = s.client.do(ctx, req, w) + err = req.Do(ctx, w) if err != nil { return nil, err } @@ -902,13 +902,13 @@ func (s *workspaces) UnassignSSHKey(ctx context.Context, workspaceID string) (*W } u := fmt.Sprintf("workspaces/%s/relationships/ssh-key", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("PATCH", u, &workspaceUnassignSSHKeyOptions{}) + req, err := s.client.NewRequest("PATCH", u, &workspaceUnassignSSHKeyOptions{}) if err != nil { return nil, err } w := &Workspace{} - err = s.client.do(ctx, req, w) + err = req.Do(ctx, w) if err != nil { return nil, err } @@ -924,13 +924,13 @@ func (s *workspaces) ListRemoteStateConsumers(ctx context.Context, workspaceID s u := fmt.Sprintf("workspaces/%s/relationships/remote-state-consumers", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } wl := &WorkspaceList{} - err = s.client.do(ctx, req, wl) + err = req.Do(ctx, wl) if err != nil { return nil, err } @@ -948,12 +948,12 @@ func (s *workspaces) AddRemoteStateConsumers(ctx context.Context, workspaceID st } u := fmt.Sprintf("workspaces/%s/relationships/remote-state-consumers", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("POST", u, options.Workspaces) + req, err := s.client.NewRequest("POST", u, options.Workspaces) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // RemoveRemoteStateConsumers removes the remote state consumers for a given workspace. @@ -966,12 +966,12 @@ func (s *workspaces) RemoveRemoteStateConsumers(ctx context.Context, workspaceID } u := fmt.Sprintf("workspaces/%s/relationships/remote-state-consumers", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("DELETE", u, options.Workspaces) + req, err := s.client.NewRequest("DELETE", u, options.Workspaces) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // UpdateRemoteStateConsumers removes the remote state consumers for a given workspace. @@ -984,12 +984,12 @@ func (s *workspaces) UpdateRemoteStateConsumers(ctx context.Context, workspaceID } u := fmt.Sprintf("workspaces/%s/relationships/remote-state-consumers", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("PATCH", u, options.Workspaces) + req, err := s.client.NewRequest("PATCH", u, options.Workspaces) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // ListTags returns the tags for a given workspace. @@ -1000,13 +1000,13 @@ func (s *workspaces) ListTags(ctx context.Context, workspaceID string, options * u := fmt.Sprintf("workspaces/%s/relationships/tags", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } tl := &TagList{} - err = s.client.do(ctx, req, tl) + err = req.Do(ctx, tl) if err != nil { return nil, err } @@ -1024,12 +1024,12 @@ func (s *workspaces) AddTags(ctx context.Context, workspaceID string, options Wo } u := fmt.Sprintf("workspaces/%s/relationships/tags", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("POST", u, options.Tags) + req, err := s.client.NewRequest("POST", u, options.Tags) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } // RemoveTags removes a list of tags from a workspace. @@ -1042,12 +1042,12 @@ func (s *workspaces) RemoveTags(ctx context.Context, workspaceID string, options } u := fmt.Sprintf("workspaces/%s/relationships/tags", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("DELETE", u, options.Tags) + req, err := s.client.NewRequest("DELETE", u, options.Tags) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (o WorkspaceCreateOptions) valid() error { diff --git a/workspace_run_task.go b/workspace_run_task.go index cc2eb4cd7..4dad5ecca 100644 --- a/workspace_run_task.go +++ b/workspace_run_task.go @@ -75,13 +75,13 @@ func (s *workspaceRunTasks) List(ctx context.Context, workspaceID string, option } u := fmt.Sprintf("workspaces/%s/tasks", url.QueryEscape(workspaceID)) - req, err := s.client.newRequest("GET", u, options) + req, err := s.client.NewRequest("GET", u, options) if err != nil { return nil, err } rl := &WorkspaceRunTaskList{} - err = s.client.do(ctx, req, rl) + err = req.Do(ctx, rl) if err != nil { return nil, err } @@ -104,13 +104,13 @@ func (s *workspaceRunTasks) Read(ctx context.Context, workspaceID, workspaceTask url.QueryEscape(workspaceID), url.QueryEscape(workspaceTaskID), ) - req, err := s.client.newRequest("GET", u, nil) + req, err := s.client.NewRequest("GET", u, nil) if err != nil { return nil, err } wr := &WorkspaceRunTask{} - err = s.client.do(ctx, req, wr) + err = req.Do(ctx, wr) if err != nil { return nil, err } @@ -129,13 +129,13 @@ func (s *workspaceRunTasks) Create(ctx context.Context, workspaceID string, opti } u := fmt.Sprintf("workspaces/%s/tasks", workspaceID) - req, err := s.client.newRequest("POST", u, &options) + req, err := s.client.NewRequest("POST", u, &options) if err != nil { return nil, err } wr := &WorkspaceRunTask{} - err = s.client.do(ctx, req, wr) + err = req.Do(ctx, wr) if err != nil { return nil, err } @@ -158,13 +158,13 @@ func (s *workspaceRunTasks) Update(ctx context.Context, workspaceID, workspaceTa url.QueryEscape(workspaceID), url.QueryEscape(workspaceTaskID), ) - req, err := s.client.newRequest("PATCH", u, &options) + req, err := s.client.NewRequest("PATCH", u, &options) if err != nil { return nil, err } wr := &WorkspaceRunTask{} - err = s.client.do(ctx, req, wr) + err = req.Do(ctx, wr) if err != nil { return nil, err } @@ -187,12 +187,12 @@ func (s *workspaceRunTasks) Delete(ctx context.Context, workspaceID, workspaceTa url.QueryEscape(workspaceID), url.QueryEscape(workspaceTaskID), ) - req, err := s.client.newRequest("DELETE", u, nil) + req, err := s.client.NewRequest("DELETE", u, nil) if err != nil { return err } - return s.client.do(ctx, req, nil) + return req.Do(ctx, nil) } func (o *WorkspaceRunTaskCreateOptions) valid() error { From f5cc5652587c35c53d0ba2c3cbdf36c1311b545c Mon Sep 17 00:00:00 2001 From: Brandon Croft Date: Fri, 24 Jun 2022 16:44:16 -0600 Subject: [PATCH 2/9] test: modify run create helpers to poll much longer before failing --- apply_integration_test.go | 4 +- helper_test.go | 300 +++++++++++++++++++++++++--------- testing.go | 2 +- workspace_integration_test.go | 6 +- 4 files changed, 230 insertions(+), 82 deletions(-) diff --git a/apply_integration_test.go b/apply_integration_test.go index adc1a772d..911b7b35c 100644 --- a/apply_integration_test.go +++ b/apply_integration_test.go @@ -22,7 +22,7 @@ func TestAppliesRead(t *testing.T) { wTest, wTestCleanup := createWorkspace(t, client, nil) defer wTestCleanup() - rTest, rTestCleanup := createAppliedRun(t, client, wTest) + rTest, rTestCleanup := createRunApply(t, client, wTest) defer rTestCleanup() t.Run("when the plan exists", func(t *testing.T) { @@ -50,7 +50,7 @@ func TestAppliesLogs(t *testing.T) { client := testClient(t) ctx := context.Background() - rTest, rTestCleanup := createAppliedRun(t, client, nil) + rTest, rTestCleanup := createRunApply(t, client, nil) defer rTestCleanup() t.Run("when the log exists", func(t *testing.T) { diff --git a/helper_test.go b/helper_test.go index 839ed407f..ad6d058e4 100644 --- a/helper_test.go +++ b/helper_test.go @@ -9,7 +9,7 @@ import ( "encoding/hex" "errors" "fmt" - "github.com/stretchr/testify/require" + "io" "io/ioutil" "math/rand" "net/url" @@ -18,6 +18,8 @@ import ( "testing" "time" + "github.com/stretchr/testify/require" + uuid "github.com/hashicorp/go-uuid" ) @@ -600,96 +602,232 @@ func createRunTrigger(t *testing.T, client *Client, w, sourceable *Workspace) (* } } -func createRun(t *testing.T, client *Client, w *Workspace) (*Run, func()) { - var wCleanup func() +func createPolicyCheckedRun(t *testing.T, client *Client, w *Workspace) (*Run, func()) { + return createRunWaitForAnyStatuses(t, client, w, []RunStatus{RunPolicyChecked, RunPolicyOverride}) +} - if w == nil { - w, wCleanup = createWorkspace(t, client, nil) +func createPlannedRun(t *testing.T, client *Client, w *Workspace) (*Run, func()) { + if paidFeaturesDisabled() { + return createRunWaitForStatus(t, client, w, RunPlanned) + } else { + return createRunWaitForStatus(t, client, w, RunCostEstimated) } +} - cv, cvCleanup := createUploadedConfigurationVersion(t, client, w) +func createCostEstimatedRun(t *testing.T, client *Client, w *Workspace) (*Run, func()) { + return createRunWaitForStatus(t, client, w, RunCostEstimated) +} +func createRunApply(t *testing.T, client *Client, w *Workspace) (*Run, func()) { ctx := context.Background() - r, err := client.Runs.Create(ctx, RunCreateOptions{ - ConfigurationVersion: cv, - Workspace: w, - }) - if err != nil { - t.Fatal(err) - } + run, rCleanup := createRunUnapplied(t, client, w) + timeout := 2 * time.Minute - return r, func() { - cvCleanup() + // If the run was not in error, it must be applyable + applyRun(t, client, ctx, run) - if wCleanup != nil { - wCleanup() - } + ctxPollRunApplied, cancelPollApplied := context.WithTimeout(ctx, timeout) + + run = pollRunStatus(t, client, ctxPollRunApplied, run, []RunStatus{RunApplied, RunErrored}) + if run.Status == RunErrored { + fatalDumpRunLog(t, client, ctx, run) + } + + return run, func() { + rCleanup() + cancelPollApplied() } } -func createRunWithStatus(t *testing.T, client *Client, w *Workspace, timeout int, desiredStatuses ...RunStatus) (*Run, func()) { +func createRunUnapplied(t *testing.T, client *Client, w *Workspace) (*Run, func()) { + var rCleanup func() + ctx := context.Background() r, rCleanup := createRun(t, client, w) - var err error + timeout := 2 * time.Minute + + ctxPollRunReady, cancelPollRunReady := context.WithTimeout(ctx, timeout) + + run := pollRunStatus( + t, + client, + ctxPollRunReady, + r, + append(applyableStatuses(r), RunErrored), + ) + + if run.Status == RunErrored { + fatalDumpRunLog(t, client, ctx, run) + } + + return run, func() { + rCleanup() + cancelPollRunReady() + } +} + +func createRunWaitForStatus(t *testing.T, client *Client, w *Workspace, status RunStatus) (*Run, func()) { + return createRunWaitForAnyStatuses(t, client, w, []RunStatus{status}) +} + +func createRunWaitForAnyStatuses(t *testing.T, client *Client, w *Workspace, statuses []RunStatus) (*Run, func()) { + var rCleanup func() ctx := context.Background() - for i := 0; ; i++ { - r, err = client.Runs.Read(ctx, r.ID) - if err != nil { - t.Fatal(err) + r, rCleanup := createRun(t, client, w) + + timeout := 2 * time.Minute + + ctxPollRunReady, cancelPollRunReady := context.WithTimeout(ctx, timeout) + + run := pollRunStatus( + t, + client, + ctxPollRunReady, + r, + append(statuses, RunErrored), + ) + + if run.Status == RunErrored { + fatalDumpRunLog(t, client, ctx, run) + } + + return run, func() { + rCleanup() + cancelPollRunReady() + } +} + +func applyableStatuses(r *Run) []RunStatus { + if len(r.PolicyChecks) > 0 { + return []RunStatus{ + RunPolicyChecked, + RunPolicyOverride, } + } else if r.CostEstimate != nil { + return []RunStatus{RunCostEstimated} + } else { + return []RunStatus{RunPlanned} + } +} + +// pollRunStatus will poll the given run until its status matches one of the given run statuses or the given context +// times out. +func pollRunStatus(t *testing.T, client *Client, ctx context.Context, r *Run, rss []RunStatus) *Run { + deadline, ok := ctx.Deadline() + if !ok { + t.Logf("No deadline was set to poll run %q which could result in an infinite loop", r.ID) + } - for _, desiredStatus := range desiredStatuses { - // if we're creating an applied run, we need to manually confirm the apply once the plan finishes - isApplyable := hasApplyableStatus(r) - if desiredStatus == RunApplied && isApplyable { - err := client.Runs.Apply(ctx, r.ID, RunApplyOptions{}) - if err != nil { - t.Fatal(err) + t.Logf("Polling run %q for status included in %q with deadline of %s", r.ID, rss, deadline) + + ticker := time.NewTicker(2 * time.Second) + defer ticker.Stop() + + for finished := false; !finished; { + t.Log("...") + select { + case <-ctx.Done(): + t.Fatalf("Run %q had status %q at deadline", r.ID, r.Status) + case <-ticker.C: + r = readRun(t, client, ctx, r) + t.Logf("Run %q had status %q", r.ID, r.Status) + for _, rs := range rss { + if rs == r.Status { + finished = true + break } - } else if desiredStatus == r.Status { - return r, rCleanup } } + } - if i > timeout { - runStatus := r.Status - rCleanup() - t.Fatal(fmt.Printf("Timeout waiting for run ID %s to reach status %v, had status %s", - r.ID, - desiredStatuses, - runStatus)) - } + return r +} - time.Sleep(1 * time.Second) +// readRun will re-read the given run. +func readRun(t *testing.T, client *Client, ctx context.Context, r *Run) *Run { + t.Logf("Reading run %q", r.ID) + + rr, err := client.Runs.Read(ctx, r.ID) + if err != nil { + t.Fatalf("Could not read run %q: %s", r.ID, err) } + + return rr } -func createPlannedRun(t *testing.T, client *Client, w *Workspace) (*Run, func()) { - if paidFeaturesDisabled() { - return createRunWithStatus(t, client, w, 45, RunPlanned) +// applyRun will apply the given run. +func applyRun(t *testing.T, client *Client, ctx context.Context, r *Run) { + t.Logf("Applying run %q", r.ID) + + if err := client.Runs.Apply(ctx, r.ID, RunApplyOptions{}); err != nil { + t.Fatalf("Could not apply run %q: %s", r.ID, err) } - return createRunWithStatus(t, client, w, 45, RunCostEstimated) } -func createCostEstimatedRun(t *testing.T, client *Client, w *Workspace) (*Run, func()) { - return createRunWithStatus(t, client, w, 45, RunCostEstimated) +// readPlan will read the given plan. +func readPlan(t *testing.T, client *Client, ctx context.Context, p *Plan) *Plan { + t.Logf("Reading plan %q", p.ID) + + rp, err := client.Plans.Read(ctx, p.ID) + if err != nil { + t.Fatalf("Could not read plan %q: %s", p.ID, err) + } + + return rp } -func createPolicyCheckedRun(t *testing.T, client *Client, w *Workspace) (*Run, func()) { - return createRunWithStatus(t, client, w, 45, RunPolicyChecked, RunPolicyOverride) +// readPlanLogs will read the logs of the given plan. +func readPlanLogs(t *testing.T, client *Client, ctx context.Context, p *Plan) io.Reader { + t.Logf("Reading logs of plan %q", p.ID) + + r, err := client.Plans.Logs(ctx, p.ID) + if err != nil { + t.Fatalf("Could not retrieve logs of plan %q: %s", p.ID, err) + } + + return r } -func createAppliedRun(t *testing.T, client *Client, w *Workspace) (*Run, func()) { - return createRunWithStatus(t, client, w, 90, RunApplied) +func fatalDumpRunLog(t *testing.T, client *Client, ctx context.Context, run *Run) { + t.Helper() + p := readPlan(t, client, ctx, run.Plan) + r := readPlanLogs(t, client, ctx, p) + + l, err := io.ReadAll(r) + if err != nil { + t.Fatalf("Could not read logs of plan %q: %v", p.ID, err) + } + + t.Log("Run errored - here's some logs to help figure out what happened") + t.Logf("---Start of logs---\n%s\n---End of logs---", l) + + t.Fatalf("Run %q unexpectedly errored", run.ID) } -func hasApplyableStatus(r *Run) bool { - if len(r.PolicyChecks) > 0 { - return r.Status == RunPolicyChecked || r.Status == RunPolicyOverride - } else if r.CostEstimate != nil { - return r.Status == RunCostEstimated - } else { - return r.Status == RunPlanned +func createRun(t *testing.T, client *Client, w *Workspace) (*Run, func()) { + var wCleanup func() + + if w == nil { + w, wCleanup = createWorkspace(t, client, nil) + } + + cv, cvCleanup := createUploadedConfigurationVersion(t, client, w) + + ctx := context.Background() + r, err := client.Runs.Create(ctx, RunCreateOptions{ + ConfigurationVersion: cv, + Workspace: w, + }) + if err != nil { + t.Fatal(err) + } + + return r, func() { + cvCleanup() + + if wCleanup != nil { + wCleanup() + } } } @@ -697,7 +835,7 @@ func createPlanExport(t *testing.T, client *Client, r *Run) (*PlanExport, func() var rCleanup func() if r == nil { - r, rCleanup = createPlannedRun(t, client, nil) + r, rCleanup = createRunApply(t, client, nil) } ctx := context.Background() @@ -709,27 +847,37 @@ func createPlanExport(t *testing.T, client *Client, r *Run) (*PlanExport, func() t.Fatal(err) } - for i := 0; ; i++ { - pe, err := client.PlanExports.Read(ctx, pe.ID) - if err != nil { - t.Fatal(err) - } + timeout := 2 * time.Minute - if pe.Status == PlanExportFinished { - return pe, func() { - if rCleanup != nil { - rCleanup() - } - } - } + ctxPollExportReady, cancelPollExportReady := context.WithTimeout(ctx, timeout) + t.Cleanup(cancelPollExportReady) - if i > 45 { + ticker := time.NewTicker(5 * time.Second) + defer ticker.Stop() + + for { + t.Log("...") + select { + case <-ctxPollExportReady.Done(): rCleanup() - t.Fatal("Timeout waiting for plan export to finish") - } + t.Fatalf("Run %q had status %q at deadline", r.ID, r.Status) + case <-ticker.C: + pe, err := client.PlanExports.Read(ctxPollExportReady, pe.ID) + if err != nil { + t.Fatal(err) + } - time.Sleep(1 * time.Second) + if pe.Status == PlanExportFinished { + return pe, func() { + if rCleanup != nil { + rCleanup() + } + } + } + } } + + return nil, rCleanup } func createRegistryModule(t *testing.T, client *Client, org *Organization) (*RegistryModule, func()) { diff --git a/testing.go b/testing.go index 63e392f36..501b99f1a 100644 --- a/testing.go +++ b/testing.go @@ -28,7 +28,7 @@ func FetchTestAccountDetails(t *testing.T, client *Client) *TestAccountDetails { } ctx := context.Background() - err = client.do(ctx, req, tad) + err = req.Do(ctx, tad) if err != nil { t.Fatalf("could not fetch test user details: %v", err) } diff --git a/workspace_integration_test.go b/workspace_integration_test.go index 0a9dbf476..d5264d912 100644 --- a/workspace_integration_test.go +++ b/workspace_integration_test.go @@ -147,7 +147,7 @@ func TestWorkspacesList(t *testing.T) { }) t.Run("with current-state-version,current-run included", func(t *testing.T) { - _, rCleanup := createAppliedRun(t, client, wTest1) + _, rCleanup := createRunApply(t, client, wTest1) t.Cleanup(rCleanup) wl, err := client.Workspaces.List(ctx, orgTest.Name, &WorkspaceListOptions{ @@ -469,7 +469,7 @@ func TestWorkspacesReadWithHistory(t *testing.T) { wTest, wTestCleanup := createWorkspace(t, client, orgTest) defer wTestCleanup() - _, rCleanup := createAppliedRun(t, client, wTest) + _, rCleanup := createRunApply(t, client, wTest) defer rCleanup() w, err := client.Workspaces.Read(context.Background(), orgTest.Name, wTest.Name) @@ -489,7 +489,7 @@ func TestWorkspacesReadReadme(t *testing.T) { wTest, wTestCleanup := createWorkspaceWithVCS(t, client, orgTest, WorkspaceCreateOptions{}) defer wTestCleanup() - _, rCleanup := createAppliedRun(t, client, wTest) + _, rCleanup := createRunApply(t, client, wTest) defer rCleanup() t.Run("when the readme exists", func(t *testing.T) { From fe72e20901ff2f88d5944df5010e1e223ac69e17 Mon Sep 17 00:00:00 2001 From: Brandon Croft Date: Thu, 30 Jun 2022 15:39:53 -0600 Subject: [PATCH 3/9] feat: optionally send json outputs when creating state versions --- state_version.go | 8 +- state_version_integration_test.go | 14 +- test-fixtures/ext-state-version/state.json | 163 ------------------ .../json-state-outputs/everything.json | 113 ++++++++++++ 4 files changed, 125 insertions(+), 173 deletions(-) delete mode 100644 test-fixtures/ext-state-version/state.json create mode 100644 test-fixtures/json-state-outputs/everything.json diff --git a/state_version.go b/state_version.go index 078d3e177..1eb1aacf2 100644 --- a/state_version.go +++ b/state_version.go @@ -139,13 +139,13 @@ type StateVersionCreateOptions struct { // Optional: Specifies the run to associate the state with. Run *Run `jsonapi:"relation,run,omitempty"` - // Optional: The external, json representation of state data, base64 encoded. - // https://www.terraform.io/internals/json-format#state-representation - // Supplying this state representation can provide more details to the platform + // Optional: The external, json representation of state outputs, base64 encoded. + // https://www.terraform.io/internals/json-format#values-representation (the contents of the + // "outputs" attribute) Supplying detailed outputs will provide more details to the platform // about the current terraform state. // // **Note**: This field is in BETA, subject to change and not widely available yet. - JSONState *string `jsonapi:"attr,json-state,omitempty"` + JSONStateOutputs *string `jsonapi:"attr,json-state-outputs,omitempty"` } // List all the state versions for a given workspace. diff --git a/state_version_integration_test.go b/state_version_integration_test.go index de4166999..35e086e04 100644 --- a/state_version_integration_test.go +++ b/state_version_integration_test.go @@ -121,7 +121,7 @@ func TestStateVersionsCreate(t *testing.T) { t.Fatal(err) } - jsonState, err := ioutil.ReadFile("test-fixtures/ext-state-version/state.json") + jsonStateOutputs, err := ioutil.ReadFile("test-fixtures/json-state-outputs/everything.json") if err != nil { t.Fatal(err) } @@ -169,11 +169,11 @@ func TestStateVersionsCreate(t *testing.T) { } sv, err := client.StateVersions.Create(ctx, wTest.ID, StateVersionCreateOptions{ - Lineage: String("741c4949-60b9-5bb1-5bf8-b14f4bb14af3"), - MD5: String(fmt.Sprintf("%x", md5.Sum(state))), - Serial: Int64(1), - State: String(base64.StdEncoding.EncodeToString(state)), - JSONState: String(base64.StdEncoding.EncodeToString(jsonState)), + Lineage: String("741c4949-60b9-5bb1-5bf8-b14f4bb14af3"), + MD5: String(fmt.Sprintf("%x", md5.Sum(state))), + Serial: Int64(1), + State: String(base64.StdEncoding.EncodeToString(state)), + JSONStateOutputs: String(base64.StdEncoding.EncodeToString(jsonStateOutputs)), }) require.NoError(t, err) @@ -186,6 +186,8 @@ func TestStateVersionsCreate(t *testing.T) { t.Fatal(err) } + // TODO: check state outputs for the ones we sent in JSONStateOutputs + for _, item := range []*StateVersion{ sv, refreshed, diff --git a/test-fixtures/ext-state-version/state.json b/test-fixtures/ext-state-version/state.json deleted file mode 100644 index 5acced8cc..000000000 --- a/test-fixtures/ext-state-version/state.json +++ /dev/null @@ -1,163 +0,0 @@ -{ - "format_version": "1.0", - "terraform_version": "1.2.0", - "values": { - "outputs": { - "a-decimal": { - "sensitive": false, - "value": 1000.1, - "type": "number" - }, - "a-false-bool": { - "sensitive": false, - "value": false, - "type": "bool" - }, - "a-list": { - "sensitive": false, - "value": [ - "example", - "1001", - "1000.1" - ], - "type": [ - "list", - "string" - ] - }, - "a-long-string": { - "sensitive": false, - "value": "The private integer of the main server instance is where you want to go when you have the most fun in every Terraform instance you can see in the world that you live in except for dogs because they don't run servers in the same place that humans do.", - "type": "string" - }, - "a-object": { - "sensitive": false, - "value": { - "bar": 1000.1, - "example": 1001 - }, - "type": [ - "object", - { - "bar": "number", - "example": "number" - } - ] - }, - "a-sensitive-value": { - "sensitive": true, - "value": "hopefully you cannot see me", - "type": "string" - }, - "a-string": { - "sensitive": false, - "value": "example string", - "type": "string" - }, - "a-true-bool": { - "sensitive": false, - "value": true, - "type": "bool" - }, - "a-tuple": { - "sensitive": false, - "value": [ - 1, - "example" - ], - "type": [ - "tuple", - [ - "number", - "string" - ] - ] - }, - "an-int": { - "sensitive": false, - "value": 1001, - "type": "number" - }, - "escapes": { - "sensitive": false, - "value": "line 1\nline 2\n\\\\\\\\\n", - "type": "string" - }, - "myoutput": { - "sensitive": false, - "value": { - "nesting1": { - "nesting2": { - "nesting3": "4263891374290101092" - } - } - }, - "type": [ - "object", - { - "nesting1": [ - "object", - { - "nesting2": [ - "object", - { - "nesting3": "string" - } - ] - } - ] - } - ] - }, - "random": { - "sensitive": false, - "value": "8b3086889a9ef7a5", - "type": "string" - } - }, - "root_module": { - "resources": [ - { - "address": "null_resource.test", - "mode": "managed", - "type": "null_resource", - "name": "test", - "provider_name": "registry.terraform.io/hashicorp/null", - "schema_version": 0, - "values": { - "id": "4263891374290101092", - "triggers": { - "hello": "wat3" - } - }, - "sensitive_values": { - "triggers": {} - } - }, - { - "address": "random_id.random", - "mode": "managed", - "type": "random_id", - "name": "random", - "provider_name": "registry.terraform.io/hashicorp/random", - "schema_version": 0, - "values": { - "b64_std": "izCGiJqe96U=", - "b64_url": "izCGiJqe96U", - "byte_length": 8, - "dec": "10029664291421878181", - "hex": "8b3086889a9ef7a5", - "id": "izCGiJqe96U", - "keepers": { - "uuid": "437a1415-932b-9f74-c214-184d88215353" - }, - "prefix": null - }, - "sensitive_values": { - "keepers": {} - } - } - ] - } - } -} diff --git a/test-fixtures/json-state-outputs/everything.json b/test-fixtures/json-state-outputs/everything.json new file mode 100644 index 000000000..66c5b45b6 --- /dev/null +++ b/test-fixtures/json-state-outputs/everything.json @@ -0,0 +1,113 @@ +{ + "a-decimal": { + "sensitive": false, + "value": 1000.1, + "type": "number" + }, + "a-false-bool": { + "sensitive": false, + "value": false, + "type": "bool" + }, + "a-list": { + "sensitive": false, + "value": [ + "example", + "1001", + "1000.1" + ], + "type": [ + "list", + "string" + ] + }, + "a-long-string": { + "sensitive": false, + "value": "The private integer of the main server instance is where you want to go when you have the most fun in every Terraform instance you can see in the world that you live in except for dogs because they don't run servers in the same place that humans do.", + "type": "string" + }, + "a-object": { + "sensitive": false, + "value": { + "bar": 1000.1, + "example": 1001 + }, + "type": [ + "object", + { + "bar": "number", + "example": "number" + } + ] + }, + "a-sensitive-value": { + "sensitive": true, + "value": "hopefully you cannot see me", + "type": "string" + }, + "a-string": { + "sensitive": false, + "value": "example string", + "type": "string" + }, + "a-true-bool": { + "sensitive": false, + "value": true, + "type": "bool" + }, + "a-tuple": { + "sensitive": false, + "value": [ + 1, + "example" + ], + "type": [ + "tuple", + [ + "number", + "string" + ] + ] + }, + "an-int": { + "sensitive": false, + "value": 1001, + "type": "number" + }, + "escapes": { + "sensitive": false, + "value": "line 1\nline 2\n\\\\\\\\\n", + "type": "string" + }, + "myoutput": { + "sensitive": false, + "value": { + "nesting1": { + "nesting2": { + "nesting3": "4263891374290101092" + } + } + }, + "type": [ + "object", + { + "nesting1": [ + "object", + { + "nesting2": [ + "object", + { + "nesting3": "string" + } + ] + } + ] + } + ] + }, + "random": { + "sensitive": false, + "value": "8b3086889a9ef7a5", + "type": "string" + } +} From 1fbe39d03e0751389a5dd08e8dbb7f16d6b30bbf Mon Sep 17 00:00:00 2001 From: Brandon Croft Date: Tue, 5 Jul 2022 13:23:05 -0600 Subject: [PATCH 4/9] Update CHANGELOG.md --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1db49b805..a845e5740 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,8 @@ ## Enhancements * Adds `RetryServerErrors` field to the `Config` object by @sebasslash [#439](https://github.com/hashicorp/go-tfe/pull/439) * Adds support for the GPG Keys API by @sebasslash [#429](https://github.com/hashicorp/go-tfe/pull/429) -* [beta] Renames the optional StateVersion field `ExtState` to `JSONState` and changes to string for base64 encoding by @annawinkler [#444](https://github.com/hashicorp/go-tfe/pull/444) * Add support for new `WorkspaceLimit` Admin setting for organizations [#425](https://github.com/hashicorp/go-tfe/pull/425) +* [beta] Renames the optional StateVersion field `ExtState` to `JSONStateOutputs` and changes the purpose and type by @annawinkler [#444](https://github.com/hashicorp/go-tfe/pull/444) and @brandoncroft [#452](https://github.com/hashicorp/go-tfe/pull/452) # v1.3.0 From 9bc3f45ea91c865d3dab0960f8df9d9cf6abff3c Mon Sep 17 00:00:00 2001 From: Brandon Croft Date: Tue, 5 Jul 2022 14:04:22 -0600 Subject: [PATCH 5/9] Update state_version.go Co-authored-by: Anna Winkler <3526523+annawinkler@users.noreply.github.com> --- state_version.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/state_version.go b/state_version.go index 1eb1aacf2..d3fd2d987 100644 --- a/state_version.go +++ b/state_version.go @@ -141,7 +141,8 @@ type StateVersionCreateOptions struct { // Optional: The external, json representation of state outputs, base64 encoded. // https://www.terraform.io/internals/json-format#values-representation (the contents of the - // "outputs" attribute) Supplying detailed outputs will provide more details to the platform + // "outputs" attribute) + // Supplying detailed outputs will provide more details to the platform // about the current terraform state. // // **Note**: This field is in BETA, subject to change and not widely available yet. From 90f07ddf69d9ca20af10cb073d4d7d6ddfcd83ae Mon Sep 17 00:00:00 2001 From: Brandon Croft Date: Tue, 5 Jul 2022 15:37:48 -0600 Subject: [PATCH 6/9] Update state_version.go Co-authored-by: Sebastian Rivera --- state_version.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/state_version.go b/state_version.go index d3fd2d987..39173aafb 100644 --- a/state_version.go +++ b/state_version.go @@ -139,10 +139,9 @@ type StateVersionCreateOptions struct { // Optional: Specifies the run to associate the state with. Run *Run `jsonapi:"relation,run,omitempty"` - // Optional: The external, json representation of state outputs, base64 encoded. - // https://www.terraform.io/internals/json-format#values-representation (the contents of the - // "outputs" attribute) - // Supplying detailed outputs will provide more details to the platform + // Optional: The external, json representation of state outputs, base64 encoded. Supplying this field + // will provide more detailed output type information to TFE. + // For more information on the contents of this field: https://www.terraform.io/internals/json-format#values-representation // about the current terraform state. // // **Note**: This field is in BETA, subject to change and not widely available yet. From b3fd1d716b67db6f58eccba31b93d0225618ba13 Mon Sep 17 00:00:00 2001 From: Brandon Croft Date: Wed, 6 Jul 2022 10:13:38 -0600 Subject: [PATCH 7/9] test fix: revert me soon --- oauth_client_integration_test.go | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/oauth_client_integration_test.go b/oauth_client_integration_test.go index b9b0817d1..2927097b1 100644 --- a/oauth_client_integration_test.go +++ b/oauth_client_integration_test.go @@ -5,6 +5,7 @@ package tfe import ( "context" + "fmt" "os" "testing" @@ -247,8 +248,14 @@ func TestOAuthClientsDelete(t *testing.T) { err := client.OAuthClients.Delete(ctx, ocTest.ID) require.NoError(t, err) - // Try loading the OAuth client - it should fail. - _, err = client.OAuthClients.Read(ctx, ocTest.ID) + _, err = retry(func() (interface{}, error) { + c, err := client.OAuthClients.Read(ctx, ocTest.ID) + if err != ErrResourceNotFound { + return nil, fmt.Errorf("expected %s, but err was %s", ErrResourceNotFound, err) + } + return c, err + }) + assert.Equal(t, err, ErrResourceNotFound) }) From 9008efbb2c1e293f07088489ee22e22e8c0f0a6b Mon Sep 17 00:00:00 2001 From: Brandon Croft Date: Wed, 6 Jul 2022 10:47:56 -0600 Subject: [PATCH 8/9] test: retry workspace read resource count test --- workspace_integration_test.go | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/workspace_integration_test.go b/workspace_integration_test.go index d5264d912..2604f1a47 100644 --- a/workspace_integration_test.go +++ b/workspace_integration_test.go @@ -472,11 +472,24 @@ func TestWorkspacesReadWithHistory(t *testing.T) { _, rCleanup := createRunApply(t, client, wTest) defer rCleanup() - w, err := client.Workspaces.Read(context.Background(), orgTest.Name, wTest.Name) - require.NoError(t, err) + _, err := retry(func() (interface{}, error) { + w, err := client.Workspaces.Read(context.Background(), orgTest.Name, wTest.Name) + require.NoError(t, err) + + if w.RunsCount != 1 { + return nil, fmt.Errorf("expected %d runs but found %d", 1, w.RunsCount) + } + + if w.ResourceCount != 1 { + return nil, fmt.Errorf("expected %d resources but found %d", 1, w.ResourceCount) + } + + return w, nil + }) - assert.Equal(t, 1, w.RunsCount) - assert.Equal(t, 1, w.ResourceCount) + if err != nil { + t.Error(err) + } } func TestWorkspacesReadReadme(t *testing.T) { From fd0b70ef67c68b1822e9b131d5d3e6b02c8eb42f Mon Sep 17 00:00:00 2001 From: Brandon Croft Date: Wed, 6 Jul 2022 17:15:27 -0600 Subject: [PATCH 9/9] test: TestConfigurationVersionsReadWithOptions should retry --- configuration_version_integration_test.go | 31 +++++++++++++---------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/configuration_version_integration_test.go b/configuration_version_integration_test.go index fe028698e..b85e6790e 100644 --- a/configuration_version_integration_test.go +++ b/configuration_version_integration_test.go @@ -7,10 +7,12 @@ import ( "bytes" "context" "encoding/json" - "github.com/hashicorp/go-slug" + "errors" "testing" "time" + "github.com/hashicorp/go-slug" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) @@ -155,22 +157,25 @@ func TestConfigurationVersionsReadWithOptions(t *testing.T) { wTest, wTestCleanup := createWorkspaceWithVCS(t, client, orgTest, WorkspaceCreateOptions{QueueAllRuns: Bool(true)}) defer wTestCleanup() - // Hack: Wait for TFC to ingress the configuration and queue a run - time.Sleep(3 * time.Second) + w, err := retry(func() (interface{}, error) { + w, err := client.Workspaces.ReadByIDWithOptions(ctx, wTest.ID, &WorkspaceReadOptions{ + Include: []WSIncludeOpt{WSCurrentRunConfigVer}, + }) - w, err := client.Workspaces.ReadByIDWithOptions(ctx, wTest.ID, &WorkspaceReadOptions{ - Include: []WSIncludeOpt{WSCurrentRunConfigVer}, - }) + if err != nil { + return nil, err + } - if err != nil { - require.NoError(t, err) - } + if w.CurrentRun == nil { + return nil, errors.New("A run was expected to be found on this workspace as a test pre-condition") + } - if w.CurrentRun == nil { - t.Fatal("A run was expected to be found on this workspace as a test pre-condition") - } + return w, nil + }) + + require.NoError(t, err) - cv := w.CurrentRun.ConfigurationVersion + cv := w.(*Workspace).CurrentRun.ConfigurationVersion t.Run("when the configuration version exists", func(t *testing.T) { options := &ConfigurationVersionReadOptions{