File: agent.go

package info (click to toggle)
glab 1.53.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 20,936 kB
  • sloc: sh: 295; makefile: 153; perl: 99; ruby: 68; javascript: 67
file content (116 lines) | stat: -rw-r--r-- 2,953 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
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 interface{}, 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 interface{}, 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 interface{}, 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 interface{}, 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 interface{}, 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)
}