api/agent.go (91 lines of code) (raw):
package api
import (
"errors"
"fmt"
"slices"
"time"
gitlab "gitlab.com/gitlab-org/api/client-go"
)
// agentTokenLimit specifies the maximal amount of agent tokens that can be active per agent at any given time.
const agentTokenLimit = 2
var AgentNotFoundErr = errors.New("agent not found")
var ListAgents = func(client *gitlab.Client, projectID any, opts *gitlab.ListAgentsOptions) ([]*gitlab.Agent, error) {
if client == nil {
client = apiClient.Lab()
}
agents, _, err := client.ClusterAgents.ListAgents(projectID, opts)
if err != nil {
return nil, err
}
return agents, nil
}
var GetAgent = func(client *gitlab.Client, projectID any, agentID int) (*gitlab.Agent, error) {
if client == nil {
client = apiClient.Lab()
}
agent, _, err := client.ClusterAgents.GetAgent(projectID, agentID)
if err != nil {
return nil, err
}
return agent, nil
}
var GetAgentByName = func(client *gitlab.Client, projectID any, agentName string) (*gitlab.Agent, error) {
opts := &gitlab.ListAgentsOptions{
Page: 1,
PerPage: 100,
}
for opts.Page != 0 {
paginatedAgents, resp, err := client.ClusterAgents.ListAgents(projectID, opts)
if err != nil {
return nil, err
}
for _, agent := range paginatedAgents {
if agent.Name == agentName {
// found
return agent, nil
}
}
opts.Page = resp.NextPage
}
return nil, AgentNotFoundErr
}
var RegisterAgent = func(client *gitlab.Client, projectID any, agentName string) (*gitlab.Agent, error) {
if client == nil {
client = apiClient.Lab()
}
agent, _, err := client.ClusterAgents.RegisterAgent(projectID, &gitlab.RegisterAgentOptions{Name: gitlab.Ptr(agentName)})
if err != nil {
return nil, err
}
return agent, nil
}
var CreateAgentToken = func(client *gitlab.Client, projectID any, agentID int, recreateOnLimit bool) (*gitlab.AgentToken, bool /* recreated */, error) {
recreated := false
if recreateOnLimit {
tokens, _, err := client.ClusterAgents.ListAgentTokens(projectID, agentID, &gitlab.ListAgentTokensOptions{PerPage: agentTokenLimit})
if err != nil {
return nil, false, err
}
if len(tokens) == agentTokenLimit {
slices.SortFunc(tokens, agentTokenSortFunc)
longestUnusedToken := tokens[0]
_, err := client.ClusterAgents.RevokeAgentToken(projectID, agentID, longestUnusedToken.ID)
if err != nil {
return nil, false, err
}
recreated = true
}
}
// create new token
token, _, err := client.ClusterAgents.CreateAgentToken(projectID, agentID, &gitlab.CreateAgentTokenOptions{
Name: gitlab.Ptr(fmt.Sprintf("glab-bootstrap-%d", time.Now().UTC().Unix())),
Description: gitlab.Ptr("Created by the `glab cluster agent bootstrap command"),
})
return token, recreated, err
}
func agentTokenSortFunc(a, b *gitlab.AgentToken) int {
if a.LastUsedAt == nil {
return 1
}
if b.LastUsedAt == nil {
return -1
}
return a.LastUsedAt.Compare(*b.LastUsedAt)
}