commands/cluster/agent/bootstrap/api_wrapper.go (145 lines of code) (raw):

package bootstrap import ( "encoding/base64" "errors" "fmt" "slices" gitlab "gitlab.com/gitlab-org/api/client-go" glab_api "gitlab.com/gitlab-org/cli/api" "gopkg.in/yaml.v3" ) var _ API = (*apiWrapper)(nil) func NewAPI(client *gitlab.Client, projectID any) API { return &apiWrapper{client: client, projectID: projectID} } type apiWrapper struct { client *gitlab.Client projectID any } func (a *apiWrapper) GetDefaultBranch() (string, error) { project, err := glab_api.GetProject(a.client, a.projectID) if err != nil { return "", err } return project.DefaultBranch, nil } func (a *apiWrapper) GetAgentByName(name string) (*gitlab.Agent, error) { return glab_api.GetAgentByName(a.client, a.projectID, name) } func (a *apiWrapper) RegisterAgent(name string) (*gitlab.Agent, error) { return glab_api.RegisterAgent(a.client, a.projectID, name) } type agentConfig struct { UserAccess *agentConfigUserAccess `yaml:"user_access"` } type agentConfigUserAccess struct { AccessAs *agentConfigAccessAs `yaml:"access_as"` Projects []*agentConfigProject `yaml:"projects"` } type agentConfigAccessAs struct { Agent struct{} } type agentConfigProject struct { ID string `yaml:"id"` } func (a *apiWrapper) ConfigureAgent(agent *gitlab.Agent, branch string) error { configPath := fmt.Sprintf(".gitlab/agents/%s/config.yaml", agent.Name) file, err := glab_api.GetFile(a.client, a.projectID, configPath, branch) if err != nil && !glab_api.Is404(err) { return err } cfg := agentConfig{} if glab_api.Is404(err) { cfg.UserAccess = &agentConfigUserAccess{ AccessAs: &agentConfigAccessAs{Agent: struct{}{}}, Projects: []*agentConfigProject{ { ID: agent.ConfigProject.PathWithNamespace, }, }, } configuredContent, err := yaml.Marshal(cfg) if err != nil { return err } return glab_api.CreateFile(a.client, a.projectID, configPath, configuredContent, branch) } else { content, err := base64.StdEncoding.DecodeString(file.Content) if err != nil { return err } err = yaml.Unmarshal(content, &cfg) if err != nil { return err } if cfg.UserAccess == nil { cfg.UserAccess = &agentConfigUserAccess{ AccessAs: &agentConfigAccessAs{Agent: struct{}{}}, } } if !slices.ContainsFunc(cfg.UserAccess.Projects, func(p *agentConfigProject) bool { return p.ID == agent.ConfigProject.PathWithNamespace }) { cfg.UserAccess.Projects = append(cfg.UserAccess.Projects, &agentConfigProject{ID: agent.ConfigProject.PathWithNamespace}) } configuredContent, err := yaml.Marshal(cfg) if err != nil { return err } return glab_api.UpdateFile(a.client, a.projectID, configPath, configuredContent, branch) } } func (a *apiWrapper) ConfigureEnvironment(agentID int, name string, kubernetesNamespace string, fluxResourcePath string) error { env, err := a.getEnvironmentByName(name) if err != nil { return err } if env == nil { _, _, err := a.client.Environments.CreateEnvironment(a.projectID, &gitlab.CreateEnvironmentOptions{ Name: gitlab.Ptr(name), ClusterAgentID: gitlab.Ptr(agentID), KubernetesNamespace: gitlab.Ptr(kubernetesNamespace), FluxResourcePath: gitlab.Ptr(fluxResourcePath), }) return err } else { _, _, err := a.client.Environments.EditEnvironment(a.projectID, env.ID, &gitlab.EditEnvironmentOptions{ Name: gitlab.Ptr(name), ClusterAgentID: gitlab.Ptr(agentID), KubernetesNamespace: gitlab.Ptr(kubernetesNamespace), FluxResourcePath: gitlab.Ptr(fluxResourcePath), }) return err } } func (a *apiWrapper) CreateAgentToken(agentID int) (*gitlab.AgentToken, error) { token, _, err := glab_api.CreateAgentToken(a.client, a.projectID, agentID, true) return token, err } func (a *apiWrapper) SyncFile(f file, branch string) error { return glab_api.SyncFile(a.client, a.projectID, f.path, f.content, branch) } func (a *apiWrapper) GetKASAddress() (string, error) { metadata, err := glab_api.GetMetadata(a.client) if err != nil { return "", err } if !metadata.KAS.Enabled { return "", errors.New("KAS is not configured in this GitLab instance. Please contact your administrator.") } return metadata.KAS.ExternalURL, nil } func (a *apiWrapper) getEnvironmentByName(name string) (*gitlab.Environment, error) { opts := &gitlab.ListEnvironmentsOptions{ Name: gitlab.Ptr(name), } envs, _, err := a.client.Environments.ListEnvironments(a.projectID, opts) if err != nil { if glab_api.Is404(err) { return nil, nil } return nil, err } if len(envs) == 0 { return nil, nil } return envs[0], nil }