1package tfe 2 3import ( 4 "context" 5 "errors" 6 "fmt" 7 "net/url" 8 "time" 9) 10 11// Compile-time proof of interface implementation. 12var _ AgentTokens = (*agentTokens)(nil) 13 14// AgentTokens describes all the agent token related methods that the 15// Terraform Cloud API supports. 16// 17// TFE API docs: 18// https://www.terraform.io/docs/cloud/api/agent-tokens.html 19type AgentTokens interface { 20 // List all the agent tokens of the given agent pool. 21 List(ctx context.Context, agentPoolID string) (*AgentTokenList, error) 22 23 // Generate a new agent token with the given options. 24 Generate(ctx context.Context, agentPoolID string, options AgentTokenGenerateOptions) (*AgentToken, error) 25 26 // Read an agent token by its ID. 27 Read(ctx context.Context, agentTokenID string) (*AgentToken, error) 28 29 // Delete an agent token by its ID. 30 Delete(ctx context.Context, agentTokenID string) error 31} 32 33// agentTokens implements AgentTokens. 34type agentTokens struct { 35 client *Client 36} 37 38// AgentTokenList represents a list of agent tokens. 39type AgentTokenList struct { 40 *Pagination 41 Items []*AgentToken 42} 43 44// AgentToken represents a Terraform Cloud agent token. 45type AgentToken struct { 46 ID string `jsonapi:"primary,authentication-tokens"` 47 CreatedAt time.Time `jsonapi:"attr,created-at,iso8601"` 48 Description string `jsonapi:"attr,description"` 49 LastUsedAt time.Time `jsonapi:"attr,last-used-at,iso8601"` 50 Token string `jsonapi:"attr,token"` 51} 52 53// List all the agent tokens of the given agent pool. 54func (s *agentTokens) List(ctx context.Context, agentPoolID string) (*AgentTokenList, error) { 55 if !validStringID(&agentPoolID) { 56 return nil, errors.New("invalid value for agent pool ID") 57 } 58 59 u := fmt.Sprintf("agent-pools/%s/authentication-tokens", url.QueryEscape(agentPoolID)) 60 req, err := s.client.newRequest("GET", u, nil) 61 if err != nil { 62 return nil, err 63 } 64 65 tokenList := &AgentTokenList{} 66 err = s.client.do(ctx, req, tokenList) 67 if err != nil { 68 return nil, err 69 } 70 71 return tokenList, nil 72} 73 74// AgentTokenGenerateOptions represents the options for creating an agent token. 75type AgentTokenGenerateOptions struct { 76 // For internal use only! 77 ID string `jsonapi:"primary,agent-tokens"` 78 79 // Description of the token 80 Description *string `jsonapi:"attr,description"` 81} 82 83// Generate a new agent token with the given options. 84func (s *agentTokens) Generate(ctx context.Context, agentPoolID string, options AgentTokenGenerateOptions) (*AgentToken, error) { 85 if !validStringID(&agentPoolID) { 86 return nil, errors.New("invalid value for agent pool ID") 87 } 88 89 if !validString(options.Description) { 90 return nil, errors.New("agent token description can't be blank") 91 } 92 93 // Make sure we don't send a user provided ID. 94 options.ID = "" 95 96 u := fmt.Sprintf("agent-pools/%s/authentication-tokens", url.QueryEscape(agentPoolID)) 97 req, err := s.client.newRequest("POST", u, &options) 98 if err != nil { 99 return nil, err 100 } 101 102 at := &AgentToken{} 103 err = s.client.do(ctx, req, at) 104 if err != nil { 105 return nil, err 106 } 107 108 return at, err 109} 110 111// Read an agent token by its ID. 112func (s *agentTokens) Read(ctx context.Context, agentTokenID string) (*AgentToken, error) { 113 if !validStringID(&agentTokenID) { 114 return nil, errors.New("invalid value for agent token ID") 115 } 116 117 u := fmt.Sprintf("authentication-tokens/%s", url.QueryEscape(agentTokenID)) 118 req, err := s.client.newRequest("GET", u, nil) 119 if err != nil { 120 return nil, err 121 } 122 123 at := &AgentToken{} 124 err = s.client.do(ctx, req, at) 125 if err != nil { 126 return nil, err 127 } 128 129 return at, err 130} 131 132// Delete an agent token by its ID. 133func (s *agentTokens) Delete(ctx context.Context, agentTokenID string) error { 134 if !validStringID(&agentTokenID) { 135 return errors.New("invalid value for agent token ID") 136 } 137 138 u := fmt.Sprintf("authentication-tokens/%s", url.QueryEscape(agentTokenID)) 139 req, err := s.client.newRequest("DELETE", u, nil) 140 if err != nil { 141 return err 142 } 143 144 return s.client.do(ctx, req, nil) 145} 146