diff --git a/admin_organization.go b/admin_organization.go index 9fb417988..a10591bc5 100644 --- a/admin_organization.go +++ b/admin_organization.go @@ -117,6 +117,7 @@ func (s *adminOrganizations) List(ctx context.Context, options *AdminOrganizatio return orgl, nil } +// List specific organizations in the Terraform Enterprise installation that have permission to use an organization's modules. func (s *adminOrganizations) ListModuleConsumers(ctx context.Context, organization string, options *AdminOrganizationListModuleConsumersOptions) (*AdminOrganizationList, error) { if !validStringID(&organization) { return nil, ErrInvalidOrg @@ -138,6 +139,7 @@ func (s *adminOrganizations) ListModuleConsumers(ctx context.Context, organizati return orgl, nil } +// Show an organization by its name. func (s *adminOrganizations) Read(ctx context.Context, organization string) (*AdminOrganization, error) { if !validStringID(&organization) { return nil, ErrInvalidOrg @@ -158,6 +160,7 @@ func (s *adminOrganizations) Read(ctx context.Context, organization string) (*Ad return org, nil } +// Update an organization by its name. func (s *adminOrganizations) Update(ctx context.Context, organization string, options AdminOrganizationUpdateOptions) (*AdminOrganization, error) { if !validStringID(&organization) { return nil, ErrInvalidOrg @@ -178,6 +181,7 @@ func (s *adminOrganizations) Update(ctx context.Context, organization string, op return org, nil } +// Update an organization to specify a list of organizations that can use modules from the sharing organization's private registry. func (s *adminOrganizations) UpdateModuleConsumers(ctx context.Context, organization string, consumerOrganizationIDs []string) error { if !validStringID(&organization) { return ErrInvalidOrg diff --git a/admin_run.go b/admin_run.go index 2ea235946..4d61b922f 100644 --- a/admin_run.go +++ b/admin_run.go @@ -29,6 +29,7 @@ type adminRuns struct { client *Client } +// AdminRun represents a run managed by site administrators that gets returned from the Runs Admin API. type AdminRun struct { ID string `jsonapi:"primary,runs"` CreatedAt time.Time `jsonapi:"attr,created-at,iso8601"` @@ -47,6 +48,7 @@ type AdminRunsList struct { Items []*AdminRun } +// AdminRunIncludeOps represents the available options for include query params // https://www.terraform.io/cloud-docs/api-docs/admin/runs#available-related-resources type AdminRunIncludeOps string @@ -111,7 +113,6 @@ func (s *adminRuns) ForceCancel(ctx context.Context, runID string, options Admin return s.client.do(ctx, req, nil) } -// Check that the field RunStatus has a valid string value func (o *AdminRunsListOptions) valid() error { if o == nil { // no need to validate fields return nil diff --git a/admin_setting.go b/admin_setting.go index ccf0551fd..a3dfafb17 100644 --- a/admin_setting.go +++ b/admin_setting.go @@ -4,7 +4,6 @@ package tfe // Note that admin settings are only available in Terraform Enterprise. // // TFE API docs: https://www.terraform.io/docs/cloud/api/admin/settings.html -// AdminSettings todo type AdminSettings struct { General GeneralSettings SAML SAMLSettings diff --git a/admin_setting_cost_estimation.go b/admin_setting_cost_estimation.go index 75f27c274..009423062 100644 --- a/admin_setting_cost_estimation.go +++ b/admin_setting_cost_estimation.go @@ -7,7 +7,7 @@ import ( // Compile-time proof of interface implementation. var _ CostEstimationSettings = (*adminCostEstimationSettings)(nil) -// CostEstimationSettings describes all the cost estimation admin settings. +// CostEstimationSettings describes all the cost estimation admin settings for the Admin Setting API https://www.terraform.io/cloud-docs/api-docs/admin/settings type CostEstimationSettings interface { // Read returns the cost estimation settings. Read(ctx context.Context) (*AdminCostEstimationSetting, error) diff --git a/admin_setting_customization.go b/admin_setting_customization.go index d467faaa0..ebe651961 100644 --- a/admin_setting_customization.go +++ b/admin_setting_customization.go @@ -20,7 +20,7 @@ type adminCustomizationSettings struct { client *Client } -// AdminCustomizationSetting represents the Customization settings in Terraform Enterprise. +// AdminCustomizationSetting represents the Customization settings in Terraform Enterprise for the Admin Settings API https://www.terraform.io/cloud-docs/api-docs/admin/settings type AdminCustomizationSetting struct { ID string `jsonapi:"primary,customization-settings"` SupportEmail string `jsonapi:"attr,support-email-address"` diff --git a/admin_setting_general.go b/admin_setting_general.go index b0c5b85fc..7dc11f64e 100644 --- a/admin_setting_general.go +++ b/admin_setting_general.go @@ -7,7 +7,7 @@ import ( // Compile-time proof of interface implementation. var _ GeneralSettings = (*adminGeneralSettings)(nil) -// GeneralSettings describes the general admin settings. +// GeneralSettings describes the general admin settings for the Admin Setting API https://www.terraform.io/cloud-docs/api-docs/admin/settings type GeneralSettings interface { // Read returns the general settings Read(ctx context.Context) (*AdminGeneralSetting, error) diff --git a/admin_setting_saml.go b/admin_setting_saml.go index 3de700faa..50a39f4e5 100644 --- a/admin_setting_saml.go +++ b/admin_setting_saml.go @@ -7,7 +7,7 @@ import ( // Compile-time proof of interface implementation. var _ SAMLSettings = (*adminSAMLSettings)(nil) -// SAMLSettings describes all the SAML admin settings. +// SAMLSettings describes all the SAML admin settings for the Admin Setting API https://www.terraform.io/cloud-docs/api-docs/admin/settings type SAMLSettings interface { // Read returns the SAML settings. Read(ctx context.Context) (*AdminSAMLSetting, error) diff --git a/admin_setting_smtp.go b/admin_setting_smtp.go index 5afc98d72..feec20662 100644 --- a/admin_setting_smtp.go +++ b/admin_setting_smtp.go @@ -7,7 +7,7 @@ import ( // Compile-time proof of interface implementation. var _ SMTPSettings = (*adminSMTPSettings)(nil) -// SMTPSettings describes all the SMTP admin settings. +// SMTPSettings describes all the SMTP admin settings for the Admin Setting API https://www.terraform.io/cloud-docs/api-docs/admin/settings. type SMTPSettings interface { // Read returns the SMTP settings. Read(ctx context.Context) (*AdminSMTPSetting, error) diff --git a/admin_setting_twilio.go b/admin_setting_twilio.go index 8c884377e..034fb10bf 100644 --- a/admin_setting_twilio.go +++ b/admin_setting_twilio.go @@ -7,7 +7,7 @@ import ( // Compile-time proof of interface implementation. var _ TwilioSettings = (*adminTwilioSettings)(nil) -// TwilioSettings describes all the Twilio admin settings. +// TwilioSettings describes all the Twilio admin settings for the Admin Setting API https://www.terraform.io/cloud-docs/api-docs/admin/settings. type TwilioSettings interface { // Read returns the Twilio settings. Read(ctx context.Context) (*AdminTwilioSetting, error) diff --git a/admin_workspace.go b/admin_workspace.go index 16a047d66..277dce0d8 100644 --- a/admin_workspace.go +++ b/admin_workspace.go @@ -24,11 +24,12 @@ type AdminWorkspaces interface { Delete(ctx context.Context, workspaceID string) error } -// adminWorkspaces implements AdminWorkspaces. +// adminWorkspaces implements AdminWorkspaces interface. type adminWorkspaces struct { client *Client } +// AdminVCSRepo represents a VCS repository type AdminVCSRepo struct { Identifier string `jsonapi:"attr,identifier"` } @@ -72,7 +73,7 @@ type AdminWorkspaceList struct { Items []*AdminWorkspace } -// List all the workspaces within a worksapce. +// List all the workspaces within a workspace. func (s *adminWorkspaces) List(ctx context.Context, options *AdminWorkspaceListOptions) (*AdminWorkspaceList, error) { u := "admin/workspaces" req, err := s.client.newRequest("GET", u, options) diff --git a/apply.go b/apply.go index 029e39d84..62b896aa2 100644 --- a/apply.go +++ b/apply.go @@ -23,7 +23,7 @@ type Applies interface { Logs(ctx context.Context, applyID string) (io.Reader, error) } -// applies implements Applys. +// applies implements Applies interface. type applies struct { client *Client } diff --git a/errors.go b/errors.go index 369301599..aee792db9 100644 --- a/errors.go +++ b/errors.go @@ -17,6 +17,7 @@ var ( ) // Options/fields that cannot be defined + var ( ErrUnsupportedOperations = errors.New("operations is deprecated and cannot be specified when execution mode is used") @@ -24,33 +25,30 @@ var ( ) // Library errors that usually indicate a bug in the implementation of go-tfe + var ( - // ErrItemsMustBeSlice is returned when an API response attribute called Items is not a slice - ErrItemsMustBeSlice = errors.New(`model field "Items" must be a slice`) + ErrItemsMustBeSlice = errors.New(`model field "Items" must be a slice`) // ErrItemsMustBeSlice is returned when an API response attribute called Items is not a slice - // ErrInvalidRequestBody is returned when a request body for DELETE/PATCH/POST is not a reference type - ErrInvalidRequestBody = errors.New("go-tfe bug: DELETE/PATCH/POST body must be nil, ptr, or ptr slice") + ErrInvalidRequestBody = errors.New("go-tfe bug: DELETE/PATCH/POST body must be nil, ptr, or ptr slice") // ErrInvalidRequestBody is returned when a request body for DELETE/PATCH/POST is not a reference type - // ErrInvalidStructFormat is returned when a mix of json and jsonapi tagged fields are used in the same struct - ErrInvalidStructFormat = errors.New("go-tfe bug: struct can't use both json and jsonapi attributes") + ErrInvalidStructFormat = errors.New("go-tfe bug: struct can't use both json and jsonapi attributes") // ErrInvalidStructFormat is returned when a mix of json and jsonapi tagged fields are used in the same struct ) // Resource Errors + var ( - // ErrWorkspaceLocked is returned when trying to lock a + ErrWorkspaceLocked = errors.New("workspace already locked") // ErrWorkspaceLocked is returned when trying to lock a // locked workspace. - ErrWorkspaceLocked = errors.New("workspace already locked") - // ErrWorkspaceNotLocked is returned when trying to unlock + ErrWorkspaceNotLocked = errors.New("workspace already unlocked") // ErrWorkspaceNotLocked is returned when trying to unlock // a unlocked workspace. - ErrWorkspaceNotLocked = errors.New("workspace already unlocked") - // ErrWorkspaceLockedByRun is returned when trying to unlock a + ErrWorkspaceLockedByRun = errors.New("unable to unlock workspace locked by run") // ErrWorkspaceLockedByRun is returned when trying to unlock a // workspace locked by a run - ErrWorkspaceLockedByRun = errors.New("unable to unlock workspace locked by run") ) // Invalid values for resources/struct fields + var ( ErrInvalidWorkspaceID = errors.New("invalid value for workspace ID") @@ -148,6 +146,7 @@ var ( ) // Missing values for required field/option + var ( ErrRequiredAccess = errors.New("access is required") diff --git a/ip_ranges.go b/ip_ranges.go index 162a797f5..59cc2daf1 100644 --- a/ip_ranges.go +++ b/ip_ranges.go @@ -22,10 +22,12 @@ type IPRanges interface { Read(ctx context.Context, modifiedSince string) (*IPRange, error) } +// ipRanges implements IPRanges interface. type ipRanges struct { client *Client } +// IPRange represents a list of Terraform Cloud's IP ranges type IPRange struct { // List of IP ranges in CIDR notation used for connections from user site to Terraform Cloud APIs API []string `json:"api"` @@ -37,6 +39,7 @@ type IPRange struct { VCS []string `json:"vcs"` } +// 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) if err != nil { diff --git a/organization_membership.go b/organization_membership.go index c0eb004d9..92ade60bd 100644 --- a/organization_membership.go +++ b/organization_membership.go @@ -63,6 +63,7 @@ type OrganizationMembership struct { Teams []*Team `jsonapi:"relation,teams"` } +// A list of relations to include. See available resources // https://www.terraform.io/cloud-docs/api-docs/organization-memberships#available-related-resources type OrganizationMembershipIncludeOps string diff --git a/organization_tags.go b/organization_tags.go index a28f432a9..6890b98ba 100644 --- a/organization_tags.go +++ b/organization_tags.go @@ -9,6 +9,10 @@ import ( var _ OrganizationTags = (*organizationTags)(nil) +// OrganizationMemberships describes all the list of tags used with all resources across the organization. +// +// TFE API docs: +// https://www.terraform.io/cloud-docs/api-docs/organization-tags type OrganizationTags interface { // List all tags within an organization List(ctx context.Context, organization string, options *OrganizationTagsListOptions) (*OrganizationTagsList, error) @@ -20,6 +24,7 @@ type OrganizationTags interface { AddWorkspaces(ctx context.Context, tag string, options AddWorkspacesToTagOptions) error } +// organizationTags implements OrganizationTags. type organizationTags struct { client *Client } @@ -75,7 +80,7 @@ type OrganizationTagsDeleteOptions struct { IDs []string } -// this represents a single tag ID sent over the wire +// tagID represents a single tag ID sent over the wire type tagID struct { ID string `jsonapi:"primary,tags"` } @@ -139,7 +144,7 @@ func (w *AddWorkspacesToTagOptions) valid() error { return nil } -// this represents how workspace IDs will be sent over the wire +// workspaceID represents how workspace IDs will be sent over the wire type workspaceID struct { ID string `jsonapi:"primary,workspaces"` } diff --git a/plan.go b/plan.go index c1355b336..6f3c140aa 100644 --- a/plan.go +++ b/plan.go @@ -15,7 +15,7 @@ var _ Plans = (*plans)(nil) // Plans describes all the plan related methods that the Terraform Enterprise // API supports. // -// TFE API docs: https://www.terraform.io/docs/cloud/api/plan.html +// TFE API docs: https://www.terraform.io/cloud-docs/api-docs/plans type Plans interface { // Read a plan by its ID. Read(ctx context.Context, planID string) (*Plan, error) diff --git a/plan_export.go b/plan_export.go index 1fd837663..0453c972c 100644 --- a/plan_export.go +++ b/plan_export.go @@ -97,6 +97,7 @@ func (o PlanExportCreateOptions) valid() error { return nil } +// Create a plan export. func (s *planExports) Create(ctx context.Context, options PlanExportCreateOptions) (*PlanExport, error) { if err := options.valid(); err != nil { return nil, err diff --git a/policy_set.go b/policy_set.go index 428cf914c..eb36afc58 100644 --- a/policy_set.go +++ b/policy_set.go @@ -13,7 +13,7 @@ var _ PolicySets = (*policySets)(nil) // PolicySets describes all the policy set related methods that the Terraform // Enterprise API supports. // -// TFE API docs: https://www.terraform.io/docs/cloud/api/policies.html +// TFE API docs: https://www.terraform.io/docs/cloud/api/policy-sets.html type PolicySets interface { // List all the policy sets for a given organization. List(ctx context.Context, organization string, options *PolicySetListOptions) (*PolicySetList, error) @@ -186,6 +186,8 @@ func (s *policySets) Create(ctx context.Context, organization string, options Po return ps, err } +// A list of relations to include. See available resources +//https://www.terraform.io/cloud-docs/api-docs/policy-sets#relationships type PolicySetIncludeOps string const ( diff --git a/policy_set_version.go b/policy_set_version.go index c5b7fbc66..35f63f61f 100644 --- a/policy_set_version.go +++ b/policy_set_version.go @@ -64,6 +64,7 @@ type PolicySetVersionStatusTimestamps struct { ErroredAt time.Time `jsonapi:"attr,errored-at,rfc3339"` } +// PolicySetVersion represents a Terraform Enterprise Policy Set Version type PolicySetVersion struct { ID string `jsonapi:"primary,policy-set-versions"` Source PolicySetVersionSource `jsonapi:"attr,source"` diff --git a/state_version_output.go b/state_version_output.go index b88c05a70..5f91d2f2f 100644 --- a/state_version_output.go +++ b/state_version_output.go @@ -18,10 +18,12 @@ type StateVersionOutputs interface { Read(ctx context.Context, outputID string) (*StateVersionOutput, error) } +// stateVersionOutputs implements StateVersionOutputs. type stateVersionOutputs struct { client *Client } +// StateVersionOutput represents a State Version Outputs type StateVersionOutput struct { ID string `jsonapi:"primary,state-version-outputs"` Name string `jsonapi:"attr,name"` @@ -30,6 +32,7 @@ type StateVersionOutput struct { Value interface{} `jsonapi:"attr,value"` } +// Read a State Version Output func (s *stateVersionOutputs) Read(ctx context.Context, outputID string) (*StateVersionOutput, error) { if !validStringID(&outputID) { return nil, ErrInvalidRunID diff --git a/team_access.go b/team_access.go index 6d5f64722..8ec1674fe 100644 --- a/team_access.go +++ b/team_access.go @@ -106,7 +106,6 @@ type TeamAccessListOptions struct { WorkspaceID string `url:"filter[workspace][id]"` } -//check that workspaceID field has a valid value func (o *TeamAccessListOptions) valid() error { if o == nil { return ErrRequiredTeamAccessListOps diff --git a/tfe.go b/tfe.go index 9a6611e60..8fa0993b9 100644 --- a/tfe.go +++ b/tfe.go @@ -28,24 +28,24 @@ import ( ) const ( - _userAgent = "go-tfe" - _headerRateLimit = "X-RateLimit-Limit" - _headerRateReset = "X-RateLimit-Reset" - _headerAPIVersion = "TFP-API-Version" - - // DefaultAddress of Terraform Enterprise. - DefaultAddress = "https://app.terraform.io" - // DefaultBasePath on which the API is served. - DefaultBasePath = "/api/v2/" - // PingEndpoint is a no-op API endpoint used to configure the rate limiter - PingEndpoint = "ping" - IncludeQueryParam = "include" + _userAgent = "go-tfe" + _headerRateLimit = "X-RateLimit-Limit" + _headerRateReset = "X-RateLimit-Reset" + _headerAPIVersion = "TFP-API-Version" + _includeQueryParam = "include" + + DefaultAddress = "https://app.terraform.io" // DefaultAddress of Terraform Enterprise. + DefaultBasePath = "/api/v2/" // DefaultBasePath on which the API is served. + PingEndpoint = "ping" // PingEndpoint is a no-op API endpoint used to configure the rate limiter + ) // RetryLogHook allows a function to run before each retry. + type RetryLogHook func(attemptNum int, resp *http.Response) // Config provides configuration details to the API client. + type Config struct { // The address of the Terraform Enterprise API. Address string @@ -67,6 +67,7 @@ type Config struct { } // DefaultConfig returns a default config structure. + func DefaultConfig() *Config { config := &Config{ Address: os.Getenv("TFE_ADDRESS"), @@ -88,7 +89,7 @@ func DefaultConfig() *Config { } // Client is the Terraform Enterprise API client. It provides the basic -// connectivity and configuration for accessing the TFE API. +// connectivity and configuration for accessing the TFE API type Client struct { baseURL *url.URL token string @@ -143,7 +144,7 @@ type Client struct { // Admin is the the Terraform Enterprise Admin API. It provides access to site // wide admin settings. These are only available for Terraform Enterprise and -// do not function against Terraform Cloud. +// do not function against Terraform Cloud type Admin struct { Organizations AdminOrganizations Workspaces AdminWorkspaces @@ -310,18 +311,21 @@ func (c *Client) RemoteAPIVersion() string { // // This is intended for use in tests, when you may want to configure your TFE client to // return something different than the actual API version in order to test error handling. + func (c *Client) SetFakeRemoteAPIVersion(fakeAPIVersion string) { c.remoteAPIVersion = fakeAPIVersion } // RetryServerErrors configures the retry HTTP check to also retry // unexpected errors or requests that failed with a server error. + func (c *Client) RetryServerErrors(retry bool) { c.retryServerErrors = retry } // retryHTTPCheck provides a callback for Client.CheckRetry which // will retry both rate limit (429) and server (>= 500) errors. + func (c *Client) retryHTTPCheck(ctx context.Context, resp *http.Response, err error) (bool, error) { if ctx.Err() != nil { return false, ctx.Err() @@ -337,6 +341,7 @@ func (c *Client) retryHTTPCheck(ctx context.Context, resp *http.Response, err er // retryHTTPBackoff provides a generic callback for Client.Backoff which // will pass through all calls based on the status code of the response. + func (c *Client) retryHTTPBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration { if c.retryLogHook != nil { c.retryLogHook(attemptNum, resp) @@ -361,6 +366,7 @@ func (c *Client) retryHTTPBackoff(min, max time.Duration, attemptNum int, resp * // min and max are mainly used for bounding the jitter that will be added to // the reset time retrieved from the headers. But if the final wait time is // less then min, min will be used instead. + func rateLimitBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration { // rnd is used to generate pseudo-random numbers. rnd := rand.New(rand.NewSource(time.Now().UnixNano())) @@ -429,6 +435,7 @@ func (c *Client) getRawAPIMetadata() (rawAPIMetadata, error) { } // configureLimiter configures the rate limiter. + func (c *Client) configureLimiter(rawLimit string) { // Set default values for when rate limiting is disabled. limit := rate.Inf @@ -519,6 +526,7 @@ func (c *Client) newRequest(method, path string, v interface{}) (*retryablehttp. // Encode encodes the values into ``URL encoded'' form // ("bar=baz&foo=quux") sorted by key. + func encodeQueryParams(v url.Values) string { if v == nil { return "" @@ -531,7 +539,7 @@ func encodeQueryParams(v url.Values) string { sort.Strings(keys) for _, k := range keys { vs := v[k] - if len(vs) > 1 && k == IncludeQueryParam { + if len(vs) > 1 && k == _includeQueryParam { val := strings.Join(vs, ",") vs = vs[:0] vs = append(vs, val) @@ -553,6 +561,7 @@ func encodeQueryParams(v url.Values) string { // Helper method that 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 @@ -616,6 +625,7 @@ func serializeRequestBody(v interface{}) (interface{}, error) { // // 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. @@ -753,6 +763,7 @@ func parsePagination(body io.Reader) (*Pagination, error) { } // checkResponseCode can be used to check the status code of an HTTP request. + func checkResponseCode(r *http.Response) error { if r.StatusCode >= 200 && r.StatusCode <= 299 { return nil diff --git a/validations.go b/validations.go index 38d95a681..ec15f8932 100644 --- a/validations.go +++ b/validations.go @@ -5,15 +5,18 @@ import ( ) // A regular expression used to validate common string ID patterns. + var reStringID = regexp.MustCompile(`^[a-zA-Z0-9\-\._]+$`) // validString checks if the given input is present and non-empty. + func validString(v *string) bool { return v != nil && *v != "" } // validStringID checks if the given string pointer is non-nil and // contains a typical string identifier. + func validStringID(v *string) bool { return v != nil && reStringID.MatchString(*v) }