commit
e49b35d3d0
351 changed files with 17734 additions and 61881 deletions
2
Makefile
2
Makefile
|
|
@ -106,7 +106,7 @@ $(LOCALBIN):
|
|||
GOLANGCI_LINT ?= $(LOCALBIN)/golangci-lint
|
||||
|
||||
## Tool Versions
|
||||
GOLANGCI_LINT_VERSION ?= v1.61.0
|
||||
GOLANGCI_LINT_VERSION ?= v1.64.8
|
||||
|
||||
.PHONY: golangci-lint
|
||||
golangci-lint: $(GOLANGCI_LINT) ## Download golangci-lint locally if necessary. If wrong version is installed, it will be overwritten.
|
||||
|
|
|
|||
|
|
@ -277,6 +277,62 @@ func (a *APIController) CreateEnterprisePoolHandler(w http.ResponseWriter, r *ht
|
|||
}
|
||||
}
|
||||
|
||||
// swagger:route POST /enterprises/{enterpriseID}/scalesets enterprises scalesets CreateEnterpriseScaleSet
|
||||
//
|
||||
// Create enterprise pool with the parameters given.
|
||||
//
|
||||
// Parameters:
|
||||
// + name: enterpriseID
|
||||
// description: Enterprise ID.
|
||||
// type: string
|
||||
// in: path
|
||||
// required: true
|
||||
//
|
||||
// + name: Body
|
||||
// description: Parameters used when creating the enterprise scale set.
|
||||
// type: CreateScaleSetParams
|
||||
// in: body
|
||||
// required: true
|
||||
//
|
||||
// Responses:
|
||||
// 200: ScaleSet
|
||||
// default: APIErrorResponse
|
||||
func (a *APIController) CreateEnterpriseScaleSetHandler(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
vars := mux.Vars(r)
|
||||
enterpriseID, ok := vars["enterpriseID"]
|
||||
if !ok {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(params.APIErrorResponse{
|
||||
Error: "Bad Request",
|
||||
Details: "No enterprise ID specified",
|
||||
}); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var scaleSetData runnerParams.CreateScaleSetParams
|
||||
if err := json.NewDecoder(r.Body).Decode(&scaleSetData); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to decode")
|
||||
handleError(ctx, w, gErrors.ErrBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
scaleSet, err := a.r.CreateEntityScaleSet(ctx, runnerParams.GithubEntityTypeEnterprise, enterpriseID, scaleSetData)
|
||||
if err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "error creating enterprise scale set")
|
||||
handleError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err := json.NewEncoder(w).Encode(scaleSet); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
|
||||
}
|
||||
}
|
||||
|
||||
// swagger:route GET /enterprises/{enterpriseID}/pools enterprises pools ListEnterprisePools
|
||||
//
|
||||
// List enterprise pools.
|
||||
|
|
@ -319,6 +375,48 @@ func (a *APIController) ListEnterprisePoolsHandler(w http.ResponseWriter, r *htt
|
|||
}
|
||||
}
|
||||
|
||||
// swagger:route GET /enterprises/{enterpriseID}/scalesets enterprises scalesets ListEnterpriseScaleSets
|
||||
//
|
||||
// List enterprise scale sets.
|
||||
//
|
||||
// Parameters:
|
||||
// + name: enterpriseID
|
||||
// description: Enterprise ID.
|
||||
// type: string
|
||||
// in: path
|
||||
// required: true
|
||||
//
|
||||
// Responses:
|
||||
// 200: ScaleSets
|
||||
// default: APIErrorResponse
|
||||
func (a *APIController) ListEnterpriseScaleSetsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
vars := mux.Vars(r)
|
||||
enterpriseID, ok := vars["enterpriseID"]
|
||||
if !ok {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(params.APIErrorResponse{
|
||||
Error: "Bad Request",
|
||||
Details: "No enterprise ID specified",
|
||||
}); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
scaleSets, err := a.r.ListEntityScaleSets(ctx, runnerParams.GithubEntityTypeEnterprise, enterpriseID)
|
||||
if err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "listing scale sets")
|
||||
handleError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err := json.NewEncoder(w).Encode(scaleSets); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
|
||||
}
|
||||
}
|
||||
|
||||
// swagger:route GET /enterprises/{enterpriseID}/pools/{poolID} enterprises pools GetEnterprisePool
|
||||
//
|
||||
// Get enterprise pool by ID.
|
||||
|
|
|
|||
|
|
@ -69,6 +69,54 @@ func (a *APIController) ListPoolInstancesHandler(w http.ResponseWriter, r *http.
|
|||
}
|
||||
}
|
||||
|
||||
// swagger:route GET /scalesets/{scalesetID}/instances instances ListScaleSetInstances
|
||||
//
|
||||
// List runner instances in a scale set.
|
||||
//
|
||||
// Parameters:
|
||||
// + name: scalesetID
|
||||
// description: Runner scale set ID.
|
||||
// type: string
|
||||
// in: path
|
||||
// required: true
|
||||
//
|
||||
// Responses:
|
||||
// 200: Instances
|
||||
// default: APIErrorResponse
|
||||
func (a *APIController) ListScaleSetInstancesHandler(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
vars := mux.Vars(r)
|
||||
scalesetID, ok := vars["scalesetID"]
|
||||
if !ok {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(params.APIErrorResponse{
|
||||
Error: "Bad Request",
|
||||
Details: "No pool ID specified",
|
||||
}); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
|
||||
}
|
||||
return
|
||||
}
|
||||
id, err := strconv.ParseUint(scalesetID, 10, 32)
|
||||
if err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to parse id")
|
||||
handleError(ctx, w, gErrors.ErrBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
instances, err := a.r.ListScaleSetInstances(ctx, uint(id))
|
||||
if err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "listing pool instances")
|
||||
handleError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err := json.NewEncoder(w).Encode(instances); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
|
||||
}
|
||||
}
|
||||
|
||||
// swagger:route GET /instances/{instanceName} instances GetInstance
|
||||
//
|
||||
// Get runner instance by name.
|
||||
|
|
|
|||
|
|
@ -287,6 +287,62 @@ func (a *APIController) CreateOrgPoolHandler(w http.ResponseWriter, r *http.Requ
|
|||
}
|
||||
}
|
||||
|
||||
// swagger:route POST /organizations/{orgID}/scalesets organizations scalesets CreateOrgScaleSet
|
||||
//
|
||||
// Create organization scale set with the parameters given.
|
||||
//
|
||||
// Parameters:
|
||||
// + name: orgID
|
||||
// description: Organization ID.
|
||||
// type: string
|
||||
// in: path
|
||||
// required: true
|
||||
//
|
||||
// + name: Body
|
||||
// description: Parameters used when creating the organization scale set.
|
||||
// type: CreateScaleSetParams
|
||||
// in: body
|
||||
// required: true
|
||||
//
|
||||
// Responses:
|
||||
// 200: ScaleSet
|
||||
// default: APIErrorResponse
|
||||
func (a *APIController) CreateOrgScaleSetHandler(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
vars := mux.Vars(r)
|
||||
orgID, ok := vars["orgID"]
|
||||
if !ok {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(params.APIErrorResponse{
|
||||
Error: "Bad Request",
|
||||
Details: "No org ID specified",
|
||||
}); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var scalesetData runnerParams.CreateScaleSetParams
|
||||
if err := json.NewDecoder(r.Body).Decode(&scalesetData); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to decode")
|
||||
handleError(ctx, w, gErrors.ErrBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
scaleSet, err := a.r.CreateEntityScaleSet(ctx, runnerParams.GithubEntityTypeOrganization, orgID, scalesetData)
|
||||
if err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "error creating organization scale set")
|
||||
handleError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err := json.NewEncoder(w).Encode(scaleSet); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
|
||||
}
|
||||
}
|
||||
|
||||
// swagger:route GET /organizations/{orgID}/pools organizations pools ListOrgPools
|
||||
//
|
||||
// List organization pools.
|
||||
|
|
@ -329,6 +385,48 @@ func (a *APIController) ListOrgPoolsHandler(w http.ResponseWriter, r *http.Reque
|
|||
}
|
||||
}
|
||||
|
||||
// swagger:route GET /organizations/{orgID}/scalesets organizations scalesets ListOrgScaleSets
|
||||
//
|
||||
// List organization scale sets.
|
||||
//
|
||||
// Parameters:
|
||||
// + name: orgID
|
||||
// description: Organization ID.
|
||||
// type: string
|
||||
// in: path
|
||||
// required: true
|
||||
//
|
||||
// Responses:
|
||||
// 200: ScaleSets
|
||||
// default: APIErrorResponse
|
||||
func (a *APIController) ListOrgScaleSetsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
vars := mux.Vars(r)
|
||||
orgID, ok := vars["orgID"]
|
||||
if !ok {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(params.APIErrorResponse{
|
||||
Error: "Bad Request",
|
||||
Details: "No org ID specified",
|
||||
}); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
scaleSets, err := a.r.ListEntityScaleSets(ctx, runnerParams.GithubEntityTypeOrganization, orgID)
|
||||
if err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "listing scale sets")
|
||||
handleError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err := json.NewEncoder(w).Encode(scaleSets); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
|
||||
}
|
||||
}
|
||||
|
||||
// swagger:route GET /organizations/{orgID}/pools/{poolID} organizations pools GetOrgPool
|
||||
//
|
||||
// Get organization pool by ID.
|
||||
|
|
|
|||
|
|
@ -286,6 +286,62 @@ func (a *APIController) CreateRepoPoolHandler(w http.ResponseWriter, r *http.Req
|
|||
}
|
||||
}
|
||||
|
||||
// swagger:route POST /repositories/{repoID}/scalesets repositories scalesets CreateRepoScaleSet
|
||||
//
|
||||
// Create repository scale set with the parameters given.
|
||||
//
|
||||
// Parameters:
|
||||
// + name: repoID
|
||||
// description: Repository ID.
|
||||
// type: string
|
||||
// in: path
|
||||
// required: true
|
||||
//
|
||||
// + name: Body
|
||||
// description: Parameters used when creating the repository scale set.
|
||||
// type: CreateScaleSetParams
|
||||
// in: body
|
||||
// required: true
|
||||
//
|
||||
// Responses:
|
||||
// 200: ScaleSet
|
||||
// default: APIErrorResponse
|
||||
func (a *APIController) CreateRepoScaleSetHandler(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
vars := mux.Vars(r)
|
||||
repoID, ok := vars["repoID"]
|
||||
if !ok {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(params.APIErrorResponse{
|
||||
Error: "Bad Request",
|
||||
Details: "No repo ID specified",
|
||||
}); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
var scaleSetData runnerParams.CreateScaleSetParams
|
||||
if err := json.NewDecoder(r.Body).Decode(&scaleSetData); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to decode")
|
||||
handleError(ctx, w, gErrors.ErrBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
scaleSet, err := a.r.CreateEntityScaleSet(ctx, runnerParams.GithubEntityTypeRepository, repoID, scaleSetData)
|
||||
if err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "error creating repository scale set")
|
||||
handleError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err := json.NewEncoder(w).Encode(scaleSet); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
|
||||
}
|
||||
}
|
||||
|
||||
// swagger:route GET /repositories/{repoID}/pools repositories pools ListRepoPools
|
||||
//
|
||||
// List repository pools.
|
||||
|
|
@ -328,6 +384,48 @@ func (a *APIController) ListRepoPoolsHandler(w http.ResponseWriter, r *http.Requ
|
|||
}
|
||||
}
|
||||
|
||||
// swagger:route GET /repositories/{repoID}/scalesets repositories scalesets ListRepoScaleSets
|
||||
//
|
||||
// List repository scale sets.
|
||||
//
|
||||
// Parameters:
|
||||
// + name: repoID
|
||||
// description: Repository ID.
|
||||
// type: string
|
||||
// in: path
|
||||
// required: true
|
||||
//
|
||||
// Responses:
|
||||
// 200: ScaleSets
|
||||
// default: APIErrorResponse
|
||||
func (a *APIController) ListRepoScaleSetsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
vars := mux.Vars(r)
|
||||
repoID, ok := vars["repoID"]
|
||||
if !ok {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(params.APIErrorResponse{
|
||||
Error: "Bad Request",
|
||||
Details: "No repo ID specified",
|
||||
}); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
scaleSets, err := a.r.ListEntityScaleSets(ctx, runnerParams.GithubEntityTypeRepository, repoID)
|
||||
if err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "listing scale sets")
|
||||
handleError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err := json.NewEncoder(w).Encode(scaleSets); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
|
||||
}
|
||||
}
|
||||
|
||||
// swagger:route GET /repositories/{repoID}/pools/{poolID} repositories pools GetRepoPool
|
||||
//
|
||||
// Get repository pool by ID.
|
||||
|
|
|
|||
211
apiserver/controllers/scalesets.go
Normal file
211
apiserver/controllers/scalesets.go
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
// Copyright 2022 Cloudbase Solutions SRL
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package controllers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/gorilla/mux"
|
||||
|
||||
gErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
"github.com/cloudbase/garm/apiserver/params"
|
||||
runnerParams "github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
// swagger:route GET /scalesets scalesets ListScalesets
|
||||
//
|
||||
// List all scalesets.
|
||||
//
|
||||
// Responses:
|
||||
// 200: ScaleSets
|
||||
// default: APIErrorResponse
|
||||
func (a *APIController) ListAllScaleSetsHandler(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
scalesets, err := a.r.ListAllScaleSets(ctx)
|
||||
if err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "listing scale sets")
|
||||
handleError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err := json.NewEncoder(w).Encode(scalesets); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
|
||||
}
|
||||
}
|
||||
|
||||
// swagger:route GET /scalesets/{scalesetID} scalesets GetScaleSet
|
||||
//
|
||||
// Get scale set by ID.
|
||||
//
|
||||
// Parameters:
|
||||
// + name: scalesetID
|
||||
// description: ID of the scale set to fetch.
|
||||
// type: string
|
||||
// in: path
|
||||
// required: true
|
||||
//
|
||||
// Responses:
|
||||
// 200: ScaleSet
|
||||
// default: APIErrorResponse
|
||||
func (a *APIController) GetScaleSetByIDHandler(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
vars := mux.Vars(r)
|
||||
scaleSetID, ok := vars["scalesetID"]
|
||||
if !ok {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(params.APIErrorResponse{
|
||||
Error: "Bad Request",
|
||||
Details: "No scale set ID specified",
|
||||
}); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
|
||||
}
|
||||
return
|
||||
}
|
||||
id, err := strconv.ParseUint(scaleSetID, 10, 32)
|
||||
if err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to parse id")
|
||||
handleError(ctx, w, gErrors.ErrBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
scaleSet, err := a.r.GetScaleSetByID(ctx, uint(id))
|
||||
if err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "fetching scale set")
|
||||
handleError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
scaleSet.RunnerBootstrapTimeout = scaleSet.RunnerTimeout()
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err := json.NewEncoder(w).Encode(scaleSet); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
|
||||
}
|
||||
}
|
||||
|
||||
// swagger:route DELETE /scalesets/{scalesetID} scalesets DeleteScaleSet
|
||||
//
|
||||
// Delete scale set by ID.
|
||||
//
|
||||
// Parameters:
|
||||
// + name: scalesetID
|
||||
// description: ID of the scale set to delete.
|
||||
// type: string
|
||||
// in: path
|
||||
// required: true
|
||||
//
|
||||
// Responses:
|
||||
// default: APIErrorResponse
|
||||
func (a *APIController) DeleteScaleSetByIDHandler(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
vars := mux.Vars(r)
|
||||
scalesetID, ok := vars["scalesetID"]
|
||||
if !ok {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(params.APIErrorResponse{
|
||||
Error: "Bad Request",
|
||||
Details: "No scale set ID specified",
|
||||
}); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
id, err := strconv.ParseUint(scalesetID, 10, 32)
|
||||
if err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to parse id")
|
||||
handleError(ctx, w, gErrors.ErrBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if err := a.r.DeleteScaleSetByID(ctx, uint(id)); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "removing scale set")
|
||||
handleError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
w.WriteHeader(http.StatusOK)
|
||||
}
|
||||
|
||||
// swagger:route PUT /scalesets/{scalesetID} scalesets UpdateScaleSet
|
||||
//
|
||||
// Update scale set by ID.
|
||||
//
|
||||
// Parameters:
|
||||
// + name: scalesetID
|
||||
// description: ID of the scale set to update.
|
||||
// type: string
|
||||
// in: path
|
||||
// required: true
|
||||
//
|
||||
// + name: Body
|
||||
// description: Parameters to update the scale set with.
|
||||
// type: UpdateScaleSetParams
|
||||
// in: body
|
||||
// required: true
|
||||
//
|
||||
// Responses:
|
||||
// 200: ScaleSet
|
||||
// default: APIErrorResponse
|
||||
func (a *APIController) UpdateScaleSetByIDHandler(w http.ResponseWriter, r *http.Request) {
|
||||
ctx := r.Context()
|
||||
|
||||
vars := mux.Vars(r)
|
||||
scalesetID, ok := vars["scalesetID"]
|
||||
if !ok {
|
||||
w.WriteHeader(http.StatusBadRequest)
|
||||
if err := json.NewEncoder(w).Encode(params.APIErrorResponse{
|
||||
Error: "Bad Request",
|
||||
Details: "No scale set ID specified",
|
||||
}); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
id, err := strconv.ParseUint(scalesetID, 10, 32)
|
||||
if err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to parse id")
|
||||
handleError(ctx, w, gErrors.ErrBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
var scaleSetData runnerParams.UpdateScaleSetParams
|
||||
if err := json.NewDecoder(r.Body).Decode(&scaleSetData); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to decode")
|
||||
handleError(ctx, w, gErrors.ErrBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
scaleSet, err := a.r.UpdateScaleSetByID(ctx, uint(id), scaleSetData)
|
||||
if err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "updating scale set")
|
||||
handleError(ctx, w, err)
|
||||
return
|
||||
}
|
||||
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err := json.NewEncoder(w).Encode(scaleSet); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to encode response")
|
||||
}
|
||||
}
|
||||
|
|
@ -214,6 +214,25 @@ func NewAPIRouter(han *controllers.APIController, authMiddleware, initMiddleware
|
|||
apiRouter.Handle("/pools/{poolID}/instances/", http.HandlerFunc(han.ListPoolInstancesHandler)).Methods("GET", "OPTIONS")
|
||||
apiRouter.Handle("/pools/{poolID}/instances", http.HandlerFunc(han.ListPoolInstancesHandler)).Methods("GET", "OPTIONS")
|
||||
|
||||
////////////////
|
||||
// Scale sets //
|
||||
////////////////
|
||||
// List all pools
|
||||
apiRouter.Handle("/scalesets/", http.HandlerFunc(han.ListAllScaleSetsHandler)).Methods("GET", "OPTIONS")
|
||||
apiRouter.Handle("/scalesets", http.HandlerFunc(han.ListAllScaleSetsHandler)).Methods("GET", "OPTIONS")
|
||||
// Get one pool
|
||||
apiRouter.Handle("/scalesets/{scalesetID}/", http.HandlerFunc(han.GetScaleSetByIDHandler)).Methods("GET", "OPTIONS")
|
||||
apiRouter.Handle("/scalesets/{scalesetID}", http.HandlerFunc(han.GetScaleSetByIDHandler)).Methods("GET", "OPTIONS")
|
||||
// Delete one pool
|
||||
apiRouter.Handle("/scalesets/{scalesetID}/", http.HandlerFunc(han.DeleteScaleSetByIDHandler)).Methods("DELETE", "OPTIONS")
|
||||
apiRouter.Handle("/scalesets/{scalesetID}", http.HandlerFunc(han.DeleteScaleSetByIDHandler)).Methods("DELETE", "OPTIONS")
|
||||
// Update one pool
|
||||
apiRouter.Handle("/scalesets/{scalesetID}/", http.HandlerFunc(han.UpdateScaleSetByIDHandler)).Methods("PUT", "OPTIONS")
|
||||
apiRouter.Handle("/scalesets/{scalesetID}", http.HandlerFunc(han.UpdateScaleSetByIDHandler)).Methods("PUT", "OPTIONS")
|
||||
// List pool instances
|
||||
apiRouter.Handle("/scalesets/{scalesetID}/instances/", http.HandlerFunc(han.ListScaleSetInstancesHandler)).Methods("GET", "OPTIONS")
|
||||
apiRouter.Handle("/scalesets/{scalesetID}/instances", http.HandlerFunc(han.ListScaleSetInstancesHandler)).Methods("GET", "OPTIONS")
|
||||
|
||||
/////////////
|
||||
// Runners //
|
||||
/////////////
|
||||
|
|
@ -246,6 +265,14 @@ func NewAPIRouter(han *controllers.APIController, authMiddleware, initMiddleware
|
|||
apiRouter.Handle("/repositories/{repoID}/pools/", http.HandlerFunc(han.CreateRepoPoolHandler)).Methods("POST", "OPTIONS")
|
||||
apiRouter.Handle("/repositories/{repoID}/pools", http.HandlerFunc(han.CreateRepoPoolHandler)).Methods("POST", "OPTIONS")
|
||||
|
||||
// Create scale set
|
||||
apiRouter.Handle("/repositories/{repoID}/scalesets/", http.HandlerFunc(han.CreateRepoScaleSetHandler)).Methods("POST", "OPTIONS")
|
||||
apiRouter.Handle("/repositories/{repoID}/scalesets", http.HandlerFunc(han.CreateRepoScaleSetHandler)).Methods("POST", "OPTIONS")
|
||||
|
||||
// List scale sets
|
||||
apiRouter.Handle("/repositories/{repoID}/scalesets/", http.HandlerFunc(han.ListRepoScaleSetsHandler)).Methods("GET", "OPTIONS")
|
||||
apiRouter.Handle("/repositories/{repoID}/scalesets", http.HandlerFunc(han.ListRepoScaleSetsHandler)).Methods("GET", "OPTIONS")
|
||||
|
||||
// Repo instances list
|
||||
apiRouter.Handle("/repositories/{repoID}/instances/", http.HandlerFunc(han.ListRepoInstancesHandler)).Methods("GET", "OPTIONS")
|
||||
apiRouter.Handle("/repositories/{repoID}/instances", http.HandlerFunc(han.ListRepoInstancesHandler)).Methods("GET", "OPTIONS")
|
||||
|
|
@ -296,6 +323,14 @@ func NewAPIRouter(han *controllers.APIController, authMiddleware, initMiddleware
|
|||
apiRouter.Handle("/organizations/{orgID}/pools/", http.HandlerFunc(han.CreateOrgPoolHandler)).Methods("POST", "OPTIONS")
|
||||
apiRouter.Handle("/organizations/{orgID}/pools", http.HandlerFunc(han.CreateOrgPoolHandler)).Methods("POST", "OPTIONS")
|
||||
|
||||
// Create org scale set
|
||||
apiRouter.Handle("/organizations/{orgID}/scalesets/", http.HandlerFunc(han.CreateOrgScaleSetHandler)).Methods("POST", "OPTIONS")
|
||||
apiRouter.Handle("/organizations/{orgID}/scalesets", http.HandlerFunc(han.CreateOrgScaleSetHandler)).Methods("POST", "OPTIONS")
|
||||
|
||||
// List org scale sets
|
||||
apiRouter.Handle("/organizations/{orgID}/scalesets/", http.HandlerFunc(han.ListOrgScaleSetsHandler)).Methods("GET", "OPTIONS")
|
||||
apiRouter.Handle("/organizations/{orgID}/scalesets", http.HandlerFunc(han.ListOrgScaleSetsHandler)).Methods("GET", "OPTIONS")
|
||||
|
||||
// Org instances list
|
||||
apiRouter.Handle("/organizations/{orgID}/instances/", http.HandlerFunc(han.ListOrgInstancesHandler)).Methods("GET", "OPTIONS")
|
||||
apiRouter.Handle("/organizations/{orgID}/instances", http.HandlerFunc(han.ListOrgInstancesHandler)).Methods("GET", "OPTIONS")
|
||||
|
|
@ -346,6 +381,14 @@ func NewAPIRouter(han *controllers.APIController, authMiddleware, initMiddleware
|
|||
apiRouter.Handle("/enterprises/{enterpriseID}/pools/", http.HandlerFunc(han.CreateEnterprisePoolHandler)).Methods("POST", "OPTIONS")
|
||||
apiRouter.Handle("/enterprises/{enterpriseID}/pools", http.HandlerFunc(han.CreateEnterprisePoolHandler)).Methods("POST", "OPTIONS")
|
||||
|
||||
// Create enterprise scale sets
|
||||
apiRouter.Handle("/enterprises/{enterpriseID}/scalesets/", http.HandlerFunc(han.CreateEnterpriseScaleSetHandler)).Methods("POST", "OPTIONS")
|
||||
apiRouter.Handle("/enterprises/{enterpriseID}/scalesets", http.HandlerFunc(han.CreateEnterpriseScaleSetHandler)).Methods("POST", "OPTIONS")
|
||||
|
||||
// List enterprise scale sets
|
||||
apiRouter.Handle("/enterprises/{enterpriseID}/scalesets/", http.HandlerFunc(han.ListEnterpriseScaleSetsHandler)).Methods("GET", "OPTIONS")
|
||||
apiRouter.Handle("/enterprises/{enterpriseID}/scalesets", http.HandlerFunc(han.ListEnterpriseScaleSetsHandler)).Methods("GET", "OPTIONS")
|
||||
|
||||
// Enterprise instances list
|
||||
apiRouter.Handle("/enterprises/{enterpriseID}/instances/", http.HandlerFunc(han.ListEnterpriseInstancesHandler)).Methods("GET", "OPTIONS")
|
||||
apiRouter.Handle("/enterprises/{enterpriseID}/instances", http.HandlerFunc(han.ListEnterpriseInstancesHandler)).Methods("GET", "OPTIONS")
|
||||
|
|
|
|||
|
|
@ -130,6 +130,22 @@ definitions:
|
|||
import:
|
||||
package: github.com/cloudbase/garm/params
|
||||
alias: garm_params
|
||||
ScaleSets:
|
||||
type: array
|
||||
x-go-type:
|
||||
type: ScaleSets
|
||||
import:
|
||||
package: github.com/cloudbase/garm/params
|
||||
alias: garm_params
|
||||
items:
|
||||
$ref: '#/definitions/ScaleSet'
|
||||
ScaleSet:
|
||||
type: object
|
||||
x-go-type:
|
||||
type: ScaleSet
|
||||
import:
|
||||
package: github.com/cloudbase/garm/params
|
||||
alias: garm_params
|
||||
Repositories:
|
||||
type: array
|
||||
x-go-type:
|
||||
|
|
@ -213,6 +229,13 @@ definitions:
|
|||
import:
|
||||
package: github.com/cloudbase/garm/params
|
||||
alias: garm_params
|
||||
CreateScaleSetParams:
|
||||
type: object
|
||||
x-go-type:
|
||||
type: CreateScaleSetParams
|
||||
import:
|
||||
package: github.com/cloudbase/garm/params
|
||||
alias: garm_params
|
||||
UpdatePoolParams:
|
||||
type: object
|
||||
x-go-type:
|
||||
|
|
@ -220,6 +243,13 @@ definitions:
|
|||
import:
|
||||
package: github.com/cloudbase/garm/params
|
||||
alias: garm_params
|
||||
UpdateScaleSetParams:
|
||||
type: object
|
||||
x-go-type:
|
||||
type: UpdateScaleSetParams
|
||||
import:
|
||||
package: github.com/cloudbase/garm/params
|
||||
alias: garm_params
|
||||
APIErrorResponse:
|
||||
type: object
|
||||
x-go-type:
|
||||
|
|
|
|||
|
|
@ -65,6 +65,13 @@ definitions:
|
|||
alias: garm_params
|
||||
package: github.com/cloudbase/garm/params
|
||||
type: CreateRepoParams
|
||||
CreateScaleSetParams:
|
||||
type: object
|
||||
x-go-type:
|
||||
import:
|
||||
alias: garm_params
|
||||
package: github.com/cloudbase/garm/params
|
||||
type: CreateScaleSetParams
|
||||
Credentials:
|
||||
items:
|
||||
$ref: '#/definitions/GithubCredentials'
|
||||
|
|
@ -244,6 +251,22 @@ definitions:
|
|||
alias: garm_params
|
||||
package: github.com/cloudbase/garm/params
|
||||
type: Repository
|
||||
ScaleSet:
|
||||
type: object
|
||||
x-go-type:
|
||||
import:
|
||||
alias: garm_params
|
||||
package: github.com/cloudbase/garm/params
|
||||
type: ScaleSet
|
||||
ScaleSets:
|
||||
items:
|
||||
$ref: '#/definitions/ScaleSet'
|
||||
type: array
|
||||
x-go-type:
|
||||
import:
|
||||
alias: garm_params
|
||||
package: github.com/cloudbase/garm/params
|
||||
type: ScaleSets
|
||||
UpdateControllerParams:
|
||||
type: object
|
||||
x-go-type:
|
||||
|
|
@ -279,6 +302,13 @@ definitions:
|
|||
alias: garm_params
|
||||
package: github.com/cloudbase/garm/params
|
||||
type: UpdatePoolParams
|
||||
UpdateScaleSetParams:
|
||||
type: object
|
||||
x-go-type:
|
||||
import:
|
||||
alias: garm_params
|
||||
package: github.com/cloudbase/garm/params
|
||||
type: UpdateScaleSetParams
|
||||
User:
|
||||
type: object
|
||||
x-go-type:
|
||||
|
|
@ -616,6 +646,57 @@ paths:
|
|||
tags:
|
||||
- enterprises
|
||||
- pools
|
||||
/enterprises/{enterpriseID}/scalesets:
|
||||
get:
|
||||
operationId: ListEnterpriseScaleSets
|
||||
parameters:
|
||||
- description: Enterprise ID.
|
||||
in: path
|
||||
name: enterpriseID
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: ScaleSets
|
||||
schema:
|
||||
$ref: '#/definitions/ScaleSets'
|
||||
default:
|
||||
description: APIErrorResponse
|
||||
schema:
|
||||
$ref: '#/definitions/APIErrorResponse'
|
||||
summary: List enterprise scale sets.
|
||||
tags:
|
||||
- enterprises
|
||||
- scalesets
|
||||
post:
|
||||
operationId: CreateEnterpriseScaleSet
|
||||
parameters:
|
||||
- description: Enterprise ID.
|
||||
in: path
|
||||
name: enterpriseID
|
||||
required: true
|
||||
type: string
|
||||
- description: Parameters used when creating the enterprise scale set.
|
||||
in: body
|
||||
name: Body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/CreateScaleSetParams'
|
||||
description: Parameters used when creating the enterprise scale set.
|
||||
type: object
|
||||
responses:
|
||||
"200":
|
||||
description: ScaleSet
|
||||
schema:
|
||||
$ref: '#/definitions/ScaleSet'
|
||||
default:
|
||||
description: APIErrorResponse
|
||||
schema:
|
||||
$ref: '#/definitions/APIErrorResponse'
|
||||
summary: Create enterprise pool with the parameters given.
|
||||
tags:
|
||||
- enterprises
|
||||
- scalesets
|
||||
/first-run:
|
||||
post:
|
||||
operationId: FirstRun
|
||||
|
|
@ -1199,6 +1280,57 @@ paths:
|
|||
tags:
|
||||
- organizations
|
||||
- pools
|
||||
/organizations/{orgID}/scalesets:
|
||||
get:
|
||||
operationId: ListOrgScaleSets
|
||||
parameters:
|
||||
- description: Organization ID.
|
||||
in: path
|
||||
name: orgID
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: ScaleSets
|
||||
schema:
|
||||
$ref: '#/definitions/ScaleSets'
|
||||
default:
|
||||
description: APIErrorResponse
|
||||
schema:
|
||||
$ref: '#/definitions/APIErrorResponse'
|
||||
summary: List organization scale sets.
|
||||
tags:
|
||||
- organizations
|
||||
- scalesets
|
||||
post:
|
||||
operationId: CreateOrgScaleSet
|
||||
parameters:
|
||||
- description: Organization ID.
|
||||
in: path
|
||||
name: orgID
|
||||
required: true
|
||||
type: string
|
||||
- description: Parameters used when creating the organization scale set.
|
||||
in: body
|
||||
name: Body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/CreateScaleSetParams'
|
||||
description: Parameters used when creating the organization scale set.
|
||||
type: object
|
||||
responses:
|
||||
"200":
|
||||
description: ScaleSet
|
||||
schema:
|
||||
$ref: '#/definitions/ScaleSet'
|
||||
default:
|
||||
description: APIErrorResponse
|
||||
schema:
|
||||
$ref: '#/definitions/APIErrorResponse'
|
||||
summary: Create organization scale set with the parameters given.
|
||||
tags:
|
||||
- organizations
|
||||
- scalesets
|
||||
/organizations/{orgID}/webhook:
|
||||
delete:
|
||||
operationId: UninstallOrgWebhook
|
||||
|
|
@ -1648,6 +1780,57 @@ paths:
|
|||
tags:
|
||||
- repositories
|
||||
- pools
|
||||
/repositories/{repoID}/scalesets:
|
||||
get:
|
||||
operationId: ListRepoScaleSets
|
||||
parameters:
|
||||
- description: Repository ID.
|
||||
in: path
|
||||
name: repoID
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: ScaleSets
|
||||
schema:
|
||||
$ref: '#/definitions/ScaleSets'
|
||||
default:
|
||||
description: APIErrorResponse
|
||||
schema:
|
||||
$ref: '#/definitions/APIErrorResponse'
|
||||
summary: List repository scale sets.
|
||||
tags:
|
||||
- repositories
|
||||
- scalesets
|
||||
post:
|
||||
operationId: CreateRepoScaleSet
|
||||
parameters:
|
||||
- description: Repository ID.
|
||||
in: path
|
||||
name: repoID
|
||||
required: true
|
||||
type: string
|
||||
- description: Parameters used when creating the repository scale set.
|
||||
in: body
|
||||
name: Body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/CreateScaleSetParams'
|
||||
description: Parameters used when creating the repository scale set.
|
||||
type: object
|
||||
responses:
|
||||
"200":
|
||||
description: ScaleSet
|
||||
schema:
|
||||
$ref: '#/definitions/ScaleSet'
|
||||
default:
|
||||
description: APIErrorResponse
|
||||
schema:
|
||||
$ref: '#/definitions/APIErrorResponse'
|
||||
summary: Create repository scale set with the parameters given.
|
||||
tags:
|
||||
- repositories
|
||||
- scalesets
|
||||
/repositories/{repoID}/webhook:
|
||||
delete:
|
||||
operationId: UninstallRepoWebhook
|
||||
|
|
@ -1718,6 +1901,107 @@ paths:
|
|||
tags:
|
||||
- repositories
|
||||
- hooks
|
||||
/scalesets:
|
||||
get:
|
||||
operationId: ListScalesets
|
||||
responses:
|
||||
"200":
|
||||
description: ScaleSets
|
||||
schema:
|
||||
$ref: '#/definitions/ScaleSets'
|
||||
default:
|
||||
description: APIErrorResponse
|
||||
schema:
|
||||
$ref: '#/definitions/APIErrorResponse'
|
||||
summary: List all scalesets.
|
||||
tags:
|
||||
- scalesets
|
||||
/scalesets/{scalesetID}:
|
||||
delete:
|
||||
operationId: DeleteScaleSet
|
||||
parameters:
|
||||
- description: ID of the scale set to delete.
|
||||
in: path
|
||||
name: scalesetID
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
default:
|
||||
description: APIErrorResponse
|
||||
schema:
|
||||
$ref: '#/definitions/APIErrorResponse'
|
||||
summary: Delete scale set by ID.
|
||||
tags:
|
||||
- scalesets
|
||||
get:
|
||||
operationId: GetScaleSet
|
||||
parameters:
|
||||
- description: ID of the scale set to fetch.
|
||||
in: path
|
||||
name: scalesetID
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: ScaleSet
|
||||
schema:
|
||||
$ref: '#/definitions/ScaleSet'
|
||||
default:
|
||||
description: APIErrorResponse
|
||||
schema:
|
||||
$ref: '#/definitions/APIErrorResponse'
|
||||
summary: Get scale set by ID.
|
||||
tags:
|
||||
- scalesets
|
||||
put:
|
||||
operationId: UpdateScaleSet
|
||||
parameters:
|
||||
- description: ID of the scale set to update.
|
||||
in: path
|
||||
name: scalesetID
|
||||
required: true
|
||||
type: string
|
||||
- description: Parameters to update the scale set with.
|
||||
in: body
|
||||
name: Body
|
||||
required: true
|
||||
schema:
|
||||
$ref: '#/definitions/UpdateScaleSetParams'
|
||||
description: Parameters to update the scale set with.
|
||||
type: object
|
||||
responses:
|
||||
"200":
|
||||
description: ScaleSet
|
||||
schema:
|
||||
$ref: '#/definitions/ScaleSet'
|
||||
default:
|
||||
description: APIErrorResponse
|
||||
schema:
|
||||
$ref: '#/definitions/APIErrorResponse'
|
||||
summary: Update scale set by ID.
|
||||
tags:
|
||||
- scalesets
|
||||
/scalesets/{scalesetID}/instances:
|
||||
get:
|
||||
operationId: ListScaleSetInstances
|
||||
parameters:
|
||||
- description: Runner scale set ID.
|
||||
in: path
|
||||
name: scalesetID
|
||||
required: true
|
||||
type: string
|
||||
responses:
|
||||
"200":
|
||||
description: Instances
|
||||
schema:
|
||||
$ref: '#/definitions/Instances'
|
||||
default:
|
||||
description: APIErrorResponse
|
||||
schema:
|
||||
$ref: '#/definitions/APIErrorResponse'
|
||||
summary: List runner instances in a scale set.
|
||||
tags:
|
||||
- instances
|
||||
produces:
|
||||
- application/json
|
||||
security:
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import (
|
|||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"math"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
|
@ -59,11 +60,17 @@ type instanceToken struct {
|
|||
jwtSecret string
|
||||
}
|
||||
|
||||
func (i *instanceToken) NewInstanceJWTToken(instance params.Instance, entity string, poolType params.GithubEntityType, ttlMinutes uint) (string, error) {
|
||||
func (i *instanceToken) NewInstanceJWTToken(instance params.Instance, entity string, entityType params.GithubEntityType, ttlMinutes uint) (string, error) {
|
||||
// Token expiration is equal to the bootstrap timeout set on the pool plus the polling
|
||||
// interval garm uses to check for timed out runners. Runners that have not sent their info
|
||||
// by the end of this interval are most likely failed and will be reaped by garm anyway.
|
||||
expireToken := time.Now().Add(time.Duration(ttlMinutes)*time.Minute + common.PoolReapTimeoutInterval)
|
||||
var ttl int
|
||||
if ttlMinutes > math.MaxInt {
|
||||
ttl = math.MaxInt
|
||||
} else {
|
||||
ttl = int(ttlMinutes)
|
||||
}
|
||||
expireToken := time.Now().Add(time.Duration(ttl)*time.Minute + common.PoolReapTimeoutInterval)
|
||||
expires := &jwt.NumericDate{
|
||||
Time: expireToken,
|
||||
}
|
||||
|
|
@ -75,7 +82,7 @@ func (i *instanceToken) NewInstanceJWTToken(instance params.Instance, entity str
|
|||
ID: instance.ID,
|
||||
Name: instance.Name,
|
||||
PoolID: instance.PoolID,
|
||||
Scope: poolType,
|
||||
Scope: entityType,
|
||||
Entity: entity,
|
||||
CreateAttempt: instance.CreateAttempt,
|
||||
}
|
||||
|
|
|
|||
619
cache/cache_test.go
vendored
Normal file
619
cache/cache_test.go
vendored
Normal file
|
|
@ -0,0 +1,619 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
commonParams "github.com/cloudbase/garm-provider-common/params"
|
||||
garmTesting "github.com/cloudbase/garm/internal/testing"
|
||||
"github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
type CacheTestSuite struct {
|
||||
suite.Suite
|
||||
entity params.GithubEntity
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) SetupTest() {
|
||||
c.entity = params.GithubEntity{
|
||||
ID: "1234",
|
||||
EntityType: params.GithubEntityTypeOrganization,
|
||||
Name: "test",
|
||||
Owner: "test",
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TearDownTest() {
|
||||
// Clean up the cache after each test
|
||||
githubToolsCache.mux.Lock()
|
||||
defer githubToolsCache.mux.Unlock()
|
||||
githubToolsCache.entities = make(map[string]GithubEntityTools)
|
||||
credentialsCache.cache = make(map[uint]params.GithubCredentials)
|
||||
instanceCache.cache = make(map[string]params.Instance)
|
||||
entityCache = &EntityCache{
|
||||
entities: make(map[string]EntityItem),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestCacheIsInitialized() {
|
||||
c.Require().NotNil(githubToolsCache)
|
||||
c.Require().NotNil(credentialsCache)
|
||||
c.Require().NotNil(instanceCache)
|
||||
c.Require().NotNil(entityCache)
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestSetCacheWorks() {
|
||||
tools := []commonParams.RunnerApplicationDownload{
|
||||
{
|
||||
DownloadURL: garmTesting.Ptr("https://example.com"),
|
||||
},
|
||||
}
|
||||
|
||||
c.Require().NotNil(githubToolsCache)
|
||||
c.Require().Len(githubToolsCache.entities, 0)
|
||||
SetGithubToolsCache(c.entity, tools)
|
||||
c.Require().Len(githubToolsCache.entities, 1)
|
||||
cachedTools, ok := GetGithubToolsCache(c.entity)
|
||||
c.Require().True(ok)
|
||||
c.Require().Len(cachedTools, 1)
|
||||
c.Require().Equal(tools[0].GetDownloadURL(), cachedTools[0].GetDownloadURL())
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestTimedOutToolsCache() {
|
||||
tools := []commonParams.RunnerApplicationDownload{
|
||||
{
|
||||
DownloadURL: garmTesting.Ptr("https://example.com"),
|
||||
},
|
||||
}
|
||||
|
||||
c.Require().NotNil(githubToolsCache)
|
||||
c.Require().Len(githubToolsCache.entities, 0)
|
||||
SetGithubToolsCache(c.entity, tools)
|
||||
c.Require().Len(githubToolsCache.entities, 1)
|
||||
entity := githubToolsCache.entities[c.entity.String()]
|
||||
entity.updatedAt = entity.updatedAt.Add(-2 * time.Hour)
|
||||
githubToolsCache.entities[c.entity.String()] = entity
|
||||
|
||||
cachedTools, ok := GetGithubToolsCache(c.entity)
|
||||
c.Require().False(ok)
|
||||
c.Require().Nil(cachedTools)
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestGetInexistentCache() {
|
||||
c.Require().NotNil(githubToolsCache)
|
||||
c.Require().Len(githubToolsCache.entities, 0)
|
||||
cachedTools, ok := GetGithubToolsCache(c.entity)
|
||||
c.Require().False(ok)
|
||||
c.Require().Nil(cachedTools)
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestSetGithubCredentials() {
|
||||
credentials := params.GithubCredentials{
|
||||
ID: 1,
|
||||
}
|
||||
SetGithubCredentials(credentials)
|
||||
cachedCreds, ok := GetGithubCredentials(1)
|
||||
c.Require().True(ok)
|
||||
c.Require().Equal(credentials.ID, cachedCreds.ID)
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestGetGithubCredentials() {
|
||||
credentials := params.GithubCredentials{
|
||||
ID: 1,
|
||||
}
|
||||
SetGithubCredentials(credentials)
|
||||
cachedCreds, ok := GetGithubCredentials(1)
|
||||
c.Require().True(ok)
|
||||
c.Require().Equal(credentials.ID, cachedCreds.ID)
|
||||
|
||||
nonExisting, ok := GetGithubCredentials(2)
|
||||
c.Require().False(ok)
|
||||
c.Require().Equal(params.GithubCredentials{}, nonExisting)
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestDeleteGithubCredentials() {
|
||||
credentials := params.GithubCredentials{
|
||||
ID: 1,
|
||||
}
|
||||
SetGithubCredentials(credentials)
|
||||
cachedCreds, ok := GetGithubCredentials(1)
|
||||
c.Require().True(ok)
|
||||
c.Require().Equal(credentials.ID, cachedCreds.ID)
|
||||
|
||||
DeleteGithubCredentials(1)
|
||||
cachedCreds, ok = GetGithubCredentials(1)
|
||||
c.Require().False(ok)
|
||||
c.Require().Equal(params.GithubCredentials{}, cachedCreds)
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestGetAllGithubCredentials() {
|
||||
credentials1 := params.GithubCredentials{
|
||||
ID: 1,
|
||||
}
|
||||
credentials2 := params.GithubCredentials{
|
||||
ID: 2,
|
||||
}
|
||||
SetGithubCredentials(credentials1)
|
||||
SetGithubCredentials(credentials2)
|
||||
|
||||
cachedCreds := GetAllGithubCredentials()
|
||||
c.Require().Len(cachedCreds, 2)
|
||||
c.Require().Contains(cachedCreds, credentials1)
|
||||
c.Require().Contains(cachedCreds, credentials2)
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestSetInstanceCache() {
|
||||
instance := params.Instance{
|
||||
Name: "test-instance",
|
||||
}
|
||||
SetInstanceCache(instance)
|
||||
cachedInstance, ok := GetInstanceCache("test-instance")
|
||||
c.Require().True(ok)
|
||||
c.Require().Equal(instance.Name, cachedInstance.Name)
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestGetInstanceCache() {
|
||||
instance := params.Instance{
|
||||
Name: "test-instance",
|
||||
}
|
||||
SetInstanceCache(instance)
|
||||
cachedInstance, ok := GetInstanceCache("test-instance")
|
||||
c.Require().True(ok)
|
||||
c.Require().Equal(instance.Name, cachedInstance.Name)
|
||||
|
||||
nonExisting, ok := GetInstanceCache("non-existing")
|
||||
c.Require().False(ok)
|
||||
c.Require().Equal(params.Instance{}, nonExisting)
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestDeleteInstanceCache() {
|
||||
instance := params.Instance{
|
||||
Name: "test-instance",
|
||||
}
|
||||
SetInstanceCache(instance)
|
||||
cachedInstance, ok := GetInstanceCache("test-instance")
|
||||
c.Require().True(ok)
|
||||
c.Require().Equal(instance.Name, cachedInstance.Name)
|
||||
|
||||
DeleteInstanceCache("test-instance")
|
||||
cachedInstance, ok = GetInstanceCache("test-instance")
|
||||
c.Require().False(ok)
|
||||
c.Require().Equal(params.Instance{}, cachedInstance)
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestGetAllInstances() {
|
||||
instance1 := params.Instance{
|
||||
Name: "test-instance-1",
|
||||
}
|
||||
instance2 := params.Instance{
|
||||
Name: "test-instance-2",
|
||||
}
|
||||
SetInstanceCache(instance1)
|
||||
SetInstanceCache(instance2)
|
||||
|
||||
cachedInstances := GetAllInstancesCache()
|
||||
c.Require().Len(cachedInstances, 2)
|
||||
c.Require().Contains(cachedInstances, instance1)
|
||||
c.Require().Contains(cachedInstances, instance2)
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestGetInstancesForPool() {
|
||||
instance1 := params.Instance{
|
||||
Name: "test-instance-1",
|
||||
PoolID: "pool-1",
|
||||
}
|
||||
instance2 := params.Instance{
|
||||
Name: "test-instance-2",
|
||||
PoolID: "pool-1",
|
||||
}
|
||||
instance3 := params.Instance{
|
||||
Name: "test-instance-3",
|
||||
PoolID: "pool-2",
|
||||
}
|
||||
SetInstanceCache(instance1)
|
||||
SetInstanceCache(instance2)
|
||||
SetInstanceCache(instance3)
|
||||
|
||||
cachedInstances := GetInstancesForPool("pool-1")
|
||||
c.Require().Len(cachedInstances, 2)
|
||||
c.Require().Contains(cachedInstances, instance1)
|
||||
c.Require().Contains(cachedInstances, instance2)
|
||||
|
||||
cachedInstances = GetInstancesForPool("pool-2")
|
||||
c.Require().Len(cachedInstances, 1)
|
||||
c.Require().Contains(cachedInstances, instance3)
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestGetInstancesForScaleSet() {
|
||||
instance1 := params.Instance{
|
||||
Name: "test-instance-1",
|
||||
ScaleSetID: 1,
|
||||
}
|
||||
instance2 := params.Instance{
|
||||
Name: "test-instance-2",
|
||||
ScaleSetID: 1,
|
||||
}
|
||||
instance3 := params.Instance{
|
||||
Name: "test-instance-3",
|
||||
ScaleSetID: 2,
|
||||
}
|
||||
SetInstanceCache(instance1)
|
||||
SetInstanceCache(instance2)
|
||||
SetInstanceCache(instance3)
|
||||
|
||||
cachedInstances := GetInstancesForScaleSet(1)
|
||||
c.Require().Len(cachedInstances, 2)
|
||||
c.Require().Contains(cachedInstances, instance1)
|
||||
c.Require().Contains(cachedInstances, instance2)
|
||||
|
||||
cachedInstances = GetInstancesForScaleSet(2)
|
||||
c.Require().Len(cachedInstances, 1)
|
||||
c.Require().Contains(cachedInstances, instance3)
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestSetGetEntityCache() {
|
||||
entity := params.GithubEntity{
|
||||
ID: "test-entity",
|
||||
EntityType: params.GithubEntityTypeOrganization,
|
||||
Name: "test",
|
||||
Owner: "test",
|
||||
}
|
||||
SetEntity(entity)
|
||||
cachedEntity, ok := GetEntity("test-entity")
|
||||
c.Require().True(ok)
|
||||
c.Require().Equal(entity.ID, cachedEntity.ID)
|
||||
|
||||
entity.Credentials.Description = "test description"
|
||||
SetEntity(entity)
|
||||
cachedEntity, ok = GetEntity("test-entity")
|
||||
c.Require().True(ok)
|
||||
c.Require().Equal(entity.ID, cachedEntity.ID)
|
||||
c.Require().Equal(entity.Credentials.Description, cachedEntity.Credentials.Description)
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestReplaceEntityPools() {
|
||||
entity := params.GithubEntity{
|
||||
ID: "test-entity",
|
||||
EntityType: params.GithubEntityTypeOrganization,
|
||||
Name: "test",
|
||||
Owner: "test",
|
||||
Credentials: params.GithubCredentials{
|
||||
ID: 1,
|
||||
},
|
||||
}
|
||||
pool1 := params.Pool{
|
||||
ID: "pool-1",
|
||||
}
|
||||
pool2 := params.Pool{
|
||||
ID: "pool-2",
|
||||
}
|
||||
|
||||
credentials := params.GithubCredentials{
|
||||
ID: 1,
|
||||
Name: "test",
|
||||
}
|
||||
SetGithubCredentials(credentials)
|
||||
|
||||
SetEntity(entity)
|
||||
ReplaceEntityPools(entity.ID, []params.Pool{pool1, pool2})
|
||||
cachedEntity, ok := GetEntity(entity.ID)
|
||||
c.Require().True(ok)
|
||||
c.Require().Equal(entity.ID, cachedEntity.ID)
|
||||
c.Require().Equal("test", cachedEntity.Credentials.Name)
|
||||
|
||||
pools := GetEntityPools(entity.ID)
|
||||
c.Require().Len(pools, 2)
|
||||
c.Require().Contains(pools, pool1)
|
||||
c.Require().Contains(pools, pool2)
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestReplaceEntityScaleSets() {
|
||||
entity := params.GithubEntity{
|
||||
ID: "test-entity",
|
||||
EntityType: params.GithubEntityTypeOrganization,
|
||||
Name: "test",
|
||||
Owner: "test",
|
||||
}
|
||||
scaleSet1 := params.ScaleSet{
|
||||
ID: 1,
|
||||
}
|
||||
scaleSet2 := params.ScaleSet{
|
||||
ID: 2,
|
||||
}
|
||||
|
||||
SetEntity(entity)
|
||||
ReplaceEntityScaleSets(entity.ID, map[uint]params.ScaleSet{1: scaleSet1, 2: scaleSet2})
|
||||
cachedEntity, ok := GetEntity(entity.ID)
|
||||
c.Require().True(ok)
|
||||
c.Require().Equal(entity.ID, cachedEntity.ID)
|
||||
|
||||
scaleSets := GetEntityScaleSets(entity.ID)
|
||||
c.Require().Len(scaleSets, 2)
|
||||
c.Require().Contains(scaleSets, scaleSet1)
|
||||
c.Require().Contains(scaleSets, scaleSet2)
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestDeleteEntity() {
|
||||
entity := params.GithubEntity{
|
||||
ID: "test-entity",
|
||||
EntityType: params.GithubEntityTypeOrganization,
|
||||
Name: "test",
|
||||
Owner: "test",
|
||||
}
|
||||
SetEntity(entity)
|
||||
cachedEntity, ok := GetEntity(entity.ID)
|
||||
c.Require().True(ok)
|
||||
c.Require().Equal(entity.ID, cachedEntity.ID)
|
||||
|
||||
DeleteEntity(entity.ID)
|
||||
cachedEntity, ok = GetEntity(entity.ID)
|
||||
c.Require().False(ok)
|
||||
c.Require().Equal(params.GithubEntity{}, cachedEntity)
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestSetEntityPool() {
|
||||
entity := params.GithubEntity{
|
||||
ID: "test-entity",
|
||||
EntityType: params.GithubEntityTypeOrganization,
|
||||
Name: "test",
|
||||
Owner: "test",
|
||||
}
|
||||
pool := params.Pool{
|
||||
ID: "pool-1",
|
||||
}
|
||||
|
||||
SetEntity(entity)
|
||||
|
||||
SetEntityPool(entity.ID, pool)
|
||||
cachedEntity, ok := GetEntity(entity.ID)
|
||||
c.Require().True(ok)
|
||||
c.Require().Equal(entity.ID, cachedEntity.ID)
|
||||
pools := GetEntityPools(entity.ID)
|
||||
c.Require().Len(pools, 1)
|
||||
c.Require().Contains(pools, pool)
|
||||
c.Require().False(pools[0].Enabled)
|
||||
|
||||
pool.Enabled = true
|
||||
SetEntityPool(entity.ID, pool)
|
||||
cachedEntity, ok = GetEntity(entity.ID)
|
||||
c.Require().True(ok)
|
||||
c.Require().Equal(entity.ID, cachedEntity.ID)
|
||||
pools = GetEntityPools(entity.ID)
|
||||
c.Require().Len(pools, 1)
|
||||
c.Require().Contains(pools, pool)
|
||||
c.Require().True(pools[0].Enabled)
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestSetEntityScaleSet() {
|
||||
entity := params.GithubEntity{
|
||||
ID: "test-entity",
|
||||
EntityType: params.GithubEntityTypeOrganization,
|
||||
Name: "test",
|
||||
Owner: "test",
|
||||
}
|
||||
scaleSet := params.ScaleSet{
|
||||
ID: 1,
|
||||
}
|
||||
|
||||
SetEntity(entity)
|
||||
SetEntityScaleSet(entity.ID, scaleSet)
|
||||
|
||||
cachedEntity, ok := GetEntity(entity.ID)
|
||||
c.Require().True(ok)
|
||||
c.Require().Equal(entity.ID, cachedEntity.ID)
|
||||
scaleSets := GetEntityScaleSets(entity.ID)
|
||||
c.Require().Len(scaleSets, 1)
|
||||
c.Require().Contains(scaleSets, scaleSet)
|
||||
c.Require().False(scaleSets[0].Enabled)
|
||||
|
||||
scaleSet.Enabled = true
|
||||
SetEntityScaleSet(entity.ID, scaleSet)
|
||||
scaleSets = GetEntityScaleSets(entity.ID)
|
||||
c.Require().Len(scaleSets, 1)
|
||||
c.Require().Contains(scaleSets, scaleSet)
|
||||
c.Require().True(scaleSets[0].Enabled)
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestDeleteEntityPool() {
|
||||
entity := params.GithubEntity{
|
||||
ID: "test-entity",
|
||||
EntityType: params.GithubEntityTypeOrganization,
|
||||
Name: "test",
|
||||
Owner: "test",
|
||||
}
|
||||
pool := params.Pool{
|
||||
ID: "pool-1",
|
||||
}
|
||||
|
||||
SetEntity(entity)
|
||||
SetEntityPool(entity.ID, pool)
|
||||
cachedEntity, ok := GetEntity(entity.ID)
|
||||
c.Require().True(ok)
|
||||
c.Require().Equal(entity.ID, cachedEntity.ID)
|
||||
|
||||
DeleteEntityPool(entity.ID, pool.ID)
|
||||
pools := GetEntityPools(entity.ID)
|
||||
c.Require().Len(pools, 0)
|
||||
c.Require().NotContains(pools, pool)
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestDeleteEntityScaleSet() {
|
||||
entity := params.GithubEntity{
|
||||
ID: "test-entity",
|
||||
EntityType: params.GithubEntityTypeOrganization,
|
||||
Name: "test",
|
||||
Owner: "test",
|
||||
}
|
||||
scaleSet := params.ScaleSet{
|
||||
ID: 1,
|
||||
}
|
||||
|
||||
SetEntity(entity)
|
||||
SetEntityScaleSet(entity.ID, scaleSet)
|
||||
cachedEntity, ok := GetEntity(entity.ID)
|
||||
c.Require().True(ok)
|
||||
c.Require().Equal(entity.ID, cachedEntity.ID)
|
||||
|
||||
DeleteEntityScaleSet(entity.ID, scaleSet.ID)
|
||||
scaleSets := GetEntityScaleSets(entity.ID)
|
||||
c.Require().Len(scaleSets, 0)
|
||||
c.Require().NotContains(scaleSets, scaleSet)
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestFindPoolsMatchingAllTags() {
|
||||
entity := params.GithubEntity{
|
||||
ID: "test-entity",
|
||||
EntityType: params.GithubEntityTypeOrganization,
|
||||
Name: "test",
|
||||
Owner: "test",
|
||||
}
|
||||
pool1 := params.Pool{
|
||||
ID: "pool-1",
|
||||
Tags: []params.Tag{
|
||||
{
|
||||
Name: "tag1",
|
||||
},
|
||||
{
|
||||
Name: "tag2",
|
||||
},
|
||||
},
|
||||
}
|
||||
pool2 := params.Pool{
|
||||
ID: "pool-2",
|
||||
Tags: []params.Tag{
|
||||
{
|
||||
Name: "tag1",
|
||||
},
|
||||
},
|
||||
}
|
||||
pool3 := params.Pool{
|
||||
ID: "pool-3",
|
||||
Tags: []params.Tag{
|
||||
{
|
||||
Name: "tag3",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
SetEntity(entity)
|
||||
SetEntityPool(entity.ID, pool1)
|
||||
SetEntityPool(entity.ID, pool2)
|
||||
SetEntityPool(entity.ID, pool3)
|
||||
|
||||
cachedEntity, ok := GetEntity(entity.ID)
|
||||
c.Require().True(ok)
|
||||
c.Require().Equal(entity.ID, cachedEntity.ID)
|
||||
pools := FindPoolsMatchingAllTags(entity.ID, []string{"tag1", "tag2"})
|
||||
c.Require().Len(pools, 1)
|
||||
c.Require().Contains(pools, pool1)
|
||||
pools = FindPoolsMatchingAllTags(entity.ID, []string{"tag1"})
|
||||
c.Require().Len(pools, 2)
|
||||
c.Require().Contains(pools, pool1)
|
||||
c.Require().Contains(pools, pool2)
|
||||
pools = FindPoolsMatchingAllTags(entity.ID, []string{"tag3"})
|
||||
c.Require().Len(pools, 1)
|
||||
c.Require().Contains(pools, pool3)
|
||||
pools = FindPoolsMatchingAllTags(entity.ID, []string{"tag4"})
|
||||
c.Require().Len(pools, 0)
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestGetEntityPools() {
|
||||
entity := params.GithubEntity{
|
||||
ID: "test-entity",
|
||||
EntityType: params.GithubEntityTypeOrganization,
|
||||
Name: "test",
|
||||
Owner: "test",
|
||||
}
|
||||
pool1 := params.Pool{
|
||||
ID: "pool-1",
|
||||
Tags: []params.Tag{
|
||||
{
|
||||
Name: "tag1",
|
||||
},
|
||||
{
|
||||
Name: "tag2",
|
||||
},
|
||||
},
|
||||
}
|
||||
pool2 := params.Pool{
|
||||
ID: "pool-2",
|
||||
Tags: []params.Tag{
|
||||
{
|
||||
Name: "tag1",
|
||||
},
|
||||
{
|
||||
Name: "tag3",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
SetEntity(entity)
|
||||
SetEntityPool(entity.ID, pool1)
|
||||
SetEntityPool(entity.ID, pool2)
|
||||
cachedEntity, ok := GetEntity(entity.ID)
|
||||
c.Require().True(ok)
|
||||
c.Require().Equal(entity.ID, cachedEntity.ID)
|
||||
pools := GetEntityPools(entity.ID)
|
||||
c.Require().Len(pools, 2)
|
||||
c.Require().Contains(pools, pool1)
|
||||
c.Require().Contains(pools, pool2)
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestGetEntityScaleSet() {
|
||||
entity := params.GithubEntity{
|
||||
ID: "test-entity",
|
||||
EntityType: params.GithubEntityTypeOrganization,
|
||||
Name: "test",
|
||||
Owner: "test",
|
||||
}
|
||||
scaleSet := params.ScaleSet{
|
||||
ID: 1,
|
||||
}
|
||||
|
||||
SetEntity(entity)
|
||||
SetEntityScaleSet(entity.ID, scaleSet)
|
||||
|
||||
cachedEntity, ok := GetEntity(entity.ID)
|
||||
c.Require().True(ok)
|
||||
c.Require().Equal(entity.ID, cachedEntity.ID)
|
||||
scaleSets, ok := GetEntityScaleSet(entity.ID, scaleSet.ID)
|
||||
c.Require().True(ok)
|
||||
c.Require().Equal(scaleSet.ID, scaleSets.ID)
|
||||
}
|
||||
|
||||
func (c *CacheTestSuite) TestGetEntityPool() {
|
||||
entity := params.GithubEntity{
|
||||
ID: "test-entity",
|
||||
EntityType: params.GithubEntityTypeOrganization,
|
||||
Name: "test",
|
||||
Owner: "test",
|
||||
}
|
||||
|
||||
pool := params.Pool{
|
||||
ID: "pool-1",
|
||||
Tags: []params.Tag{
|
||||
{
|
||||
Name: "tag1",
|
||||
},
|
||||
{
|
||||
Name: "tag2",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
SetEntity(entity)
|
||||
SetEntityPool(entity.ID, pool)
|
||||
cachedEntity, ok := GetEntity(entity.ID)
|
||||
c.Require().True(ok)
|
||||
c.Require().Equal(entity.ID, cachedEntity.ID)
|
||||
poolFromCache, ok := GetEntityPool(entity.ID, pool.ID)
|
||||
c.Require().True(ok)
|
||||
c.Require().Equal(pool.ID, poolFromCache.ID)
|
||||
}
|
||||
|
||||
func TestCacheTestSuite(t *testing.T) {
|
||||
t.Parallel()
|
||||
suite.Run(t, new(CacheTestSuite))
|
||||
}
|
||||
73
cache/credentials_cache.go
vendored
Normal file
73
cache/credentials_cache.go
vendored
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
var credentialsCache *GithubCredentials
|
||||
|
||||
func init() {
|
||||
ghCredentialsCache := &GithubCredentials{
|
||||
cache: make(map[uint]params.GithubCredentials),
|
||||
}
|
||||
credentialsCache = ghCredentialsCache
|
||||
}
|
||||
|
||||
type GithubCredentials struct {
|
||||
mux sync.Mutex
|
||||
|
||||
cache map[uint]params.GithubCredentials
|
||||
}
|
||||
|
||||
func (g *GithubCredentials) SetCredentials(credentials params.GithubCredentials) {
|
||||
g.mux.Lock()
|
||||
defer g.mux.Unlock()
|
||||
|
||||
g.cache[credentials.ID] = credentials
|
||||
}
|
||||
|
||||
func (g *GithubCredentials) GetCredentials(id uint) (params.GithubCredentials, bool) {
|
||||
g.mux.Lock()
|
||||
defer g.mux.Unlock()
|
||||
|
||||
if creds, ok := g.cache[id]; ok {
|
||||
return creds, true
|
||||
}
|
||||
return params.GithubCredentials{}, false
|
||||
}
|
||||
|
||||
func (g *GithubCredentials) DeleteCredentials(id uint) {
|
||||
g.mux.Lock()
|
||||
defer g.mux.Unlock()
|
||||
|
||||
delete(g.cache, id)
|
||||
}
|
||||
|
||||
func (g *GithubCredentials) GetAllCredentials() []params.GithubCredentials {
|
||||
g.mux.Lock()
|
||||
defer g.mux.Unlock()
|
||||
|
||||
creds := make([]params.GithubCredentials, 0, len(g.cache))
|
||||
for _, cred := range g.cache {
|
||||
creds = append(creds, cred)
|
||||
}
|
||||
return creds
|
||||
}
|
||||
|
||||
func SetGithubCredentials(credentials params.GithubCredentials) {
|
||||
credentialsCache.SetCredentials(credentials)
|
||||
}
|
||||
|
||||
func GetGithubCredentials(id uint) (params.GithubCredentials, bool) {
|
||||
return credentialsCache.GetCredentials(id)
|
||||
}
|
||||
|
||||
func DeleteGithubCredentials(id uint) {
|
||||
credentialsCache.DeleteCredentials(id)
|
||||
}
|
||||
|
||||
func GetAllGithubCredentials() []params.GithubCredentials {
|
||||
return credentialsCache.GetAllCredentials()
|
||||
}
|
||||
264
cache/entity_cache.go
vendored
Normal file
264
cache/entity_cache.go
vendored
Normal file
|
|
@ -0,0 +1,264 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"sync"
|
||||
|
||||
"github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
var entityCache *EntityCache
|
||||
|
||||
func init() {
|
||||
ghEntityCache := &EntityCache{
|
||||
entities: make(map[string]EntityItem),
|
||||
}
|
||||
entityCache = ghEntityCache
|
||||
}
|
||||
|
||||
type EntityItem struct {
|
||||
Entity params.GithubEntity
|
||||
Pools map[string]params.Pool
|
||||
ScaleSets map[uint]params.ScaleSet
|
||||
}
|
||||
|
||||
type EntityCache struct {
|
||||
mux sync.Mutex
|
||||
// entity IDs are UUID4s. It is highly unlikely they will collide (🤞).
|
||||
entities map[string]EntityItem
|
||||
}
|
||||
|
||||
func (e *EntityCache) GetEntity(entityID string) (params.GithubEntity, bool) {
|
||||
e.mux.Lock()
|
||||
defer e.mux.Unlock()
|
||||
|
||||
if cache, ok := e.entities[entityID]; ok {
|
||||
// Updating specific credential details will not update entity cache which
|
||||
// uses those credentials.
|
||||
// Entity credentials in the cache are only updated if you swap the creds
|
||||
// on the entity. We get the updated credentials from the credentials cache.
|
||||
creds, ok := GetGithubCredentials(cache.Entity.Credentials.ID)
|
||||
if ok {
|
||||
cache.Entity.Credentials = creds
|
||||
}
|
||||
return cache.Entity, true
|
||||
}
|
||||
return params.GithubEntity{}, false
|
||||
}
|
||||
|
||||
func (e *EntityCache) SetEntity(entity params.GithubEntity) {
|
||||
e.mux.Lock()
|
||||
defer e.mux.Unlock()
|
||||
|
||||
_, ok := e.entities[entity.ID]
|
||||
if !ok {
|
||||
e.entities[entity.ID] = EntityItem{
|
||||
Entity: entity,
|
||||
Pools: make(map[string]params.Pool),
|
||||
ScaleSets: make(map[uint]params.ScaleSet),
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
e.entities[entity.ID] = EntityItem{
|
||||
Entity: entity,
|
||||
}
|
||||
}
|
||||
|
||||
func (e *EntityCache) ReplaceEntityPools(entityID string, pools []params.Pool) {
|
||||
e.mux.Lock()
|
||||
defer e.mux.Unlock()
|
||||
|
||||
cache, ok := e.entities[entityID]
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
|
||||
poolsByID := map[string]params.Pool{}
|
||||
for _, pool := range pools {
|
||||
poolsByID[pool.ID] = pool
|
||||
}
|
||||
cache.Pools = poolsByID
|
||||
e.entities[entityID] = cache
|
||||
}
|
||||
|
||||
func (e *EntityCache) ReplaceEntityScaleSets(entityID string, scaleSets map[uint]params.ScaleSet) {
|
||||
e.mux.Lock()
|
||||
defer e.mux.Unlock()
|
||||
|
||||
if cache, ok := e.entities[entityID]; ok {
|
||||
cache.ScaleSets = scaleSets
|
||||
e.entities[entityID] = cache
|
||||
}
|
||||
}
|
||||
|
||||
func (e *EntityCache) DeleteEntity(entityID string) {
|
||||
e.mux.Lock()
|
||||
defer e.mux.Unlock()
|
||||
delete(e.entities, entityID)
|
||||
}
|
||||
|
||||
func (e *EntityCache) SetEntityPool(entityID string, pool params.Pool) {
|
||||
e.mux.Lock()
|
||||
defer e.mux.Unlock()
|
||||
|
||||
if cache, ok := e.entities[entityID]; ok {
|
||||
cache.Pools[pool.ID] = pool
|
||||
e.entities[entityID] = cache
|
||||
}
|
||||
}
|
||||
|
||||
func (e *EntityCache) SetEntityScaleSet(entityID string, scaleSet params.ScaleSet) {
|
||||
e.mux.Lock()
|
||||
defer e.mux.Unlock()
|
||||
|
||||
if cache, ok := e.entities[entityID]; ok {
|
||||
cache.ScaleSets[scaleSet.ID] = scaleSet
|
||||
e.entities[entityID] = cache
|
||||
}
|
||||
}
|
||||
|
||||
func (e *EntityCache) DeleteEntityPool(entityID string, poolID string) {
|
||||
e.mux.Lock()
|
||||
defer e.mux.Unlock()
|
||||
|
||||
if cache, ok := e.entities[entityID]; ok {
|
||||
delete(cache.Pools, poolID)
|
||||
e.entities[entityID] = cache
|
||||
}
|
||||
}
|
||||
|
||||
func (e *EntityCache) DeleteEntityScaleSet(entityID string, scaleSetID uint) {
|
||||
e.mux.Lock()
|
||||
defer e.mux.Unlock()
|
||||
|
||||
if cache, ok := e.entities[entityID]; ok {
|
||||
delete(cache.ScaleSets, scaleSetID)
|
||||
e.entities[entityID] = cache
|
||||
}
|
||||
}
|
||||
|
||||
func (e *EntityCache) GetEntityPool(entityID string, poolID string) (params.Pool, bool) {
|
||||
e.mux.Lock()
|
||||
defer e.mux.Unlock()
|
||||
|
||||
if cache, ok := e.entities[entityID]; ok {
|
||||
if pool, ok := cache.Pools[poolID]; ok {
|
||||
return pool, true
|
||||
}
|
||||
}
|
||||
return params.Pool{}, false
|
||||
}
|
||||
|
||||
func (e *EntityCache) GetEntityScaleSet(entityID string, scaleSetID uint) (params.ScaleSet, bool) {
|
||||
e.mux.Lock()
|
||||
defer e.mux.Unlock()
|
||||
|
||||
if cache, ok := e.entities[entityID]; ok {
|
||||
if scaleSet, ok := cache.ScaleSets[scaleSetID]; ok {
|
||||
return scaleSet, true
|
||||
}
|
||||
}
|
||||
return params.ScaleSet{}, false
|
||||
}
|
||||
|
||||
func (e *EntityCache) FindPoolsMatchingAllTags(entityID string, tags []string) []params.Pool {
|
||||
e.mux.Lock()
|
||||
defer e.mux.Unlock()
|
||||
|
||||
if cache, ok := e.entities[entityID]; ok {
|
||||
var pools []params.Pool
|
||||
slog.Debug("Finding pools matching all tags", "entityID", entityID, "tags", tags, "pools", cache.Pools)
|
||||
for _, pool := range cache.Pools {
|
||||
if pool.HasRequiredLabels(tags) {
|
||||
pools = append(pools, pool)
|
||||
}
|
||||
}
|
||||
return pools
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *EntityCache) GetEntityPools(entityID string) []params.Pool {
|
||||
e.mux.Lock()
|
||||
defer e.mux.Unlock()
|
||||
|
||||
if cache, ok := e.entities[entityID]; ok {
|
||||
var pools []params.Pool
|
||||
for _, pool := range cache.Pools {
|
||||
pools = append(pools, pool)
|
||||
}
|
||||
return pools
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (e *EntityCache) GetEntityScaleSets(entityID string) []params.ScaleSet {
|
||||
e.mux.Lock()
|
||||
defer e.mux.Unlock()
|
||||
|
||||
if cache, ok := e.entities[entityID]; ok {
|
||||
var scaleSets []params.ScaleSet
|
||||
for _, scaleSet := range cache.ScaleSets {
|
||||
scaleSets = append(scaleSets, scaleSet)
|
||||
}
|
||||
return scaleSets
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func GetEntity(entityID string) (params.GithubEntity, bool) {
|
||||
return entityCache.GetEntity(entityID)
|
||||
}
|
||||
|
||||
func SetEntity(entity params.GithubEntity) {
|
||||
entityCache.SetEntity(entity)
|
||||
}
|
||||
|
||||
func ReplaceEntityPools(entityID string, pools []params.Pool) {
|
||||
entityCache.ReplaceEntityPools(entityID, pools)
|
||||
}
|
||||
|
||||
func ReplaceEntityScaleSets(entityID string, scaleSets map[uint]params.ScaleSet) {
|
||||
entityCache.ReplaceEntityScaleSets(entityID, scaleSets)
|
||||
}
|
||||
|
||||
func DeleteEntity(entityID string) {
|
||||
entityCache.DeleteEntity(entityID)
|
||||
}
|
||||
|
||||
func SetEntityPool(entityID string, pool params.Pool) {
|
||||
entityCache.SetEntityPool(entityID, pool)
|
||||
}
|
||||
|
||||
func SetEntityScaleSet(entityID string, scaleSet params.ScaleSet) {
|
||||
entityCache.SetEntityScaleSet(entityID, scaleSet)
|
||||
}
|
||||
|
||||
func DeleteEntityPool(entityID string, poolID string) {
|
||||
entityCache.DeleteEntityPool(entityID, poolID)
|
||||
}
|
||||
|
||||
func DeleteEntityScaleSet(entityID string, scaleSetID uint) {
|
||||
entityCache.DeleteEntityScaleSet(entityID, scaleSetID)
|
||||
}
|
||||
|
||||
func GetEntityPool(entityID string, poolID string) (params.Pool, bool) {
|
||||
return entityCache.GetEntityPool(entityID, poolID)
|
||||
}
|
||||
|
||||
func GetEntityScaleSet(entityID string, scaleSetID uint) (params.ScaleSet, bool) {
|
||||
return entityCache.GetEntityScaleSet(entityID, scaleSetID)
|
||||
}
|
||||
|
||||
func FindPoolsMatchingAllTags(entityID string, tags []string) []params.Pool {
|
||||
return entityCache.FindPoolsMatchingAllTags(entityID, tags)
|
||||
}
|
||||
|
||||
func GetEntityPools(entityID string) []params.Pool {
|
||||
return entityCache.GetEntityPools(entityID)
|
||||
}
|
||||
|
||||
func GetEntityScaleSets(entityID string) []params.ScaleSet {
|
||||
return entityCache.GetEntityScaleSets(entityID)
|
||||
}
|
||||
107
cache/instance_cache.go
vendored
Normal file
107
cache/instance_cache.go
vendored
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
var instanceCache *InstanceCache
|
||||
|
||||
func init() {
|
||||
cache := &InstanceCache{
|
||||
cache: make(map[string]params.Instance),
|
||||
}
|
||||
instanceCache = cache
|
||||
}
|
||||
|
||||
type InstanceCache struct {
|
||||
mux sync.Mutex
|
||||
|
||||
cache map[string]params.Instance
|
||||
}
|
||||
|
||||
func (i *InstanceCache) SetInstance(instance params.Instance) {
|
||||
i.mux.Lock()
|
||||
defer i.mux.Unlock()
|
||||
|
||||
i.cache[instance.Name] = instance
|
||||
}
|
||||
|
||||
func (i *InstanceCache) GetInstance(name string) (params.Instance, bool) {
|
||||
i.mux.Lock()
|
||||
defer i.mux.Unlock()
|
||||
|
||||
if instance, ok := i.cache[name]; ok {
|
||||
return instance, true
|
||||
}
|
||||
return params.Instance{}, false
|
||||
}
|
||||
|
||||
func (i *InstanceCache) DeleteInstance(name string) {
|
||||
i.mux.Lock()
|
||||
defer i.mux.Unlock()
|
||||
|
||||
delete(i.cache, name)
|
||||
}
|
||||
|
||||
func (i *InstanceCache) GetAllInstances() []params.Instance {
|
||||
i.mux.Lock()
|
||||
defer i.mux.Unlock()
|
||||
|
||||
instances := make([]params.Instance, 0, len(i.cache))
|
||||
for _, instance := range i.cache {
|
||||
instances = append(instances, instance)
|
||||
}
|
||||
return instances
|
||||
}
|
||||
|
||||
func (i *InstanceCache) GetInstancesForPool(poolID string) []params.Instance {
|
||||
i.mux.Lock()
|
||||
defer i.mux.Unlock()
|
||||
|
||||
var filteredInstances []params.Instance
|
||||
for _, instance := range i.cache {
|
||||
if instance.PoolID == poolID {
|
||||
filteredInstances = append(filteredInstances, instance)
|
||||
}
|
||||
}
|
||||
return filteredInstances
|
||||
}
|
||||
|
||||
func (i *InstanceCache) GetInstancesForScaleSet(scaleSetID uint) []params.Instance {
|
||||
i.mux.Lock()
|
||||
defer i.mux.Unlock()
|
||||
|
||||
var filteredInstances []params.Instance
|
||||
for _, instance := range i.cache {
|
||||
if instance.ScaleSetID == scaleSetID {
|
||||
filteredInstances = append(filteredInstances, instance)
|
||||
}
|
||||
}
|
||||
return filteredInstances
|
||||
}
|
||||
|
||||
func SetInstanceCache(instance params.Instance) {
|
||||
instanceCache.SetInstance(instance)
|
||||
}
|
||||
|
||||
func GetInstanceCache(name string) (params.Instance, bool) {
|
||||
return instanceCache.GetInstance(name)
|
||||
}
|
||||
|
||||
func DeleteInstanceCache(name string) {
|
||||
instanceCache.DeleteInstance(name)
|
||||
}
|
||||
|
||||
func GetAllInstancesCache() []params.Instance {
|
||||
return instanceCache.GetAllInstances()
|
||||
}
|
||||
|
||||
func GetInstancesForPool(poolID string) []params.Instance {
|
||||
return instanceCache.GetInstancesForPool(poolID)
|
||||
}
|
||||
|
||||
func GetInstancesForScaleSet(scaleSetID uint) []params.Instance {
|
||||
return instanceCache.GetInstancesForScaleSet(scaleSetID)
|
||||
}
|
||||
64
cache/tools_cache.go
vendored
Normal file
64
cache/tools_cache.go
vendored
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
package cache
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
commonParams "github.com/cloudbase/garm-provider-common/params"
|
||||
"github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
var githubToolsCache *GithubToolsCache
|
||||
|
||||
func init() {
|
||||
ghToolsCache := &GithubToolsCache{
|
||||
entities: make(map[string]GithubEntityTools),
|
||||
}
|
||||
githubToolsCache = ghToolsCache
|
||||
}
|
||||
|
||||
type GithubEntityTools struct {
|
||||
updatedAt time.Time
|
||||
entity params.GithubEntity
|
||||
tools []commonParams.RunnerApplicationDownload
|
||||
}
|
||||
|
||||
type GithubToolsCache struct {
|
||||
mux sync.Mutex
|
||||
// entity IDs are UUID4s. It is highly unlikely they will collide (🤞).
|
||||
entities map[string]GithubEntityTools
|
||||
}
|
||||
|
||||
func (g *GithubToolsCache) Get(entity params.GithubEntity) ([]commonParams.RunnerApplicationDownload, bool) {
|
||||
g.mux.Lock()
|
||||
defer g.mux.Unlock()
|
||||
|
||||
if cache, ok := g.entities[entity.String()]; ok {
|
||||
if time.Since(cache.updatedAt) > 1*time.Hour {
|
||||
// Stale cache, remove it.
|
||||
delete(g.entities, entity.String())
|
||||
return nil, false
|
||||
}
|
||||
return cache.tools, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (g *GithubToolsCache) Set(entity params.GithubEntity, tools []commonParams.RunnerApplicationDownload) {
|
||||
g.mux.Lock()
|
||||
defer g.mux.Unlock()
|
||||
|
||||
g.entities[entity.String()] = GithubEntityTools{
|
||||
updatedAt: time.Now(),
|
||||
entity: entity,
|
||||
tools: tools,
|
||||
}
|
||||
}
|
||||
|
||||
func SetGithubToolsCache(entity params.GithubEntity, tools []commonParams.RunnerApplicationDownload) {
|
||||
githubToolsCache.Set(entity, tools)
|
||||
}
|
||||
|
||||
func GetGithubToolsCache(entity params.GithubEntity) ([]commonParams.RunnerApplicationDownload, bool) {
|
||||
return githubToolsCache.Get(entity)
|
||||
}
|
||||
173
client/enterprises/create_enterprise_scale_set_parameters.go
Normal file
173
client/enterprises/create_enterprise_scale_set_parameters.go
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package enterprises
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
cr "github.com/go-openapi/runtime/client"
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
garm_params "github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
// NewCreateEnterpriseScaleSetParams creates a new CreateEnterpriseScaleSetParams object,
|
||||
// with the default timeout for this client.
|
||||
//
|
||||
// Default values are not hydrated, since defaults are normally applied by the API server side.
|
||||
//
|
||||
// To enforce default values in parameter, use SetDefaults or WithDefaults.
|
||||
func NewCreateEnterpriseScaleSetParams() *CreateEnterpriseScaleSetParams {
|
||||
return &CreateEnterpriseScaleSetParams{
|
||||
timeout: cr.DefaultTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
// NewCreateEnterpriseScaleSetParamsWithTimeout creates a new CreateEnterpriseScaleSetParams object
|
||||
// with the ability to set a timeout on a request.
|
||||
func NewCreateEnterpriseScaleSetParamsWithTimeout(timeout time.Duration) *CreateEnterpriseScaleSetParams {
|
||||
return &CreateEnterpriseScaleSetParams{
|
||||
timeout: timeout,
|
||||
}
|
||||
}
|
||||
|
||||
// NewCreateEnterpriseScaleSetParamsWithContext creates a new CreateEnterpriseScaleSetParams object
|
||||
// with the ability to set a context for a request.
|
||||
func NewCreateEnterpriseScaleSetParamsWithContext(ctx context.Context) *CreateEnterpriseScaleSetParams {
|
||||
return &CreateEnterpriseScaleSetParams{
|
||||
Context: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
// NewCreateEnterpriseScaleSetParamsWithHTTPClient creates a new CreateEnterpriseScaleSetParams object
|
||||
// with the ability to set a custom HTTPClient for a request.
|
||||
func NewCreateEnterpriseScaleSetParamsWithHTTPClient(client *http.Client) *CreateEnterpriseScaleSetParams {
|
||||
return &CreateEnterpriseScaleSetParams{
|
||||
HTTPClient: client,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
CreateEnterpriseScaleSetParams contains all the parameters to send to the API endpoint
|
||||
|
||||
for the create enterprise scale set operation.
|
||||
|
||||
Typically these are written to a http.Request.
|
||||
*/
|
||||
type CreateEnterpriseScaleSetParams struct {
|
||||
|
||||
/* Body.
|
||||
|
||||
Parameters used when creating the enterprise scale set.
|
||||
*/
|
||||
Body garm_params.CreateScaleSetParams
|
||||
|
||||
/* EnterpriseID.
|
||||
|
||||
Enterprise ID.
|
||||
*/
|
||||
EnterpriseID string
|
||||
|
||||
timeout time.Duration
|
||||
Context context.Context
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// WithDefaults hydrates default values in the create enterprise scale set params (not the query body).
|
||||
//
|
||||
// All values with no default are reset to their zero value.
|
||||
func (o *CreateEnterpriseScaleSetParams) WithDefaults() *CreateEnterpriseScaleSetParams {
|
||||
o.SetDefaults()
|
||||
return o
|
||||
}
|
||||
|
||||
// SetDefaults hydrates default values in the create enterprise scale set params (not the query body).
|
||||
//
|
||||
// All values with no default are reset to their zero value.
|
||||
func (o *CreateEnterpriseScaleSetParams) SetDefaults() {
|
||||
// no default values defined for this parameter
|
||||
}
|
||||
|
||||
// WithTimeout adds the timeout to the create enterprise scale set params
|
||||
func (o *CreateEnterpriseScaleSetParams) WithTimeout(timeout time.Duration) *CreateEnterpriseScaleSetParams {
|
||||
o.SetTimeout(timeout)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetTimeout adds the timeout to the create enterprise scale set params
|
||||
func (o *CreateEnterpriseScaleSetParams) SetTimeout(timeout time.Duration) {
|
||||
o.timeout = timeout
|
||||
}
|
||||
|
||||
// WithContext adds the context to the create enterprise scale set params
|
||||
func (o *CreateEnterpriseScaleSetParams) WithContext(ctx context.Context) *CreateEnterpriseScaleSetParams {
|
||||
o.SetContext(ctx)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetContext adds the context to the create enterprise scale set params
|
||||
func (o *CreateEnterpriseScaleSetParams) SetContext(ctx context.Context) {
|
||||
o.Context = ctx
|
||||
}
|
||||
|
||||
// WithHTTPClient adds the HTTPClient to the create enterprise scale set params
|
||||
func (o *CreateEnterpriseScaleSetParams) WithHTTPClient(client *http.Client) *CreateEnterpriseScaleSetParams {
|
||||
o.SetHTTPClient(client)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetHTTPClient adds the HTTPClient to the create enterprise scale set params
|
||||
func (o *CreateEnterpriseScaleSetParams) SetHTTPClient(client *http.Client) {
|
||||
o.HTTPClient = client
|
||||
}
|
||||
|
||||
// WithBody adds the body to the create enterprise scale set params
|
||||
func (o *CreateEnterpriseScaleSetParams) WithBody(body garm_params.CreateScaleSetParams) *CreateEnterpriseScaleSetParams {
|
||||
o.SetBody(body)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetBody adds the body to the create enterprise scale set params
|
||||
func (o *CreateEnterpriseScaleSetParams) SetBody(body garm_params.CreateScaleSetParams) {
|
||||
o.Body = body
|
||||
}
|
||||
|
||||
// WithEnterpriseID adds the enterpriseID to the create enterprise scale set params
|
||||
func (o *CreateEnterpriseScaleSetParams) WithEnterpriseID(enterpriseID string) *CreateEnterpriseScaleSetParams {
|
||||
o.SetEnterpriseID(enterpriseID)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetEnterpriseID adds the enterpriseId to the create enterprise scale set params
|
||||
func (o *CreateEnterpriseScaleSetParams) SetEnterpriseID(enterpriseID string) {
|
||||
o.EnterpriseID = enterpriseID
|
||||
}
|
||||
|
||||
// WriteToRequest writes these params to a swagger request
|
||||
func (o *CreateEnterpriseScaleSetParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
|
||||
|
||||
if err := r.SetTimeout(o.timeout); err != nil {
|
||||
return err
|
||||
}
|
||||
var res []error
|
||||
if err := r.SetBodyParam(o.Body); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// path param enterpriseID
|
||||
if err := r.SetPathParam("enterpriseID", o.EnterpriseID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
184
client/enterprises/create_enterprise_scale_set_responses.go
Normal file
184
client/enterprises/create_enterprise_scale_set_responses.go
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package enterprises
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
apiserver_params "github.com/cloudbase/garm/apiserver/params"
|
||||
garm_params "github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
// CreateEnterpriseScaleSetReader is a Reader for the CreateEnterpriseScaleSet structure.
|
||||
type CreateEnterpriseScaleSetReader struct {
|
||||
formats strfmt.Registry
|
||||
}
|
||||
|
||||
// ReadResponse reads a server response into the received o.
|
||||
func (o *CreateEnterpriseScaleSetReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
switch response.Code() {
|
||||
case 200:
|
||||
result := NewCreateEnterpriseScaleSetOK()
|
||||
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
default:
|
||||
result := NewCreateEnterpriseScaleSetDefault(response.Code())
|
||||
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if response.Code()/100 == 2 {
|
||||
return result, nil
|
||||
}
|
||||
return nil, result
|
||||
}
|
||||
}
|
||||
|
||||
// NewCreateEnterpriseScaleSetOK creates a CreateEnterpriseScaleSetOK with default headers values
|
||||
func NewCreateEnterpriseScaleSetOK() *CreateEnterpriseScaleSetOK {
|
||||
return &CreateEnterpriseScaleSetOK{}
|
||||
}
|
||||
|
||||
/*
|
||||
CreateEnterpriseScaleSetOK describes a response with status code 200, with default header values.
|
||||
|
||||
ScaleSet
|
||||
*/
|
||||
type CreateEnterpriseScaleSetOK struct {
|
||||
Payload garm_params.ScaleSet
|
||||
}
|
||||
|
||||
// IsSuccess returns true when this create enterprise scale set o k response has a 2xx status code
|
||||
func (o *CreateEnterpriseScaleSetOK) IsSuccess() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// IsRedirect returns true when this create enterprise scale set o k response has a 3xx status code
|
||||
func (o *CreateEnterpriseScaleSetOK) IsRedirect() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsClientError returns true when this create enterprise scale set o k response has a 4xx status code
|
||||
func (o *CreateEnterpriseScaleSetOK) IsClientError() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsServerError returns true when this create enterprise scale set o k response has a 5xx status code
|
||||
func (o *CreateEnterpriseScaleSetOK) IsServerError() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsCode returns true when this create enterprise scale set o k response a status code equal to that given
|
||||
func (o *CreateEnterpriseScaleSetOK) IsCode(code int) bool {
|
||||
return code == 200
|
||||
}
|
||||
|
||||
// Code gets the status code for the create enterprise scale set o k response
|
||||
func (o *CreateEnterpriseScaleSetOK) Code() int {
|
||||
return 200
|
||||
}
|
||||
|
||||
func (o *CreateEnterpriseScaleSetOK) Error() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[POST /enterprises/{enterpriseID}/scalesets][%d] createEnterpriseScaleSetOK %s", 200, payload)
|
||||
}
|
||||
|
||||
func (o *CreateEnterpriseScaleSetOK) String() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[POST /enterprises/{enterpriseID}/scalesets][%d] createEnterpriseScaleSetOK %s", 200, payload)
|
||||
}
|
||||
|
||||
func (o *CreateEnterpriseScaleSetOK) GetPayload() garm_params.ScaleSet {
|
||||
return o.Payload
|
||||
}
|
||||
|
||||
func (o *CreateEnterpriseScaleSetOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewCreateEnterpriseScaleSetDefault creates a CreateEnterpriseScaleSetDefault with default headers values
|
||||
func NewCreateEnterpriseScaleSetDefault(code int) *CreateEnterpriseScaleSetDefault {
|
||||
return &CreateEnterpriseScaleSetDefault{
|
||||
_statusCode: code,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
CreateEnterpriseScaleSetDefault describes a response with status code -1, with default header values.
|
||||
|
||||
APIErrorResponse
|
||||
*/
|
||||
type CreateEnterpriseScaleSetDefault struct {
|
||||
_statusCode int
|
||||
|
||||
Payload apiserver_params.APIErrorResponse
|
||||
}
|
||||
|
||||
// IsSuccess returns true when this create enterprise scale set default response has a 2xx status code
|
||||
func (o *CreateEnterpriseScaleSetDefault) IsSuccess() bool {
|
||||
return o._statusCode/100 == 2
|
||||
}
|
||||
|
||||
// IsRedirect returns true when this create enterprise scale set default response has a 3xx status code
|
||||
func (o *CreateEnterpriseScaleSetDefault) IsRedirect() bool {
|
||||
return o._statusCode/100 == 3
|
||||
}
|
||||
|
||||
// IsClientError returns true when this create enterprise scale set default response has a 4xx status code
|
||||
func (o *CreateEnterpriseScaleSetDefault) IsClientError() bool {
|
||||
return o._statusCode/100 == 4
|
||||
}
|
||||
|
||||
// IsServerError returns true when this create enterprise scale set default response has a 5xx status code
|
||||
func (o *CreateEnterpriseScaleSetDefault) IsServerError() bool {
|
||||
return o._statusCode/100 == 5
|
||||
}
|
||||
|
||||
// IsCode returns true when this create enterprise scale set default response a status code equal to that given
|
||||
func (o *CreateEnterpriseScaleSetDefault) IsCode(code int) bool {
|
||||
return o._statusCode == code
|
||||
}
|
||||
|
||||
// Code gets the status code for the create enterprise scale set default response
|
||||
func (o *CreateEnterpriseScaleSetDefault) Code() int {
|
||||
return o._statusCode
|
||||
}
|
||||
|
||||
func (o *CreateEnterpriseScaleSetDefault) Error() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[POST /enterprises/{enterpriseID}/scalesets][%d] CreateEnterpriseScaleSet default %s", o._statusCode, payload)
|
||||
}
|
||||
|
||||
func (o *CreateEnterpriseScaleSetDefault) String() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[POST /enterprises/{enterpriseID}/scalesets][%d] CreateEnterpriseScaleSet default %s", o._statusCode, payload)
|
||||
}
|
||||
|
||||
func (o *CreateEnterpriseScaleSetDefault) GetPayload() apiserver_params.APIErrorResponse {
|
||||
return o.Payload
|
||||
}
|
||||
|
||||
func (o *CreateEnterpriseScaleSetDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -58,6 +58,8 @@ type ClientService interface {
|
|||
|
||||
CreateEnterprisePool(params *CreateEnterprisePoolParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*CreateEnterprisePoolOK, error)
|
||||
|
||||
CreateEnterpriseScaleSet(params *CreateEnterpriseScaleSetParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*CreateEnterpriseScaleSetOK, error)
|
||||
|
||||
DeleteEnterprise(params *DeleteEnterpriseParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) error
|
||||
|
||||
DeleteEnterprisePool(params *DeleteEnterprisePoolParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) error
|
||||
|
|
@ -70,6 +72,8 @@ type ClientService interface {
|
|||
|
||||
ListEnterprisePools(params *ListEnterprisePoolsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ListEnterprisePoolsOK, error)
|
||||
|
||||
ListEnterpriseScaleSets(params *ListEnterpriseScaleSetsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ListEnterpriseScaleSetsOK, error)
|
||||
|
||||
ListEnterprises(params *ListEnterprisesParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ListEnterprisesOK, error)
|
||||
|
||||
UpdateEnterprise(params *UpdateEnterpriseParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*UpdateEnterpriseOK, error)
|
||||
|
|
@ -155,6 +159,44 @@ func (a *Client) CreateEnterprisePool(params *CreateEnterprisePoolParams, authIn
|
|||
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
|
||||
}
|
||||
|
||||
/*
|
||||
CreateEnterpriseScaleSet creates enterprise pool with the parameters given
|
||||
*/
|
||||
func (a *Client) CreateEnterpriseScaleSet(params *CreateEnterpriseScaleSetParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*CreateEnterpriseScaleSetOK, error) {
|
||||
// TODO: Validate the params before sending
|
||||
if params == nil {
|
||||
params = NewCreateEnterpriseScaleSetParams()
|
||||
}
|
||||
op := &runtime.ClientOperation{
|
||||
ID: "CreateEnterpriseScaleSet",
|
||||
Method: "POST",
|
||||
PathPattern: "/enterprises/{enterpriseID}/scalesets",
|
||||
ProducesMediaTypes: []string{"application/json"},
|
||||
ConsumesMediaTypes: []string{"application/json"},
|
||||
Schemes: []string{"http"},
|
||||
Params: params,
|
||||
Reader: &CreateEnterpriseScaleSetReader{formats: a.formats},
|
||||
AuthInfo: authInfo,
|
||||
Context: params.Context,
|
||||
Client: params.HTTPClient,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(op)
|
||||
}
|
||||
|
||||
result, err := a.transport.Submit(op)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
success, ok := result.(*CreateEnterpriseScaleSetOK)
|
||||
if ok {
|
||||
return success, nil
|
||||
}
|
||||
// unexpected success response
|
||||
unexpectedSuccess := result.(*CreateEnterpriseScaleSetDefault)
|
||||
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
|
||||
}
|
||||
|
||||
/*
|
||||
DeleteEnterprise deletes enterprise by ID
|
||||
*/
|
||||
|
|
@ -371,6 +413,44 @@ func (a *Client) ListEnterprisePools(params *ListEnterprisePoolsParams, authInfo
|
|||
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
|
||||
}
|
||||
|
||||
/*
|
||||
ListEnterpriseScaleSets lists enterprise scale sets
|
||||
*/
|
||||
func (a *Client) ListEnterpriseScaleSets(params *ListEnterpriseScaleSetsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ListEnterpriseScaleSetsOK, error) {
|
||||
// TODO: Validate the params before sending
|
||||
if params == nil {
|
||||
params = NewListEnterpriseScaleSetsParams()
|
||||
}
|
||||
op := &runtime.ClientOperation{
|
||||
ID: "ListEnterpriseScaleSets",
|
||||
Method: "GET",
|
||||
PathPattern: "/enterprises/{enterpriseID}/scalesets",
|
||||
ProducesMediaTypes: []string{"application/json"},
|
||||
ConsumesMediaTypes: []string{"application/json"},
|
||||
Schemes: []string{"http"},
|
||||
Params: params,
|
||||
Reader: &ListEnterpriseScaleSetsReader{formats: a.formats},
|
||||
AuthInfo: authInfo,
|
||||
Context: params.Context,
|
||||
Client: params.HTTPClient,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(op)
|
||||
}
|
||||
|
||||
result, err := a.transport.Submit(op)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
success, ok := result.(*ListEnterpriseScaleSetsOK)
|
||||
if ok {
|
||||
return success, nil
|
||||
}
|
||||
// unexpected success response
|
||||
unexpectedSuccess := result.(*ListEnterpriseScaleSetsDefault)
|
||||
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
|
||||
}
|
||||
|
||||
/*
|
||||
ListEnterprises lists all enterprises
|
||||
*/
|
||||
|
|
|
|||
151
client/enterprises/list_enterprise_scale_sets_parameters.go
Normal file
151
client/enterprises/list_enterprise_scale_sets_parameters.go
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package enterprises
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
cr "github.com/go-openapi/runtime/client"
|
||||
"github.com/go-openapi/strfmt"
|
||||
)
|
||||
|
||||
// NewListEnterpriseScaleSetsParams creates a new ListEnterpriseScaleSetsParams object,
|
||||
// with the default timeout for this client.
|
||||
//
|
||||
// Default values are not hydrated, since defaults are normally applied by the API server side.
|
||||
//
|
||||
// To enforce default values in parameter, use SetDefaults or WithDefaults.
|
||||
func NewListEnterpriseScaleSetsParams() *ListEnterpriseScaleSetsParams {
|
||||
return &ListEnterpriseScaleSetsParams{
|
||||
timeout: cr.DefaultTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
// NewListEnterpriseScaleSetsParamsWithTimeout creates a new ListEnterpriseScaleSetsParams object
|
||||
// with the ability to set a timeout on a request.
|
||||
func NewListEnterpriseScaleSetsParamsWithTimeout(timeout time.Duration) *ListEnterpriseScaleSetsParams {
|
||||
return &ListEnterpriseScaleSetsParams{
|
||||
timeout: timeout,
|
||||
}
|
||||
}
|
||||
|
||||
// NewListEnterpriseScaleSetsParamsWithContext creates a new ListEnterpriseScaleSetsParams object
|
||||
// with the ability to set a context for a request.
|
||||
func NewListEnterpriseScaleSetsParamsWithContext(ctx context.Context) *ListEnterpriseScaleSetsParams {
|
||||
return &ListEnterpriseScaleSetsParams{
|
||||
Context: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
// NewListEnterpriseScaleSetsParamsWithHTTPClient creates a new ListEnterpriseScaleSetsParams object
|
||||
// with the ability to set a custom HTTPClient for a request.
|
||||
func NewListEnterpriseScaleSetsParamsWithHTTPClient(client *http.Client) *ListEnterpriseScaleSetsParams {
|
||||
return &ListEnterpriseScaleSetsParams{
|
||||
HTTPClient: client,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
ListEnterpriseScaleSetsParams contains all the parameters to send to the API endpoint
|
||||
|
||||
for the list enterprise scale sets operation.
|
||||
|
||||
Typically these are written to a http.Request.
|
||||
*/
|
||||
type ListEnterpriseScaleSetsParams struct {
|
||||
|
||||
/* EnterpriseID.
|
||||
|
||||
Enterprise ID.
|
||||
*/
|
||||
EnterpriseID string
|
||||
|
||||
timeout time.Duration
|
||||
Context context.Context
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// WithDefaults hydrates default values in the list enterprise scale sets params (not the query body).
|
||||
//
|
||||
// All values with no default are reset to their zero value.
|
||||
func (o *ListEnterpriseScaleSetsParams) WithDefaults() *ListEnterpriseScaleSetsParams {
|
||||
o.SetDefaults()
|
||||
return o
|
||||
}
|
||||
|
||||
// SetDefaults hydrates default values in the list enterprise scale sets params (not the query body).
|
||||
//
|
||||
// All values with no default are reset to their zero value.
|
||||
func (o *ListEnterpriseScaleSetsParams) SetDefaults() {
|
||||
// no default values defined for this parameter
|
||||
}
|
||||
|
||||
// WithTimeout adds the timeout to the list enterprise scale sets params
|
||||
func (o *ListEnterpriseScaleSetsParams) WithTimeout(timeout time.Duration) *ListEnterpriseScaleSetsParams {
|
||||
o.SetTimeout(timeout)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetTimeout adds the timeout to the list enterprise scale sets params
|
||||
func (o *ListEnterpriseScaleSetsParams) SetTimeout(timeout time.Duration) {
|
||||
o.timeout = timeout
|
||||
}
|
||||
|
||||
// WithContext adds the context to the list enterprise scale sets params
|
||||
func (o *ListEnterpriseScaleSetsParams) WithContext(ctx context.Context) *ListEnterpriseScaleSetsParams {
|
||||
o.SetContext(ctx)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetContext adds the context to the list enterprise scale sets params
|
||||
func (o *ListEnterpriseScaleSetsParams) SetContext(ctx context.Context) {
|
||||
o.Context = ctx
|
||||
}
|
||||
|
||||
// WithHTTPClient adds the HTTPClient to the list enterprise scale sets params
|
||||
func (o *ListEnterpriseScaleSetsParams) WithHTTPClient(client *http.Client) *ListEnterpriseScaleSetsParams {
|
||||
o.SetHTTPClient(client)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetHTTPClient adds the HTTPClient to the list enterprise scale sets params
|
||||
func (o *ListEnterpriseScaleSetsParams) SetHTTPClient(client *http.Client) {
|
||||
o.HTTPClient = client
|
||||
}
|
||||
|
||||
// WithEnterpriseID adds the enterpriseID to the list enterprise scale sets params
|
||||
func (o *ListEnterpriseScaleSetsParams) WithEnterpriseID(enterpriseID string) *ListEnterpriseScaleSetsParams {
|
||||
o.SetEnterpriseID(enterpriseID)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetEnterpriseID adds the enterpriseId to the list enterprise scale sets params
|
||||
func (o *ListEnterpriseScaleSetsParams) SetEnterpriseID(enterpriseID string) {
|
||||
o.EnterpriseID = enterpriseID
|
||||
}
|
||||
|
||||
// WriteToRequest writes these params to a swagger request
|
||||
func (o *ListEnterpriseScaleSetsParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
|
||||
|
||||
if err := r.SetTimeout(o.timeout); err != nil {
|
||||
return err
|
||||
}
|
||||
var res []error
|
||||
|
||||
// path param enterpriseID
|
||||
if err := r.SetPathParam("enterpriseID", o.EnterpriseID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
184
client/enterprises/list_enterprise_scale_sets_responses.go
Normal file
184
client/enterprises/list_enterprise_scale_sets_responses.go
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package enterprises
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
apiserver_params "github.com/cloudbase/garm/apiserver/params"
|
||||
garm_params "github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
// ListEnterpriseScaleSetsReader is a Reader for the ListEnterpriseScaleSets structure.
|
||||
type ListEnterpriseScaleSetsReader struct {
|
||||
formats strfmt.Registry
|
||||
}
|
||||
|
||||
// ReadResponse reads a server response into the received o.
|
||||
func (o *ListEnterpriseScaleSetsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
switch response.Code() {
|
||||
case 200:
|
||||
result := NewListEnterpriseScaleSetsOK()
|
||||
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
default:
|
||||
result := NewListEnterpriseScaleSetsDefault(response.Code())
|
||||
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if response.Code()/100 == 2 {
|
||||
return result, nil
|
||||
}
|
||||
return nil, result
|
||||
}
|
||||
}
|
||||
|
||||
// NewListEnterpriseScaleSetsOK creates a ListEnterpriseScaleSetsOK with default headers values
|
||||
func NewListEnterpriseScaleSetsOK() *ListEnterpriseScaleSetsOK {
|
||||
return &ListEnterpriseScaleSetsOK{}
|
||||
}
|
||||
|
||||
/*
|
||||
ListEnterpriseScaleSetsOK describes a response with status code 200, with default header values.
|
||||
|
||||
ScaleSets
|
||||
*/
|
||||
type ListEnterpriseScaleSetsOK struct {
|
||||
Payload garm_params.ScaleSets
|
||||
}
|
||||
|
||||
// IsSuccess returns true when this list enterprise scale sets o k response has a 2xx status code
|
||||
func (o *ListEnterpriseScaleSetsOK) IsSuccess() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// IsRedirect returns true when this list enterprise scale sets o k response has a 3xx status code
|
||||
func (o *ListEnterpriseScaleSetsOK) IsRedirect() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsClientError returns true when this list enterprise scale sets o k response has a 4xx status code
|
||||
func (o *ListEnterpriseScaleSetsOK) IsClientError() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsServerError returns true when this list enterprise scale sets o k response has a 5xx status code
|
||||
func (o *ListEnterpriseScaleSetsOK) IsServerError() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsCode returns true when this list enterprise scale sets o k response a status code equal to that given
|
||||
func (o *ListEnterpriseScaleSetsOK) IsCode(code int) bool {
|
||||
return code == 200
|
||||
}
|
||||
|
||||
// Code gets the status code for the list enterprise scale sets o k response
|
||||
func (o *ListEnterpriseScaleSetsOK) Code() int {
|
||||
return 200
|
||||
}
|
||||
|
||||
func (o *ListEnterpriseScaleSetsOK) Error() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /enterprises/{enterpriseID}/scalesets][%d] listEnterpriseScaleSetsOK %s", 200, payload)
|
||||
}
|
||||
|
||||
func (o *ListEnterpriseScaleSetsOK) String() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /enterprises/{enterpriseID}/scalesets][%d] listEnterpriseScaleSetsOK %s", 200, payload)
|
||||
}
|
||||
|
||||
func (o *ListEnterpriseScaleSetsOK) GetPayload() garm_params.ScaleSets {
|
||||
return o.Payload
|
||||
}
|
||||
|
||||
func (o *ListEnterpriseScaleSetsOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewListEnterpriseScaleSetsDefault creates a ListEnterpriseScaleSetsDefault with default headers values
|
||||
func NewListEnterpriseScaleSetsDefault(code int) *ListEnterpriseScaleSetsDefault {
|
||||
return &ListEnterpriseScaleSetsDefault{
|
||||
_statusCode: code,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
ListEnterpriseScaleSetsDefault describes a response with status code -1, with default header values.
|
||||
|
||||
APIErrorResponse
|
||||
*/
|
||||
type ListEnterpriseScaleSetsDefault struct {
|
||||
_statusCode int
|
||||
|
||||
Payload apiserver_params.APIErrorResponse
|
||||
}
|
||||
|
||||
// IsSuccess returns true when this list enterprise scale sets default response has a 2xx status code
|
||||
func (o *ListEnterpriseScaleSetsDefault) IsSuccess() bool {
|
||||
return o._statusCode/100 == 2
|
||||
}
|
||||
|
||||
// IsRedirect returns true when this list enterprise scale sets default response has a 3xx status code
|
||||
func (o *ListEnterpriseScaleSetsDefault) IsRedirect() bool {
|
||||
return o._statusCode/100 == 3
|
||||
}
|
||||
|
||||
// IsClientError returns true when this list enterprise scale sets default response has a 4xx status code
|
||||
func (o *ListEnterpriseScaleSetsDefault) IsClientError() bool {
|
||||
return o._statusCode/100 == 4
|
||||
}
|
||||
|
||||
// IsServerError returns true when this list enterprise scale sets default response has a 5xx status code
|
||||
func (o *ListEnterpriseScaleSetsDefault) IsServerError() bool {
|
||||
return o._statusCode/100 == 5
|
||||
}
|
||||
|
||||
// IsCode returns true when this list enterprise scale sets default response a status code equal to that given
|
||||
func (o *ListEnterpriseScaleSetsDefault) IsCode(code int) bool {
|
||||
return o._statusCode == code
|
||||
}
|
||||
|
||||
// Code gets the status code for the list enterprise scale sets default response
|
||||
func (o *ListEnterpriseScaleSetsDefault) Code() int {
|
||||
return o._statusCode
|
||||
}
|
||||
|
||||
func (o *ListEnterpriseScaleSetsDefault) Error() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /enterprises/{enterpriseID}/scalesets][%d] ListEnterpriseScaleSets default %s", o._statusCode, payload)
|
||||
}
|
||||
|
||||
func (o *ListEnterpriseScaleSetsDefault) String() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /enterprises/{enterpriseID}/scalesets][%d] ListEnterpriseScaleSets default %s", o._statusCode, payload)
|
||||
}
|
||||
|
||||
func (o *ListEnterpriseScaleSetsDefault) GetPayload() apiserver_params.APIErrorResponse {
|
||||
return o.Payload
|
||||
}
|
||||
|
||||
func (o *ListEnterpriseScaleSetsDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -24,6 +24,7 @@ import (
|
|||
"github.com/cloudbase/garm/client/pools"
|
||||
"github.com/cloudbase/garm/client/providers"
|
||||
"github.com/cloudbase/garm/client/repositories"
|
||||
"github.com/cloudbase/garm/client/scalesets"
|
||||
)
|
||||
|
||||
// Default garm API HTTP client.
|
||||
|
|
@ -82,6 +83,7 @@ func New(transport runtime.ClientTransport, formats strfmt.Registry) *GarmAPI {
|
|||
cli.Pools = pools.New(transport, formats)
|
||||
cli.Providers = providers.New(transport, formats)
|
||||
cli.Repositories = repositories.New(transport, formats)
|
||||
cli.Scalesets = scalesets.New(transport, formats)
|
||||
return cli
|
||||
}
|
||||
|
||||
|
|
@ -154,6 +156,8 @@ type GarmAPI struct {
|
|||
|
||||
Repositories repositories.ClientService
|
||||
|
||||
Scalesets scalesets.ClientService
|
||||
|
||||
Transport runtime.ClientTransport
|
||||
}
|
||||
|
||||
|
|
@ -174,4 +178,5 @@ func (c *GarmAPI) SetTransport(transport runtime.ClientTransport) {
|
|||
c.Pools.SetTransport(transport)
|
||||
c.Providers.SetTransport(transport)
|
||||
c.Repositories.SetTransport(transport)
|
||||
c.Scalesets.SetTransport(transport)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,6 +62,8 @@ type ClientService interface {
|
|||
|
||||
ListPoolInstances(params *ListPoolInstancesParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ListPoolInstancesOK, error)
|
||||
|
||||
ListScaleSetInstances(params *ListScaleSetInstancesParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ListScaleSetInstancesOK, error)
|
||||
|
||||
SetTransport(transport runtime.ClientTransport)
|
||||
}
|
||||
|
||||
|
|
@ -211,6 +213,44 @@ func (a *Client) ListPoolInstances(params *ListPoolInstancesParams, authInfo run
|
|||
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
|
||||
}
|
||||
|
||||
/*
|
||||
ListScaleSetInstances lists runner instances in a scale set
|
||||
*/
|
||||
func (a *Client) ListScaleSetInstances(params *ListScaleSetInstancesParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ListScaleSetInstancesOK, error) {
|
||||
// TODO: Validate the params before sending
|
||||
if params == nil {
|
||||
params = NewListScaleSetInstancesParams()
|
||||
}
|
||||
op := &runtime.ClientOperation{
|
||||
ID: "ListScaleSetInstances",
|
||||
Method: "GET",
|
||||
PathPattern: "/scalesets/{scalesetID}/instances",
|
||||
ProducesMediaTypes: []string{"application/json"},
|
||||
ConsumesMediaTypes: []string{"application/json"},
|
||||
Schemes: []string{"http"},
|
||||
Params: params,
|
||||
Reader: &ListScaleSetInstancesReader{formats: a.formats},
|
||||
AuthInfo: authInfo,
|
||||
Context: params.Context,
|
||||
Client: params.HTTPClient,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(op)
|
||||
}
|
||||
|
||||
result, err := a.transport.Submit(op)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
success, ok := result.(*ListScaleSetInstancesOK)
|
||||
if ok {
|
||||
return success, nil
|
||||
}
|
||||
// unexpected success response
|
||||
unexpectedSuccess := result.(*ListScaleSetInstancesDefault)
|
||||
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
|
||||
}
|
||||
|
||||
// SetTransport changes the transport on the client
|
||||
func (a *Client) SetTransport(transport runtime.ClientTransport) {
|
||||
a.transport = transport
|
||||
|
|
|
|||
151
client/instances/list_scale_set_instances_parameters.go
Normal file
151
client/instances/list_scale_set_instances_parameters.go
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package instances
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
cr "github.com/go-openapi/runtime/client"
|
||||
"github.com/go-openapi/strfmt"
|
||||
)
|
||||
|
||||
// NewListScaleSetInstancesParams creates a new ListScaleSetInstancesParams object,
|
||||
// with the default timeout for this client.
|
||||
//
|
||||
// Default values are not hydrated, since defaults are normally applied by the API server side.
|
||||
//
|
||||
// To enforce default values in parameter, use SetDefaults or WithDefaults.
|
||||
func NewListScaleSetInstancesParams() *ListScaleSetInstancesParams {
|
||||
return &ListScaleSetInstancesParams{
|
||||
timeout: cr.DefaultTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
// NewListScaleSetInstancesParamsWithTimeout creates a new ListScaleSetInstancesParams object
|
||||
// with the ability to set a timeout on a request.
|
||||
func NewListScaleSetInstancesParamsWithTimeout(timeout time.Duration) *ListScaleSetInstancesParams {
|
||||
return &ListScaleSetInstancesParams{
|
||||
timeout: timeout,
|
||||
}
|
||||
}
|
||||
|
||||
// NewListScaleSetInstancesParamsWithContext creates a new ListScaleSetInstancesParams object
|
||||
// with the ability to set a context for a request.
|
||||
func NewListScaleSetInstancesParamsWithContext(ctx context.Context) *ListScaleSetInstancesParams {
|
||||
return &ListScaleSetInstancesParams{
|
||||
Context: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
// NewListScaleSetInstancesParamsWithHTTPClient creates a new ListScaleSetInstancesParams object
|
||||
// with the ability to set a custom HTTPClient for a request.
|
||||
func NewListScaleSetInstancesParamsWithHTTPClient(client *http.Client) *ListScaleSetInstancesParams {
|
||||
return &ListScaleSetInstancesParams{
|
||||
HTTPClient: client,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
ListScaleSetInstancesParams contains all the parameters to send to the API endpoint
|
||||
|
||||
for the list scale set instances operation.
|
||||
|
||||
Typically these are written to a http.Request.
|
||||
*/
|
||||
type ListScaleSetInstancesParams struct {
|
||||
|
||||
/* ScalesetID.
|
||||
|
||||
Runner scale set ID.
|
||||
*/
|
||||
ScalesetID string
|
||||
|
||||
timeout time.Duration
|
||||
Context context.Context
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// WithDefaults hydrates default values in the list scale set instances params (not the query body).
|
||||
//
|
||||
// All values with no default are reset to their zero value.
|
||||
func (o *ListScaleSetInstancesParams) WithDefaults() *ListScaleSetInstancesParams {
|
||||
o.SetDefaults()
|
||||
return o
|
||||
}
|
||||
|
||||
// SetDefaults hydrates default values in the list scale set instances params (not the query body).
|
||||
//
|
||||
// All values with no default are reset to their zero value.
|
||||
func (o *ListScaleSetInstancesParams) SetDefaults() {
|
||||
// no default values defined for this parameter
|
||||
}
|
||||
|
||||
// WithTimeout adds the timeout to the list scale set instances params
|
||||
func (o *ListScaleSetInstancesParams) WithTimeout(timeout time.Duration) *ListScaleSetInstancesParams {
|
||||
o.SetTimeout(timeout)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetTimeout adds the timeout to the list scale set instances params
|
||||
func (o *ListScaleSetInstancesParams) SetTimeout(timeout time.Duration) {
|
||||
o.timeout = timeout
|
||||
}
|
||||
|
||||
// WithContext adds the context to the list scale set instances params
|
||||
func (o *ListScaleSetInstancesParams) WithContext(ctx context.Context) *ListScaleSetInstancesParams {
|
||||
o.SetContext(ctx)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetContext adds the context to the list scale set instances params
|
||||
func (o *ListScaleSetInstancesParams) SetContext(ctx context.Context) {
|
||||
o.Context = ctx
|
||||
}
|
||||
|
||||
// WithHTTPClient adds the HTTPClient to the list scale set instances params
|
||||
func (o *ListScaleSetInstancesParams) WithHTTPClient(client *http.Client) *ListScaleSetInstancesParams {
|
||||
o.SetHTTPClient(client)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetHTTPClient adds the HTTPClient to the list scale set instances params
|
||||
func (o *ListScaleSetInstancesParams) SetHTTPClient(client *http.Client) {
|
||||
o.HTTPClient = client
|
||||
}
|
||||
|
||||
// WithScalesetID adds the scalesetID to the list scale set instances params
|
||||
func (o *ListScaleSetInstancesParams) WithScalesetID(scalesetID string) *ListScaleSetInstancesParams {
|
||||
o.SetScalesetID(scalesetID)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetScalesetID adds the scalesetId to the list scale set instances params
|
||||
func (o *ListScaleSetInstancesParams) SetScalesetID(scalesetID string) {
|
||||
o.ScalesetID = scalesetID
|
||||
}
|
||||
|
||||
// WriteToRequest writes these params to a swagger request
|
||||
func (o *ListScaleSetInstancesParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
|
||||
|
||||
if err := r.SetTimeout(o.timeout); err != nil {
|
||||
return err
|
||||
}
|
||||
var res []error
|
||||
|
||||
// path param scalesetID
|
||||
if err := r.SetPathParam("scalesetID", o.ScalesetID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
184
client/instances/list_scale_set_instances_responses.go
Normal file
184
client/instances/list_scale_set_instances_responses.go
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package instances
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
apiserver_params "github.com/cloudbase/garm/apiserver/params"
|
||||
garm_params "github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
// ListScaleSetInstancesReader is a Reader for the ListScaleSetInstances structure.
|
||||
type ListScaleSetInstancesReader struct {
|
||||
formats strfmt.Registry
|
||||
}
|
||||
|
||||
// ReadResponse reads a server response into the received o.
|
||||
func (o *ListScaleSetInstancesReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
switch response.Code() {
|
||||
case 200:
|
||||
result := NewListScaleSetInstancesOK()
|
||||
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
default:
|
||||
result := NewListScaleSetInstancesDefault(response.Code())
|
||||
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if response.Code()/100 == 2 {
|
||||
return result, nil
|
||||
}
|
||||
return nil, result
|
||||
}
|
||||
}
|
||||
|
||||
// NewListScaleSetInstancesOK creates a ListScaleSetInstancesOK with default headers values
|
||||
func NewListScaleSetInstancesOK() *ListScaleSetInstancesOK {
|
||||
return &ListScaleSetInstancesOK{}
|
||||
}
|
||||
|
||||
/*
|
||||
ListScaleSetInstancesOK describes a response with status code 200, with default header values.
|
||||
|
||||
Instances
|
||||
*/
|
||||
type ListScaleSetInstancesOK struct {
|
||||
Payload garm_params.Instances
|
||||
}
|
||||
|
||||
// IsSuccess returns true when this list scale set instances o k response has a 2xx status code
|
||||
func (o *ListScaleSetInstancesOK) IsSuccess() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// IsRedirect returns true when this list scale set instances o k response has a 3xx status code
|
||||
func (o *ListScaleSetInstancesOK) IsRedirect() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsClientError returns true when this list scale set instances o k response has a 4xx status code
|
||||
func (o *ListScaleSetInstancesOK) IsClientError() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsServerError returns true when this list scale set instances o k response has a 5xx status code
|
||||
func (o *ListScaleSetInstancesOK) IsServerError() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsCode returns true when this list scale set instances o k response a status code equal to that given
|
||||
func (o *ListScaleSetInstancesOK) IsCode(code int) bool {
|
||||
return code == 200
|
||||
}
|
||||
|
||||
// Code gets the status code for the list scale set instances o k response
|
||||
func (o *ListScaleSetInstancesOK) Code() int {
|
||||
return 200
|
||||
}
|
||||
|
||||
func (o *ListScaleSetInstancesOK) Error() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /scalesets/{scalesetID}/instances][%d] listScaleSetInstancesOK %s", 200, payload)
|
||||
}
|
||||
|
||||
func (o *ListScaleSetInstancesOK) String() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /scalesets/{scalesetID}/instances][%d] listScaleSetInstancesOK %s", 200, payload)
|
||||
}
|
||||
|
||||
func (o *ListScaleSetInstancesOK) GetPayload() garm_params.Instances {
|
||||
return o.Payload
|
||||
}
|
||||
|
||||
func (o *ListScaleSetInstancesOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewListScaleSetInstancesDefault creates a ListScaleSetInstancesDefault with default headers values
|
||||
func NewListScaleSetInstancesDefault(code int) *ListScaleSetInstancesDefault {
|
||||
return &ListScaleSetInstancesDefault{
|
||||
_statusCode: code,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
ListScaleSetInstancesDefault describes a response with status code -1, with default header values.
|
||||
|
||||
APIErrorResponse
|
||||
*/
|
||||
type ListScaleSetInstancesDefault struct {
|
||||
_statusCode int
|
||||
|
||||
Payload apiserver_params.APIErrorResponse
|
||||
}
|
||||
|
||||
// IsSuccess returns true when this list scale set instances default response has a 2xx status code
|
||||
func (o *ListScaleSetInstancesDefault) IsSuccess() bool {
|
||||
return o._statusCode/100 == 2
|
||||
}
|
||||
|
||||
// IsRedirect returns true when this list scale set instances default response has a 3xx status code
|
||||
func (o *ListScaleSetInstancesDefault) IsRedirect() bool {
|
||||
return o._statusCode/100 == 3
|
||||
}
|
||||
|
||||
// IsClientError returns true when this list scale set instances default response has a 4xx status code
|
||||
func (o *ListScaleSetInstancesDefault) IsClientError() bool {
|
||||
return o._statusCode/100 == 4
|
||||
}
|
||||
|
||||
// IsServerError returns true when this list scale set instances default response has a 5xx status code
|
||||
func (o *ListScaleSetInstancesDefault) IsServerError() bool {
|
||||
return o._statusCode/100 == 5
|
||||
}
|
||||
|
||||
// IsCode returns true when this list scale set instances default response a status code equal to that given
|
||||
func (o *ListScaleSetInstancesDefault) IsCode(code int) bool {
|
||||
return o._statusCode == code
|
||||
}
|
||||
|
||||
// Code gets the status code for the list scale set instances default response
|
||||
func (o *ListScaleSetInstancesDefault) Code() int {
|
||||
return o._statusCode
|
||||
}
|
||||
|
||||
func (o *ListScaleSetInstancesDefault) Error() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /scalesets/{scalesetID}/instances][%d] ListScaleSetInstances default %s", o._statusCode, payload)
|
||||
}
|
||||
|
||||
func (o *ListScaleSetInstancesDefault) String() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /scalesets/{scalesetID}/instances][%d] ListScaleSetInstances default %s", o._statusCode, payload)
|
||||
}
|
||||
|
||||
func (o *ListScaleSetInstancesDefault) GetPayload() apiserver_params.APIErrorResponse {
|
||||
return o.Payload
|
||||
}
|
||||
|
||||
func (o *ListScaleSetInstancesDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
173
client/organizations/create_org_scale_set_parameters.go
Normal file
173
client/organizations/create_org_scale_set_parameters.go
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package organizations
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
cr "github.com/go-openapi/runtime/client"
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
garm_params "github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
// NewCreateOrgScaleSetParams creates a new CreateOrgScaleSetParams object,
|
||||
// with the default timeout for this client.
|
||||
//
|
||||
// Default values are not hydrated, since defaults are normally applied by the API server side.
|
||||
//
|
||||
// To enforce default values in parameter, use SetDefaults or WithDefaults.
|
||||
func NewCreateOrgScaleSetParams() *CreateOrgScaleSetParams {
|
||||
return &CreateOrgScaleSetParams{
|
||||
timeout: cr.DefaultTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
// NewCreateOrgScaleSetParamsWithTimeout creates a new CreateOrgScaleSetParams object
|
||||
// with the ability to set a timeout on a request.
|
||||
func NewCreateOrgScaleSetParamsWithTimeout(timeout time.Duration) *CreateOrgScaleSetParams {
|
||||
return &CreateOrgScaleSetParams{
|
||||
timeout: timeout,
|
||||
}
|
||||
}
|
||||
|
||||
// NewCreateOrgScaleSetParamsWithContext creates a new CreateOrgScaleSetParams object
|
||||
// with the ability to set a context for a request.
|
||||
func NewCreateOrgScaleSetParamsWithContext(ctx context.Context) *CreateOrgScaleSetParams {
|
||||
return &CreateOrgScaleSetParams{
|
||||
Context: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
// NewCreateOrgScaleSetParamsWithHTTPClient creates a new CreateOrgScaleSetParams object
|
||||
// with the ability to set a custom HTTPClient for a request.
|
||||
func NewCreateOrgScaleSetParamsWithHTTPClient(client *http.Client) *CreateOrgScaleSetParams {
|
||||
return &CreateOrgScaleSetParams{
|
||||
HTTPClient: client,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
CreateOrgScaleSetParams contains all the parameters to send to the API endpoint
|
||||
|
||||
for the create org scale set operation.
|
||||
|
||||
Typically these are written to a http.Request.
|
||||
*/
|
||||
type CreateOrgScaleSetParams struct {
|
||||
|
||||
/* Body.
|
||||
|
||||
Parameters used when creating the organization scale set.
|
||||
*/
|
||||
Body garm_params.CreateScaleSetParams
|
||||
|
||||
/* OrgID.
|
||||
|
||||
Organization ID.
|
||||
*/
|
||||
OrgID string
|
||||
|
||||
timeout time.Duration
|
||||
Context context.Context
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// WithDefaults hydrates default values in the create org scale set params (not the query body).
|
||||
//
|
||||
// All values with no default are reset to their zero value.
|
||||
func (o *CreateOrgScaleSetParams) WithDefaults() *CreateOrgScaleSetParams {
|
||||
o.SetDefaults()
|
||||
return o
|
||||
}
|
||||
|
||||
// SetDefaults hydrates default values in the create org scale set params (not the query body).
|
||||
//
|
||||
// All values with no default are reset to their zero value.
|
||||
func (o *CreateOrgScaleSetParams) SetDefaults() {
|
||||
// no default values defined for this parameter
|
||||
}
|
||||
|
||||
// WithTimeout adds the timeout to the create org scale set params
|
||||
func (o *CreateOrgScaleSetParams) WithTimeout(timeout time.Duration) *CreateOrgScaleSetParams {
|
||||
o.SetTimeout(timeout)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetTimeout adds the timeout to the create org scale set params
|
||||
func (o *CreateOrgScaleSetParams) SetTimeout(timeout time.Duration) {
|
||||
o.timeout = timeout
|
||||
}
|
||||
|
||||
// WithContext adds the context to the create org scale set params
|
||||
func (o *CreateOrgScaleSetParams) WithContext(ctx context.Context) *CreateOrgScaleSetParams {
|
||||
o.SetContext(ctx)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetContext adds the context to the create org scale set params
|
||||
func (o *CreateOrgScaleSetParams) SetContext(ctx context.Context) {
|
||||
o.Context = ctx
|
||||
}
|
||||
|
||||
// WithHTTPClient adds the HTTPClient to the create org scale set params
|
||||
func (o *CreateOrgScaleSetParams) WithHTTPClient(client *http.Client) *CreateOrgScaleSetParams {
|
||||
o.SetHTTPClient(client)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetHTTPClient adds the HTTPClient to the create org scale set params
|
||||
func (o *CreateOrgScaleSetParams) SetHTTPClient(client *http.Client) {
|
||||
o.HTTPClient = client
|
||||
}
|
||||
|
||||
// WithBody adds the body to the create org scale set params
|
||||
func (o *CreateOrgScaleSetParams) WithBody(body garm_params.CreateScaleSetParams) *CreateOrgScaleSetParams {
|
||||
o.SetBody(body)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetBody adds the body to the create org scale set params
|
||||
func (o *CreateOrgScaleSetParams) SetBody(body garm_params.CreateScaleSetParams) {
|
||||
o.Body = body
|
||||
}
|
||||
|
||||
// WithOrgID adds the orgID to the create org scale set params
|
||||
func (o *CreateOrgScaleSetParams) WithOrgID(orgID string) *CreateOrgScaleSetParams {
|
||||
o.SetOrgID(orgID)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetOrgID adds the orgId to the create org scale set params
|
||||
func (o *CreateOrgScaleSetParams) SetOrgID(orgID string) {
|
||||
o.OrgID = orgID
|
||||
}
|
||||
|
||||
// WriteToRequest writes these params to a swagger request
|
||||
func (o *CreateOrgScaleSetParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
|
||||
|
||||
if err := r.SetTimeout(o.timeout); err != nil {
|
||||
return err
|
||||
}
|
||||
var res []error
|
||||
if err := r.SetBodyParam(o.Body); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// path param orgID
|
||||
if err := r.SetPathParam("orgID", o.OrgID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
184
client/organizations/create_org_scale_set_responses.go
Normal file
184
client/organizations/create_org_scale_set_responses.go
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package organizations
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
apiserver_params "github.com/cloudbase/garm/apiserver/params"
|
||||
garm_params "github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
// CreateOrgScaleSetReader is a Reader for the CreateOrgScaleSet structure.
|
||||
type CreateOrgScaleSetReader struct {
|
||||
formats strfmt.Registry
|
||||
}
|
||||
|
||||
// ReadResponse reads a server response into the received o.
|
||||
func (o *CreateOrgScaleSetReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
switch response.Code() {
|
||||
case 200:
|
||||
result := NewCreateOrgScaleSetOK()
|
||||
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
default:
|
||||
result := NewCreateOrgScaleSetDefault(response.Code())
|
||||
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if response.Code()/100 == 2 {
|
||||
return result, nil
|
||||
}
|
||||
return nil, result
|
||||
}
|
||||
}
|
||||
|
||||
// NewCreateOrgScaleSetOK creates a CreateOrgScaleSetOK with default headers values
|
||||
func NewCreateOrgScaleSetOK() *CreateOrgScaleSetOK {
|
||||
return &CreateOrgScaleSetOK{}
|
||||
}
|
||||
|
||||
/*
|
||||
CreateOrgScaleSetOK describes a response with status code 200, with default header values.
|
||||
|
||||
ScaleSet
|
||||
*/
|
||||
type CreateOrgScaleSetOK struct {
|
||||
Payload garm_params.ScaleSet
|
||||
}
|
||||
|
||||
// IsSuccess returns true when this create org scale set o k response has a 2xx status code
|
||||
func (o *CreateOrgScaleSetOK) IsSuccess() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// IsRedirect returns true when this create org scale set o k response has a 3xx status code
|
||||
func (o *CreateOrgScaleSetOK) IsRedirect() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsClientError returns true when this create org scale set o k response has a 4xx status code
|
||||
func (o *CreateOrgScaleSetOK) IsClientError() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsServerError returns true when this create org scale set o k response has a 5xx status code
|
||||
func (o *CreateOrgScaleSetOK) IsServerError() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsCode returns true when this create org scale set o k response a status code equal to that given
|
||||
func (o *CreateOrgScaleSetOK) IsCode(code int) bool {
|
||||
return code == 200
|
||||
}
|
||||
|
||||
// Code gets the status code for the create org scale set o k response
|
||||
func (o *CreateOrgScaleSetOK) Code() int {
|
||||
return 200
|
||||
}
|
||||
|
||||
func (o *CreateOrgScaleSetOK) Error() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[POST /organizations/{orgID}/scalesets][%d] createOrgScaleSetOK %s", 200, payload)
|
||||
}
|
||||
|
||||
func (o *CreateOrgScaleSetOK) String() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[POST /organizations/{orgID}/scalesets][%d] createOrgScaleSetOK %s", 200, payload)
|
||||
}
|
||||
|
||||
func (o *CreateOrgScaleSetOK) GetPayload() garm_params.ScaleSet {
|
||||
return o.Payload
|
||||
}
|
||||
|
||||
func (o *CreateOrgScaleSetOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewCreateOrgScaleSetDefault creates a CreateOrgScaleSetDefault with default headers values
|
||||
func NewCreateOrgScaleSetDefault(code int) *CreateOrgScaleSetDefault {
|
||||
return &CreateOrgScaleSetDefault{
|
||||
_statusCode: code,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
CreateOrgScaleSetDefault describes a response with status code -1, with default header values.
|
||||
|
||||
APIErrorResponse
|
||||
*/
|
||||
type CreateOrgScaleSetDefault struct {
|
||||
_statusCode int
|
||||
|
||||
Payload apiserver_params.APIErrorResponse
|
||||
}
|
||||
|
||||
// IsSuccess returns true when this create org scale set default response has a 2xx status code
|
||||
func (o *CreateOrgScaleSetDefault) IsSuccess() bool {
|
||||
return o._statusCode/100 == 2
|
||||
}
|
||||
|
||||
// IsRedirect returns true when this create org scale set default response has a 3xx status code
|
||||
func (o *CreateOrgScaleSetDefault) IsRedirect() bool {
|
||||
return o._statusCode/100 == 3
|
||||
}
|
||||
|
||||
// IsClientError returns true when this create org scale set default response has a 4xx status code
|
||||
func (o *CreateOrgScaleSetDefault) IsClientError() bool {
|
||||
return o._statusCode/100 == 4
|
||||
}
|
||||
|
||||
// IsServerError returns true when this create org scale set default response has a 5xx status code
|
||||
func (o *CreateOrgScaleSetDefault) IsServerError() bool {
|
||||
return o._statusCode/100 == 5
|
||||
}
|
||||
|
||||
// IsCode returns true when this create org scale set default response a status code equal to that given
|
||||
func (o *CreateOrgScaleSetDefault) IsCode(code int) bool {
|
||||
return o._statusCode == code
|
||||
}
|
||||
|
||||
// Code gets the status code for the create org scale set default response
|
||||
func (o *CreateOrgScaleSetDefault) Code() int {
|
||||
return o._statusCode
|
||||
}
|
||||
|
||||
func (o *CreateOrgScaleSetDefault) Error() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[POST /organizations/{orgID}/scalesets][%d] CreateOrgScaleSet default %s", o._statusCode, payload)
|
||||
}
|
||||
|
||||
func (o *CreateOrgScaleSetDefault) String() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[POST /organizations/{orgID}/scalesets][%d] CreateOrgScaleSet default %s", o._statusCode, payload)
|
||||
}
|
||||
|
||||
func (o *CreateOrgScaleSetDefault) GetPayload() apiserver_params.APIErrorResponse {
|
||||
return o.Payload
|
||||
}
|
||||
|
||||
func (o *CreateOrgScaleSetDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
151
client/organizations/list_org_scale_sets_parameters.go
Normal file
151
client/organizations/list_org_scale_sets_parameters.go
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package organizations
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
cr "github.com/go-openapi/runtime/client"
|
||||
"github.com/go-openapi/strfmt"
|
||||
)
|
||||
|
||||
// NewListOrgScaleSetsParams creates a new ListOrgScaleSetsParams object,
|
||||
// with the default timeout for this client.
|
||||
//
|
||||
// Default values are not hydrated, since defaults are normally applied by the API server side.
|
||||
//
|
||||
// To enforce default values in parameter, use SetDefaults or WithDefaults.
|
||||
func NewListOrgScaleSetsParams() *ListOrgScaleSetsParams {
|
||||
return &ListOrgScaleSetsParams{
|
||||
timeout: cr.DefaultTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
// NewListOrgScaleSetsParamsWithTimeout creates a new ListOrgScaleSetsParams object
|
||||
// with the ability to set a timeout on a request.
|
||||
func NewListOrgScaleSetsParamsWithTimeout(timeout time.Duration) *ListOrgScaleSetsParams {
|
||||
return &ListOrgScaleSetsParams{
|
||||
timeout: timeout,
|
||||
}
|
||||
}
|
||||
|
||||
// NewListOrgScaleSetsParamsWithContext creates a new ListOrgScaleSetsParams object
|
||||
// with the ability to set a context for a request.
|
||||
func NewListOrgScaleSetsParamsWithContext(ctx context.Context) *ListOrgScaleSetsParams {
|
||||
return &ListOrgScaleSetsParams{
|
||||
Context: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
// NewListOrgScaleSetsParamsWithHTTPClient creates a new ListOrgScaleSetsParams object
|
||||
// with the ability to set a custom HTTPClient for a request.
|
||||
func NewListOrgScaleSetsParamsWithHTTPClient(client *http.Client) *ListOrgScaleSetsParams {
|
||||
return &ListOrgScaleSetsParams{
|
||||
HTTPClient: client,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
ListOrgScaleSetsParams contains all the parameters to send to the API endpoint
|
||||
|
||||
for the list org scale sets operation.
|
||||
|
||||
Typically these are written to a http.Request.
|
||||
*/
|
||||
type ListOrgScaleSetsParams struct {
|
||||
|
||||
/* OrgID.
|
||||
|
||||
Organization ID.
|
||||
*/
|
||||
OrgID string
|
||||
|
||||
timeout time.Duration
|
||||
Context context.Context
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// WithDefaults hydrates default values in the list org scale sets params (not the query body).
|
||||
//
|
||||
// All values with no default are reset to their zero value.
|
||||
func (o *ListOrgScaleSetsParams) WithDefaults() *ListOrgScaleSetsParams {
|
||||
o.SetDefaults()
|
||||
return o
|
||||
}
|
||||
|
||||
// SetDefaults hydrates default values in the list org scale sets params (not the query body).
|
||||
//
|
||||
// All values with no default are reset to their zero value.
|
||||
func (o *ListOrgScaleSetsParams) SetDefaults() {
|
||||
// no default values defined for this parameter
|
||||
}
|
||||
|
||||
// WithTimeout adds the timeout to the list org scale sets params
|
||||
func (o *ListOrgScaleSetsParams) WithTimeout(timeout time.Duration) *ListOrgScaleSetsParams {
|
||||
o.SetTimeout(timeout)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetTimeout adds the timeout to the list org scale sets params
|
||||
func (o *ListOrgScaleSetsParams) SetTimeout(timeout time.Duration) {
|
||||
o.timeout = timeout
|
||||
}
|
||||
|
||||
// WithContext adds the context to the list org scale sets params
|
||||
func (o *ListOrgScaleSetsParams) WithContext(ctx context.Context) *ListOrgScaleSetsParams {
|
||||
o.SetContext(ctx)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetContext adds the context to the list org scale sets params
|
||||
func (o *ListOrgScaleSetsParams) SetContext(ctx context.Context) {
|
||||
o.Context = ctx
|
||||
}
|
||||
|
||||
// WithHTTPClient adds the HTTPClient to the list org scale sets params
|
||||
func (o *ListOrgScaleSetsParams) WithHTTPClient(client *http.Client) *ListOrgScaleSetsParams {
|
||||
o.SetHTTPClient(client)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetHTTPClient adds the HTTPClient to the list org scale sets params
|
||||
func (o *ListOrgScaleSetsParams) SetHTTPClient(client *http.Client) {
|
||||
o.HTTPClient = client
|
||||
}
|
||||
|
||||
// WithOrgID adds the orgID to the list org scale sets params
|
||||
func (o *ListOrgScaleSetsParams) WithOrgID(orgID string) *ListOrgScaleSetsParams {
|
||||
o.SetOrgID(orgID)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetOrgID adds the orgId to the list org scale sets params
|
||||
func (o *ListOrgScaleSetsParams) SetOrgID(orgID string) {
|
||||
o.OrgID = orgID
|
||||
}
|
||||
|
||||
// WriteToRequest writes these params to a swagger request
|
||||
func (o *ListOrgScaleSetsParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
|
||||
|
||||
if err := r.SetTimeout(o.timeout); err != nil {
|
||||
return err
|
||||
}
|
||||
var res []error
|
||||
|
||||
// path param orgID
|
||||
if err := r.SetPathParam("orgID", o.OrgID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
184
client/organizations/list_org_scale_sets_responses.go
Normal file
184
client/organizations/list_org_scale_sets_responses.go
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package organizations
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
apiserver_params "github.com/cloudbase/garm/apiserver/params"
|
||||
garm_params "github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
// ListOrgScaleSetsReader is a Reader for the ListOrgScaleSets structure.
|
||||
type ListOrgScaleSetsReader struct {
|
||||
formats strfmt.Registry
|
||||
}
|
||||
|
||||
// ReadResponse reads a server response into the received o.
|
||||
func (o *ListOrgScaleSetsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
switch response.Code() {
|
||||
case 200:
|
||||
result := NewListOrgScaleSetsOK()
|
||||
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
default:
|
||||
result := NewListOrgScaleSetsDefault(response.Code())
|
||||
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if response.Code()/100 == 2 {
|
||||
return result, nil
|
||||
}
|
||||
return nil, result
|
||||
}
|
||||
}
|
||||
|
||||
// NewListOrgScaleSetsOK creates a ListOrgScaleSetsOK with default headers values
|
||||
func NewListOrgScaleSetsOK() *ListOrgScaleSetsOK {
|
||||
return &ListOrgScaleSetsOK{}
|
||||
}
|
||||
|
||||
/*
|
||||
ListOrgScaleSetsOK describes a response with status code 200, with default header values.
|
||||
|
||||
ScaleSets
|
||||
*/
|
||||
type ListOrgScaleSetsOK struct {
|
||||
Payload garm_params.ScaleSets
|
||||
}
|
||||
|
||||
// IsSuccess returns true when this list org scale sets o k response has a 2xx status code
|
||||
func (o *ListOrgScaleSetsOK) IsSuccess() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// IsRedirect returns true when this list org scale sets o k response has a 3xx status code
|
||||
func (o *ListOrgScaleSetsOK) IsRedirect() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsClientError returns true when this list org scale sets o k response has a 4xx status code
|
||||
func (o *ListOrgScaleSetsOK) IsClientError() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsServerError returns true when this list org scale sets o k response has a 5xx status code
|
||||
func (o *ListOrgScaleSetsOK) IsServerError() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsCode returns true when this list org scale sets o k response a status code equal to that given
|
||||
func (o *ListOrgScaleSetsOK) IsCode(code int) bool {
|
||||
return code == 200
|
||||
}
|
||||
|
||||
// Code gets the status code for the list org scale sets o k response
|
||||
func (o *ListOrgScaleSetsOK) Code() int {
|
||||
return 200
|
||||
}
|
||||
|
||||
func (o *ListOrgScaleSetsOK) Error() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /organizations/{orgID}/scalesets][%d] listOrgScaleSetsOK %s", 200, payload)
|
||||
}
|
||||
|
||||
func (o *ListOrgScaleSetsOK) String() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /organizations/{orgID}/scalesets][%d] listOrgScaleSetsOK %s", 200, payload)
|
||||
}
|
||||
|
||||
func (o *ListOrgScaleSetsOK) GetPayload() garm_params.ScaleSets {
|
||||
return o.Payload
|
||||
}
|
||||
|
||||
func (o *ListOrgScaleSetsOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewListOrgScaleSetsDefault creates a ListOrgScaleSetsDefault with default headers values
|
||||
func NewListOrgScaleSetsDefault(code int) *ListOrgScaleSetsDefault {
|
||||
return &ListOrgScaleSetsDefault{
|
||||
_statusCode: code,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
ListOrgScaleSetsDefault describes a response with status code -1, with default header values.
|
||||
|
||||
APIErrorResponse
|
||||
*/
|
||||
type ListOrgScaleSetsDefault struct {
|
||||
_statusCode int
|
||||
|
||||
Payload apiserver_params.APIErrorResponse
|
||||
}
|
||||
|
||||
// IsSuccess returns true when this list org scale sets default response has a 2xx status code
|
||||
func (o *ListOrgScaleSetsDefault) IsSuccess() bool {
|
||||
return o._statusCode/100 == 2
|
||||
}
|
||||
|
||||
// IsRedirect returns true when this list org scale sets default response has a 3xx status code
|
||||
func (o *ListOrgScaleSetsDefault) IsRedirect() bool {
|
||||
return o._statusCode/100 == 3
|
||||
}
|
||||
|
||||
// IsClientError returns true when this list org scale sets default response has a 4xx status code
|
||||
func (o *ListOrgScaleSetsDefault) IsClientError() bool {
|
||||
return o._statusCode/100 == 4
|
||||
}
|
||||
|
||||
// IsServerError returns true when this list org scale sets default response has a 5xx status code
|
||||
func (o *ListOrgScaleSetsDefault) IsServerError() bool {
|
||||
return o._statusCode/100 == 5
|
||||
}
|
||||
|
||||
// IsCode returns true when this list org scale sets default response a status code equal to that given
|
||||
func (o *ListOrgScaleSetsDefault) IsCode(code int) bool {
|
||||
return o._statusCode == code
|
||||
}
|
||||
|
||||
// Code gets the status code for the list org scale sets default response
|
||||
func (o *ListOrgScaleSetsDefault) Code() int {
|
||||
return o._statusCode
|
||||
}
|
||||
|
||||
func (o *ListOrgScaleSetsDefault) Error() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /organizations/{orgID}/scalesets][%d] ListOrgScaleSets default %s", o._statusCode, payload)
|
||||
}
|
||||
|
||||
func (o *ListOrgScaleSetsDefault) String() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /organizations/{orgID}/scalesets][%d] ListOrgScaleSets default %s", o._statusCode, payload)
|
||||
}
|
||||
|
||||
func (o *ListOrgScaleSetsDefault) GetPayload() apiserver_params.APIErrorResponse {
|
||||
return o.Payload
|
||||
}
|
||||
|
||||
func (o *ListOrgScaleSetsDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -58,6 +58,8 @@ type ClientService interface {
|
|||
|
||||
CreateOrgPool(params *CreateOrgPoolParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*CreateOrgPoolOK, error)
|
||||
|
||||
CreateOrgScaleSet(params *CreateOrgScaleSetParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*CreateOrgScaleSetOK, error)
|
||||
|
||||
DeleteOrg(params *DeleteOrgParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) error
|
||||
|
||||
DeleteOrgPool(params *DeleteOrgPoolParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) error
|
||||
|
|
@ -74,6 +76,8 @@ type ClientService interface {
|
|||
|
||||
ListOrgPools(params *ListOrgPoolsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ListOrgPoolsOK, error)
|
||||
|
||||
ListOrgScaleSets(params *ListOrgScaleSetsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ListOrgScaleSetsOK, error)
|
||||
|
||||
ListOrgs(params *ListOrgsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ListOrgsOK, error)
|
||||
|
||||
UninstallOrgWebhook(params *UninstallOrgWebhookParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) error
|
||||
|
|
@ -161,6 +165,44 @@ func (a *Client) CreateOrgPool(params *CreateOrgPoolParams, authInfo runtime.Cli
|
|||
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
|
||||
}
|
||||
|
||||
/*
|
||||
CreateOrgScaleSet creates organization scale set with the parameters given
|
||||
*/
|
||||
func (a *Client) CreateOrgScaleSet(params *CreateOrgScaleSetParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*CreateOrgScaleSetOK, error) {
|
||||
// TODO: Validate the params before sending
|
||||
if params == nil {
|
||||
params = NewCreateOrgScaleSetParams()
|
||||
}
|
||||
op := &runtime.ClientOperation{
|
||||
ID: "CreateOrgScaleSet",
|
||||
Method: "POST",
|
||||
PathPattern: "/organizations/{orgID}/scalesets",
|
||||
ProducesMediaTypes: []string{"application/json"},
|
||||
ConsumesMediaTypes: []string{"application/json"},
|
||||
Schemes: []string{"http"},
|
||||
Params: params,
|
||||
Reader: &CreateOrgScaleSetReader{formats: a.formats},
|
||||
AuthInfo: authInfo,
|
||||
Context: params.Context,
|
||||
Client: params.HTTPClient,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(op)
|
||||
}
|
||||
|
||||
result, err := a.transport.Submit(op)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
success, ok := result.(*CreateOrgScaleSetOK)
|
||||
if ok {
|
||||
return success, nil
|
||||
}
|
||||
// unexpected success response
|
||||
unexpectedSuccess := result.(*CreateOrgScaleSetDefault)
|
||||
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
|
||||
}
|
||||
|
||||
/*
|
||||
DeleteOrg deletes organization by ID
|
||||
*/
|
||||
|
|
@ -455,6 +497,44 @@ func (a *Client) ListOrgPools(params *ListOrgPoolsParams, authInfo runtime.Clien
|
|||
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
|
||||
}
|
||||
|
||||
/*
|
||||
ListOrgScaleSets lists organization scale sets
|
||||
*/
|
||||
func (a *Client) ListOrgScaleSets(params *ListOrgScaleSetsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ListOrgScaleSetsOK, error) {
|
||||
// TODO: Validate the params before sending
|
||||
if params == nil {
|
||||
params = NewListOrgScaleSetsParams()
|
||||
}
|
||||
op := &runtime.ClientOperation{
|
||||
ID: "ListOrgScaleSets",
|
||||
Method: "GET",
|
||||
PathPattern: "/organizations/{orgID}/scalesets",
|
||||
ProducesMediaTypes: []string{"application/json"},
|
||||
ConsumesMediaTypes: []string{"application/json"},
|
||||
Schemes: []string{"http"},
|
||||
Params: params,
|
||||
Reader: &ListOrgScaleSetsReader{formats: a.formats},
|
||||
AuthInfo: authInfo,
|
||||
Context: params.Context,
|
||||
Client: params.HTTPClient,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(op)
|
||||
}
|
||||
|
||||
result, err := a.transport.Submit(op)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
success, ok := result.(*ListOrgScaleSetsOK)
|
||||
if ok {
|
||||
return success, nil
|
||||
}
|
||||
// unexpected success response
|
||||
unexpectedSuccess := result.(*ListOrgScaleSetsDefault)
|
||||
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
|
||||
}
|
||||
|
||||
/*
|
||||
ListOrgs lists organizations
|
||||
*/
|
||||
|
|
|
|||
173
client/repositories/create_repo_scale_set_parameters.go
Normal file
173
client/repositories/create_repo_scale_set_parameters.go
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package repositories
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
cr "github.com/go-openapi/runtime/client"
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
garm_params "github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
// NewCreateRepoScaleSetParams creates a new CreateRepoScaleSetParams object,
|
||||
// with the default timeout for this client.
|
||||
//
|
||||
// Default values are not hydrated, since defaults are normally applied by the API server side.
|
||||
//
|
||||
// To enforce default values in parameter, use SetDefaults or WithDefaults.
|
||||
func NewCreateRepoScaleSetParams() *CreateRepoScaleSetParams {
|
||||
return &CreateRepoScaleSetParams{
|
||||
timeout: cr.DefaultTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
// NewCreateRepoScaleSetParamsWithTimeout creates a new CreateRepoScaleSetParams object
|
||||
// with the ability to set a timeout on a request.
|
||||
func NewCreateRepoScaleSetParamsWithTimeout(timeout time.Duration) *CreateRepoScaleSetParams {
|
||||
return &CreateRepoScaleSetParams{
|
||||
timeout: timeout,
|
||||
}
|
||||
}
|
||||
|
||||
// NewCreateRepoScaleSetParamsWithContext creates a new CreateRepoScaleSetParams object
|
||||
// with the ability to set a context for a request.
|
||||
func NewCreateRepoScaleSetParamsWithContext(ctx context.Context) *CreateRepoScaleSetParams {
|
||||
return &CreateRepoScaleSetParams{
|
||||
Context: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
// NewCreateRepoScaleSetParamsWithHTTPClient creates a new CreateRepoScaleSetParams object
|
||||
// with the ability to set a custom HTTPClient for a request.
|
||||
func NewCreateRepoScaleSetParamsWithHTTPClient(client *http.Client) *CreateRepoScaleSetParams {
|
||||
return &CreateRepoScaleSetParams{
|
||||
HTTPClient: client,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
CreateRepoScaleSetParams contains all the parameters to send to the API endpoint
|
||||
|
||||
for the create repo scale set operation.
|
||||
|
||||
Typically these are written to a http.Request.
|
||||
*/
|
||||
type CreateRepoScaleSetParams struct {
|
||||
|
||||
/* Body.
|
||||
|
||||
Parameters used when creating the repository scale set.
|
||||
*/
|
||||
Body garm_params.CreateScaleSetParams
|
||||
|
||||
/* RepoID.
|
||||
|
||||
Repository ID.
|
||||
*/
|
||||
RepoID string
|
||||
|
||||
timeout time.Duration
|
||||
Context context.Context
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// WithDefaults hydrates default values in the create repo scale set params (not the query body).
|
||||
//
|
||||
// All values with no default are reset to their zero value.
|
||||
func (o *CreateRepoScaleSetParams) WithDefaults() *CreateRepoScaleSetParams {
|
||||
o.SetDefaults()
|
||||
return o
|
||||
}
|
||||
|
||||
// SetDefaults hydrates default values in the create repo scale set params (not the query body).
|
||||
//
|
||||
// All values with no default are reset to their zero value.
|
||||
func (o *CreateRepoScaleSetParams) SetDefaults() {
|
||||
// no default values defined for this parameter
|
||||
}
|
||||
|
||||
// WithTimeout adds the timeout to the create repo scale set params
|
||||
func (o *CreateRepoScaleSetParams) WithTimeout(timeout time.Duration) *CreateRepoScaleSetParams {
|
||||
o.SetTimeout(timeout)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetTimeout adds the timeout to the create repo scale set params
|
||||
func (o *CreateRepoScaleSetParams) SetTimeout(timeout time.Duration) {
|
||||
o.timeout = timeout
|
||||
}
|
||||
|
||||
// WithContext adds the context to the create repo scale set params
|
||||
func (o *CreateRepoScaleSetParams) WithContext(ctx context.Context) *CreateRepoScaleSetParams {
|
||||
o.SetContext(ctx)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetContext adds the context to the create repo scale set params
|
||||
func (o *CreateRepoScaleSetParams) SetContext(ctx context.Context) {
|
||||
o.Context = ctx
|
||||
}
|
||||
|
||||
// WithHTTPClient adds the HTTPClient to the create repo scale set params
|
||||
func (o *CreateRepoScaleSetParams) WithHTTPClient(client *http.Client) *CreateRepoScaleSetParams {
|
||||
o.SetHTTPClient(client)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetHTTPClient adds the HTTPClient to the create repo scale set params
|
||||
func (o *CreateRepoScaleSetParams) SetHTTPClient(client *http.Client) {
|
||||
o.HTTPClient = client
|
||||
}
|
||||
|
||||
// WithBody adds the body to the create repo scale set params
|
||||
func (o *CreateRepoScaleSetParams) WithBody(body garm_params.CreateScaleSetParams) *CreateRepoScaleSetParams {
|
||||
o.SetBody(body)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetBody adds the body to the create repo scale set params
|
||||
func (o *CreateRepoScaleSetParams) SetBody(body garm_params.CreateScaleSetParams) {
|
||||
o.Body = body
|
||||
}
|
||||
|
||||
// WithRepoID adds the repoID to the create repo scale set params
|
||||
func (o *CreateRepoScaleSetParams) WithRepoID(repoID string) *CreateRepoScaleSetParams {
|
||||
o.SetRepoID(repoID)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetRepoID adds the repoId to the create repo scale set params
|
||||
func (o *CreateRepoScaleSetParams) SetRepoID(repoID string) {
|
||||
o.RepoID = repoID
|
||||
}
|
||||
|
||||
// WriteToRequest writes these params to a swagger request
|
||||
func (o *CreateRepoScaleSetParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
|
||||
|
||||
if err := r.SetTimeout(o.timeout); err != nil {
|
||||
return err
|
||||
}
|
||||
var res []error
|
||||
if err := r.SetBodyParam(o.Body); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// path param repoID
|
||||
if err := r.SetPathParam("repoID", o.RepoID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
184
client/repositories/create_repo_scale_set_responses.go
Normal file
184
client/repositories/create_repo_scale_set_responses.go
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package repositories
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
apiserver_params "github.com/cloudbase/garm/apiserver/params"
|
||||
garm_params "github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
// CreateRepoScaleSetReader is a Reader for the CreateRepoScaleSet structure.
|
||||
type CreateRepoScaleSetReader struct {
|
||||
formats strfmt.Registry
|
||||
}
|
||||
|
||||
// ReadResponse reads a server response into the received o.
|
||||
func (o *CreateRepoScaleSetReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
switch response.Code() {
|
||||
case 200:
|
||||
result := NewCreateRepoScaleSetOK()
|
||||
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
default:
|
||||
result := NewCreateRepoScaleSetDefault(response.Code())
|
||||
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if response.Code()/100 == 2 {
|
||||
return result, nil
|
||||
}
|
||||
return nil, result
|
||||
}
|
||||
}
|
||||
|
||||
// NewCreateRepoScaleSetOK creates a CreateRepoScaleSetOK with default headers values
|
||||
func NewCreateRepoScaleSetOK() *CreateRepoScaleSetOK {
|
||||
return &CreateRepoScaleSetOK{}
|
||||
}
|
||||
|
||||
/*
|
||||
CreateRepoScaleSetOK describes a response with status code 200, with default header values.
|
||||
|
||||
ScaleSet
|
||||
*/
|
||||
type CreateRepoScaleSetOK struct {
|
||||
Payload garm_params.ScaleSet
|
||||
}
|
||||
|
||||
// IsSuccess returns true when this create repo scale set o k response has a 2xx status code
|
||||
func (o *CreateRepoScaleSetOK) IsSuccess() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// IsRedirect returns true when this create repo scale set o k response has a 3xx status code
|
||||
func (o *CreateRepoScaleSetOK) IsRedirect() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsClientError returns true when this create repo scale set o k response has a 4xx status code
|
||||
func (o *CreateRepoScaleSetOK) IsClientError() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsServerError returns true when this create repo scale set o k response has a 5xx status code
|
||||
func (o *CreateRepoScaleSetOK) IsServerError() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsCode returns true when this create repo scale set o k response a status code equal to that given
|
||||
func (o *CreateRepoScaleSetOK) IsCode(code int) bool {
|
||||
return code == 200
|
||||
}
|
||||
|
||||
// Code gets the status code for the create repo scale set o k response
|
||||
func (o *CreateRepoScaleSetOK) Code() int {
|
||||
return 200
|
||||
}
|
||||
|
||||
func (o *CreateRepoScaleSetOK) Error() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[POST /repositories/{repoID}/scalesets][%d] createRepoScaleSetOK %s", 200, payload)
|
||||
}
|
||||
|
||||
func (o *CreateRepoScaleSetOK) String() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[POST /repositories/{repoID}/scalesets][%d] createRepoScaleSetOK %s", 200, payload)
|
||||
}
|
||||
|
||||
func (o *CreateRepoScaleSetOK) GetPayload() garm_params.ScaleSet {
|
||||
return o.Payload
|
||||
}
|
||||
|
||||
func (o *CreateRepoScaleSetOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewCreateRepoScaleSetDefault creates a CreateRepoScaleSetDefault with default headers values
|
||||
func NewCreateRepoScaleSetDefault(code int) *CreateRepoScaleSetDefault {
|
||||
return &CreateRepoScaleSetDefault{
|
||||
_statusCode: code,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
CreateRepoScaleSetDefault describes a response with status code -1, with default header values.
|
||||
|
||||
APIErrorResponse
|
||||
*/
|
||||
type CreateRepoScaleSetDefault struct {
|
||||
_statusCode int
|
||||
|
||||
Payload apiserver_params.APIErrorResponse
|
||||
}
|
||||
|
||||
// IsSuccess returns true when this create repo scale set default response has a 2xx status code
|
||||
func (o *CreateRepoScaleSetDefault) IsSuccess() bool {
|
||||
return o._statusCode/100 == 2
|
||||
}
|
||||
|
||||
// IsRedirect returns true when this create repo scale set default response has a 3xx status code
|
||||
func (o *CreateRepoScaleSetDefault) IsRedirect() bool {
|
||||
return o._statusCode/100 == 3
|
||||
}
|
||||
|
||||
// IsClientError returns true when this create repo scale set default response has a 4xx status code
|
||||
func (o *CreateRepoScaleSetDefault) IsClientError() bool {
|
||||
return o._statusCode/100 == 4
|
||||
}
|
||||
|
||||
// IsServerError returns true when this create repo scale set default response has a 5xx status code
|
||||
func (o *CreateRepoScaleSetDefault) IsServerError() bool {
|
||||
return o._statusCode/100 == 5
|
||||
}
|
||||
|
||||
// IsCode returns true when this create repo scale set default response a status code equal to that given
|
||||
func (o *CreateRepoScaleSetDefault) IsCode(code int) bool {
|
||||
return o._statusCode == code
|
||||
}
|
||||
|
||||
// Code gets the status code for the create repo scale set default response
|
||||
func (o *CreateRepoScaleSetDefault) Code() int {
|
||||
return o._statusCode
|
||||
}
|
||||
|
||||
func (o *CreateRepoScaleSetDefault) Error() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[POST /repositories/{repoID}/scalesets][%d] CreateRepoScaleSet default %s", o._statusCode, payload)
|
||||
}
|
||||
|
||||
func (o *CreateRepoScaleSetDefault) String() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[POST /repositories/{repoID}/scalesets][%d] CreateRepoScaleSet default %s", o._statusCode, payload)
|
||||
}
|
||||
|
||||
func (o *CreateRepoScaleSetDefault) GetPayload() apiserver_params.APIErrorResponse {
|
||||
return o.Payload
|
||||
}
|
||||
|
||||
func (o *CreateRepoScaleSetDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
151
client/repositories/list_repo_scale_sets_parameters.go
Normal file
151
client/repositories/list_repo_scale_sets_parameters.go
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package repositories
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
cr "github.com/go-openapi/runtime/client"
|
||||
"github.com/go-openapi/strfmt"
|
||||
)
|
||||
|
||||
// NewListRepoScaleSetsParams creates a new ListRepoScaleSetsParams object,
|
||||
// with the default timeout for this client.
|
||||
//
|
||||
// Default values are not hydrated, since defaults are normally applied by the API server side.
|
||||
//
|
||||
// To enforce default values in parameter, use SetDefaults or WithDefaults.
|
||||
func NewListRepoScaleSetsParams() *ListRepoScaleSetsParams {
|
||||
return &ListRepoScaleSetsParams{
|
||||
timeout: cr.DefaultTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
// NewListRepoScaleSetsParamsWithTimeout creates a new ListRepoScaleSetsParams object
|
||||
// with the ability to set a timeout on a request.
|
||||
func NewListRepoScaleSetsParamsWithTimeout(timeout time.Duration) *ListRepoScaleSetsParams {
|
||||
return &ListRepoScaleSetsParams{
|
||||
timeout: timeout,
|
||||
}
|
||||
}
|
||||
|
||||
// NewListRepoScaleSetsParamsWithContext creates a new ListRepoScaleSetsParams object
|
||||
// with the ability to set a context for a request.
|
||||
func NewListRepoScaleSetsParamsWithContext(ctx context.Context) *ListRepoScaleSetsParams {
|
||||
return &ListRepoScaleSetsParams{
|
||||
Context: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
// NewListRepoScaleSetsParamsWithHTTPClient creates a new ListRepoScaleSetsParams object
|
||||
// with the ability to set a custom HTTPClient for a request.
|
||||
func NewListRepoScaleSetsParamsWithHTTPClient(client *http.Client) *ListRepoScaleSetsParams {
|
||||
return &ListRepoScaleSetsParams{
|
||||
HTTPClient: client,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
ListRepoScaleSetsParams contains all the parameters to send to the API endpoint
|
||||
|
||||
for the list repo scale sets operation.
|
||||
|
||||
Typically these are written to a http.Request.
|
||||
*/
|
||||
type ListRepoScaleSetsParams struct {
|
||||
|
||||
/* RepoID.
|
||||
|
||||
Repository ID.
|
||||
*/
|
||||
RepoID string
|
||||
|
||||
timeout time.Duration
|
||||
Context context.Context
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// WithDefaults hydrates default values in the list repo scale sets params (not the query body).
|
||||
//
|
||||
// All values with no default are reset to their zero value.
|
||||
func (o *ListRepoScaleSetsParams) WithDefaults() *ListRepoScaleSetsParams {
|
||||
o.SetDefaults()
|
||||
return o
|
||||
}
|
||||
|
||||
// SetDefaults hydrates default values in the list repo scale sets params (not the query body).
|
||||
//
|
||||
// All values with no default are reset to their zero value.
|
||||
func (o *ListRepoScaleSetsParams) SetDefaults() {
|
||||
// no default values defined for this parameter
|
||||
}
|
||||
|
||||
// WithTimeout adds the timeout to the list repo scale sets params
|
||||
func (o *ListRepoScaleSetsParams) WithTimeout(timeout time.Duration) *ListRepoScaleSetsParams {
|
||||
o.SetTimeout(timeout)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetTimeout adds the timeout to the list repo scale sets params
|
||||
func (o *ListRepoScaleSetsParams) SetTimeout(timeout time.Duration) {
|
||||
o.timeout = timeout
|
||||
}
|
||||
|
||||
// WithContext adds the context to the list repo scale sets params
|
||||
func (o *ListRepoScaleSetsParams) WithContext(ctx context.Context) *ListRepoScaleSetsParams {
|
||||
o.SetContext(ctx)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetContext adds the context to the list repo scale sets params
|
||||
func (o *ListRepoScaleSetsParams) SetContext(ctx context.Context) {
|
||||
o.Context = ctx
|
||||
}
|
||||
|
||||
// WithHTTPClient adds the HTTPClient to the list repo scale sets params
|
||||
func (o *ListRepoScaleSetsParams) WithHTTPClient(client *http.Client) *ListRepoScaleSetsParams {
|
||||
o.SetHTTPClient(client)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetHTTPClient adds the HTTPClient to the list repo scale sets params
|
||||
func (o *ListRepoScaleSetsParams) SetHTTPClient(client *http.Client) {
|
||||
o.HTTPClient = client
|
||||
}
|
||||
|
||||
// WithRepoID adds the repoID to the list repo scale sets params
|
||||
func (o *ListRepoScaleSetsParams) WithRepoID(repoID string) *ListRepoScaleSetsParams {
|
||||
o.SetRepoID(repoID)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetRepoID adds the repoId to the list repo scale sets params
|
||||
func (o *ListRepoScaleSetsParams) SetRepoID(repoID string) {
|
||||
o.RepoID = repoID
|
||||
}
|
||||
|
||||
// WriteToRequest writes these params to a swagger request
|
||||
func (o *ListRepoScaleSetsParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
|
||||
|
||||
if err := r.SetTimeout(o.timeout); err != nil {
|
||||
return err
|
||||
}
|
||||
var res []error
|
||||
|
||||
// path param repoID
|
||||
if err := r.SetPathParam("repoID", o.RepoID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
184
client/repositories/list_repo_scale_sets_responses.go
Normal file
184
client/repositories/list_repo_scale_sets_responses.go
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package repositories
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
apiserver_params "github.com/cloudbase/garm/apiserver/params"
|
||||
garm_params "github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
// ListRepoScaleSetsReader is a Reader for the ListRepoScaleSets structure.
|
||||
type ListRepoScaleSetsReader struct {
|
||||
formats strfmt.Registry
|
||||
}
|
||||
|
||||
// ReadResponse reads a server response into the received o.
|
||||
func (o *ListRepoScaleSetsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
switch response.Code() {
|
||||
case 200:
|
||||
result := NewListRepoScaleSetsOK()
|
||||
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
default:
|
||||
result := NewListRepoScaleSetsDefault(response.Code())
|
||||
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if response.Code()/100 == 2 {
|
||||
return result, nil
|
||||
}
|
||||
return nil, result
|
||||
}
|
||||
}
|
||||
|
||||
// NewListRepoScaleSetsOK creates a ListRepoScaleSetsOK with default headers values
|
||||
func NewListRepoScaleSetsOK() *ListRepoScaleSetsOK {
|
||||
return &ListRepoScaleSetsOK{}
|
||||
}
|
||||
|
||||
/*
|
||||
ListRepoScaleSetsOK describes a response with status code 200, with default header values.
|
||||
|
||||
ScaleSets
|
||||
*/
|
||||
type ListRepoScaleSetsOK struct {
|
||||
Payload garm_params.ScaleSets
|
||||
}
|
||||
|
||||
// IsSuccess returns true when this list repo scale sets o k response has a 2xx status code
|
||||
func (o *ListRepoScaleSetsOK) IsSuccess() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// IsRedirect returns true when this list repo scale sets o k response has a 3xx status code
|
||||
func (o *ListRepoScaleSetsOK) IsRedirect() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsClientError returns true when this list repo scale sets o k response has a 4xx status code
|
||||
func (o *ListRepoScaleSetsOK) IsClientError() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsServerError returns true when this list repo scale sets o k response has a 5xx status code
|
||||
func (o *ListRepoScaleSetsOK) IsServerError() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsCode returns true when this list repo scale sets o k response a status code equal to that given
|
||||
func (o *ListRepoScaleSetsOK) IsCode(code int) bool {
|
||||
return code == 200
|
||||
}
|
||||
|
||||
// Code gets the status code for the list repo scale sets o k response
|
||||
func (o *ListRepoScaleSetsOK) Code() int {
|
||||
return 200
|
||||
}
|
||||
|
||||
func (o *ListRepoScaleSetsOK) Error() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /repositories/{repoID}/scalesets][%d] listRepoScaleSetsOK %s", 200, payload)
|
||||
}
|
||||
|
||||
func (o *ListRepoScaleSetsOK) String() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /repositories/{repoID}/scalesets][%d] listRepoScaleSetsOK %s", 200, payload)
|
||||
}
|
||||
|
||||
func (o *ListRepoScaleSetsOK) GetPayload() garm_params.ScaleSets {
|
||||
return o.Payload
|
||||
}
|
||||
|
||||
func (o *ListRepoScaleSetsOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewListRepoScaleSetsDefault creates a ListRepoScaleSetsDefault with default headers values
|
||||
func NewListRepoScaleSetsDefault(code int) *ListRepoScaleSetsDefault {
|
||||
return &ListRepoScaleSetsDefault{
|
||||
_statusCode: code,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
ListRepoScaleSetsDefault describes a response with status code -1, with default header values.
|
||||
|
||||
APIErrorResponse
|
||||
*/
|
||||
type ListRepoScaleSetsDefault struct {
|
||||
_statusCode int
|
||||
|
||||
Payload apiserver_params.APIErrorResponse
|
||||
}
|
||||
|
||||
// IsSuccess returns true when this list repo scale sets default response has a 2xx status code
|
||||
func (o *ListRepoScaleSetsDefault) IsSuccess() bool {
|
||||
return o._statusCode/100 == 2
|
||||
}
|
||||
|
||||
// IsRedirect returns true when this list repo scale sets default response has a 3xx status code
|
||||
func (o *ListRepoScaleSetsDefault) IsRedirect() bool {
|
||||
return o._statusCode/100 == 3
|
||||
}
|
||||
|
||||
// IsClientError returns true when this list repo scale sets default response has a 4xx status code
|
||||
func (o *ListRepoScaleSetsDefault) IsClientError() bool {
|
||||
return o._statusCode/100 == 4
|
||||
}
|
||||
|
||||
// IsServerError returns true when this list repo scale sets default response has a 5xx status code
|
||||
func (o *ListRepoScaleSetsDefault) IsServerError() bool {
|
||||
return o._statusCode/100 == 5
|
||||
}
|
||||
|
||||
// IsCode returns true when this list repo scale sets default response a status code equal to that given
|
||||
func (o *ListRepoScaleSetsDefault) IsCode(code int) bool {
|
||||
return o._statusCode == code
|
||||
}
|
||||
|
||||
// Code gets the status code for the list repo scale sets default response
|
||||
func (o *ListRepoScaleSetsDefault) Code() int {
|
||||
return o._statusCode
|
||||
}
|
||||
|
||||
func (o *ListRepoScaleSetsDefault) Error() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /repositories/{repoID}/scalesets][%d] ListRepoScaleSets default %s", o._statusCode, payload)
|
||||
}
|
||||
|
||||
func (o *ListRepoScaleSetsDefault) String() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /repositories/{repoID}/scalesets][%d] ListRepoScaleSets default %s", o._statusCode, payload)
|
||||
}
|
||||
|
||||
func (o *ListRepoScaleSetsDefault) GetPayload() apiserver_params.APIErrorResponse {
|
||||
return o.Payload
|
||||
}
|
||||
|
||||
func (o *ListRepoScaleSetsDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -58,6 +58,8 @@ type ClientService interface {
|
|||
|
||||
CreateRepoPool(params *CreateRepoPoolParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*CreateRepoPoolOK, error)
|
||||
|
||||
CreateRepoScaleSet(params *CreateRepoScaleSetParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*CreateRepoScaleSetOK, error)
|
||||
|
||||
DeleteRepo(params *DeleteRepoParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) error
|
||||
|
||||
DeleteRepoPool(params *DeleteRepoPoolParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) error
|
||||
|
|
@ -74,6 +76,8 @@ type ClientService interface {
|
|||
|
||||
ListRepoPools(params *ListRepoPoolsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ListRepoPoolsOK, error)
|
||||
|
||||
ListRepoScaleSets(params *ListRepoScaleSetsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ListRepoScaleSetsOK, error)
|
||||
|
||||
ListRepos(params *ListReposParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ListReposOK, error)
|
||||
|
||||
UninstallRepoWebhook(params *UninstallRepoWebhookParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) error
|
||||
|
|
@ -161,6 +165,44 @@ func (a *Client) CreateRepoPool(params *CreateRepoPoolParams, authInfo runtime.C
|
|||
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
|
||||
}
|
||||
|
||||
/*
|
||||
CreateRepoScaleSet creates repository scale set with the parameters given
|
||||
*/
|
||||
func (a *Client) CreateRepoScaleSet(params *CreateRepoScaleSetParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*CreateRepoScaleSetOK, error) {
|
||||
// TODO: Validate the params before sending
|
||||
if params == nil {
|
||||
params = NewCreateRepoScaleSetParams()
|
||||
}
|
||||
op := &runtime.ClientOperation{
|
||||
ID: "CreateRepoScaleSet",
|
||||
Method: "POST",
|
||||
PathPattern: "/repositories/{repoID}/scalesets",
|
||||
ProducesMediaTypes: []string{"application/json"},
|
||||
ConsumesMediaTypes: []string{"application/json"},
|
||||
Schemes: []string{"http"},
|
||||
Params: params,
|
||||
Reader: &CreateRepoScaleSetReader{formats: a.formats},
|
||||
AuthInfo: authInfo,
|
||||
Context: params.Context,
|
||||
Client: params.HTTPClient,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(op)
|
||||
}
|
||||
|
||||
result, err := a.transport.Submit(op)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
success, ok := result.(*CreateRepoScaleSetOK)
|
||||
if ok {
|
||||
return success, nil
|
||||
}
|
||||
// unexpected success response
|
||||
unexpectedSuccess := result.(*CreateRepoScaleSetDefault)
|
||||
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
|
||||
}
|
||||
|
||||
/*
|
||||
DeleteRepo deletes repository by ID
|
||||
*/
|
||||
|
|
@ -455,6 +497,44 @@ func (a *Client) ListRepoPools(params *ListRepoPoolsParams, authInfo runtime.Cli
|
|||
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
|
||||
}
|
||||
|
||||
/*
|
||||
ListRepoScaleSets lists repository scale sets
|
||||
*/
|
||||
func (a *Client) ListRepoScaleSets(params *ListRepoScaleSetsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ListRepoScaleSetsOK, error) {
|
||||
// TODO: Validate the params before sending
|
||||
if params == nil {
|
||||
params = NewListRepoScaleSetsParams()
|
||||
}
|
||||
op := &runtime.ClientOperation{
|
||||
ID: "ListRepoScaleSets",
|
||||
Method: "GET",
|
||||
PathPattern: "/repositories/{repoID}/scalesets",
|
||||
ProducesMediaTypes: []string{"application/json"},
|
||||
ConsumesMediaTypes: []string{"application/json"},
|
||||
Schemes: []string{"http"},
|
||||
Params: params,
|
||||
Reader: &ListRepoScaleSetsReader{formats: a.formats},
|
||||
AuthInfo: authInfo,
|
||||
Context: params.Context,
|
||||
Client: params.HTTPClient,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(op)
|
||||
}
|
||||
|
||||
result, err := a.transport.Submit(op)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
success, ok := result.(*ListRepoScaleSetsOK)
|
||||
if ok {
|
||||
return success, nil
|
||||
}
|
||||
// unexpected success response
|
||||
unexpectedSuccess := result.(*ListRepoScaleSetsDefault)
|
||||
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
|
||||
}
|
||||
|
||||
/*
|
||||
ListRepos lists repositories
|
||||
*/
|
||||
|
|
|
|||
151
client/scalesets/delete_scale_set_parameters.go
Normal file
151
client/scalesets/delete_scale_set_parameters.go
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package scalesets
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
cr "github.com/go-openapi/runtime/client"
|
||||
"github.com/go-openapi/strfmt"
|
||||
)
|
||||
|
||||
// NewDeleteScaleSetParams creates a new DeleteScaleSetParams object,
|
||||
// with the default timeout for this client.
|
||||
//
|
||||
// Default values are not hydrated, since defaults are normally applied by the API server side.
|
||||
//
|
||||
// To enforce default values in parameter, use SetDefaults or WithDefaults.
|
||||
func NewDeleteScaleSetParams() *DeleteScaleSetParams {
|
||||
return &DeleteScaleSetParams{
|
||||
timeout: cr.DefaultTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
// NewDeleteScaleSetParamsWithTimeout creates a new DeleteScaleSetParams object
|
||||
// with the ability to set a timeout on a request.
|
||||
func NewDeleteScaleSetParamsWithTimeout(timeout time.Duration) *DeleteScaleSetParams {
|
||||
return &DeleteScaleSetParams{
|
||||
timeout: timeout,
|
||||
}
|
||||
}
|
||||
|
||||
// NewDeleteScaleSetParamsWithContext creates a new DeleteScaleSetParams object
|
||||
// with the ability to set a context for a request.
|
||||
func NewDeleteScaleSetParamsWithContext(ctx context.Context) *DeleteScaleSetParams {
|
||||
return &DeleteScaleSetParams{
|
||||
Context: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
// NewDeleteScaleSetParamsWithHTTPClient creates a new DeleteScaleSetParams object
|
||||
// with the ability to set a custom HTTPClient for a request.
|
||||
func NewDeleteScaleSetParamsWithHTTPClient(client *http.Client) *DeleteScaleSetParams {
|
||||
return &DeleteScaleSetParams{
|
||||
HTTPClient: client,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
DeleteScaleSetParams contains all the parameters to send to the API endpoint
|
||||
|
||||
for the delete scale set operation.
|
||||
|
||||
Typically these are written to a http.Request.
|
||||
*/
|
||||
type DeleteScaleSetParams struct {
|
||||
|
||||
/* ScalesetID.
|
||||
|
||||
ID of the scale set to delete.
|
||||
*/
|
||||
ScalesetID string
|
||||
|
||||
timeout time.Duration
|
||||
Context context.Context
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// WithDefaults hydrates default values in the delete scale set params (not the query body).
|
||||
//
|
||||
// All values with no default are reset to their zero value.
|
||||
func (o *DeleteScaleSetParams) WithDefaults() *DeleteScaleSetParams {
|
||||
o.SetDefaults()
|
||||
return o
|
||||
}
|
||||
|
||||
// SetDefaults hydrates default values in the delete scale set params (not the query body).
|
||||
//
|
||||
// All values with no default are reset to their zero value.
|
||||
func (o *DeleteScaleSetParams) SetDefaults() {
|
||||
// no default values defined for this parameter
|
||||
}
|
||||
|
||||
// WithTimeout adds the timeout to the delete scale set params
|
||||
func (o *DeleteScaleSetParams) WithTimeout(timeout time.Duration) *DeleteScaleSetParams {
|
||||
o.SetTimeout(timeout)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetTimeout adds the timeout to the delete scale set params
|
||||
func (o *DeleteScaleSetParams) SetTimeout(timeout time.Duration) {
|
||||
o.timeout = timeout
|
||||
}
|
||||
|
||||
// WithContext adds the context to the delete scale set params
|
||||
func (o *DeleteScaleSetParams) WithContext(ctx context.Context) *DeleteScaleSetParams {
|
||||
o.SetContext(ctx)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetContext adds the context to the delete scale set params
|
||||
func (o *DeleteScaleSetParams) SetContext(ctx context.Context) {
|
||||
o.Context = ctx
|
||||
}
|
||||
|
||||
// WithHTTPClient adds the HTTPClient to the delete scale set params
|
||||
func (o *DeleteScaleSetParams) WithHTTPClient(client *http.Client) *DeleteScaleSetParams {
|
||||
o.SetHTTPClient(client)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetHTTPClient adds the HTTPClient to the delete scale set params
|
||||
func (o *DeleteScaleSetParams) SetHTTPClient(client *http.Client) {
|
||||
o.HTTPClient = client
|
||||
}
|
||||
|
||||
// WithScalesetID adds the scalesetID to the delete scale set params
|
||||
func (o *DeleteScaleSetParams) WithScalesetID(scalesetID string) *DeleteScaleSetParams {
|
||||
o.SetScalesetID(scalesetID)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetScalesetID adds the scalesetId to the delete scale set params
|
||||
func (o *DeleteScaleSetParams) SetScalesetID(scalesetID string) {
|
||||
o.ScalesetID = scalesetID
|
||||
}
|
||||
|
||||
// WriteToRequest writes these params to a swagger request
|
||||
func (o *DeleteScaleSetParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
|
||||
|
||||
if err := r.SetTimeout(o.timeout); err != nil {
|
||||
return err
|
||||
}
|
||||
var res []error
|
||||
|
||||
// path param scalesetID
|
||||
if err := r.SetPathParam("scalesetID", o.ScalesetID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
106
client/scalesets/delete_scale_set_responses.go
Normal file
106
client/scalesets/delete_scale_set_responses.go
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package scalesets
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
apiserver_params "github.com/cloudbase/garm/apiserver/params"
|
||||
)
|
||||
|
||||
// DeleteScaleSetReader is a Reader for the DeleteScaleSet structure.
|
||||
type DeleteScaleSetReader struct {
|
||||
formats strfmt.Registry
|
||||
}
|
||||
|
||||
// ReadResponse reads a server response into the received o.
|
||||
func (o *DeleteScaleSetReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
result := NewDeleteScaleSetDefault(response.Code())
|
||||
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if response.Code()/100 == 2 {
|
||||
return result, nil
|
||||
}
|
||||
return nil, result
|
||||
}
|
||||
|
||||
// NewDeleteScaleSetDefault creates a DeleteScaleSetDefault with default headers values
|
||||
func NewDeleteScaleSetDefault(code int) *DeleteScaleSetDefault {
|
||||
return &DeleteScaleSetDefault{
|
||||
_statusCode: code,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
DeleteScaleSetDefault describes a response with status code -1, with default header values.
|
||||
|
||||
APIErrorResponse
|
||||
*/
|
||||
type DeleteScaleSetDefault struct {
|
||||
_statusCode int
|
||||
|
||||
Payload apiserver_params.APIErrorResponse
|
||||
}
|
||||
|
||||
// IsSuccess returns true when this delete scale set default response has a 2xx status code
|
||||
func (o *DeleteScaleSetDefault) IsSuccess() bool {
|
||||
return o._statusCode/100 == 2
|
||||
}
|
||||
|
||||
// IsRedirect returns true when this delete scale set default response has a 3xx status code
|
||||
func (o *DeleteScaleSetDefault) IsRedirect() bool {
|
||||
return o._statusCode/100 == 3
|
||||
}
|
||||
|
||||
// IsClientError returns true when this delete scale set default response has a 4xx status code
|
||||
func (o *DeleteScaleSetDefault) IsClientError() bool {
|
||||
return o._statusCode/100 == 4
|
||||
}
|
||||
|
||||
// IsServerError returns true when this delete scale set default response has a 5xx status code
|
||||
func (o *DeleteScaleSetDefault) IsServerError() bool {
|
||||
return o._statusCode/100 == 5
|
||||
}
|
||||
|
||||
// IsCode returns true when this delete scale set default response a status code equal to that given
|
||||
func (o *DeleteScaleSetDefault) IsCode(code int) bool {
|
||||
return o._statusCode == code
|
||||
}
|
||||
|
||||
// Code gets the status code for the delete scale set default response
|
||||
func (o *DeleteScaleSetDefault) Code() int {
|
||||
return o._statusCode
|
||||
}
|
||||
|
||||
func (o *DeleteScaleSetDefault) Error() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[DELETE /scalesets/{scalesetID}][%d] DeleteScaleSet default %s", o._statusCode, payload)
|
||||
}
|
||||
|
||||
func (o *DeleteScaleSetDefault) String() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[DELETE /scalesets/{scalesetID}][%d] DeleteScaleSet default %s", o._statusCode, payload)
|
||||
}
|
||||
|
||||
func (o *DeleteScaleSetDefault) GetPayload() apiserver_params.APIErrorResponse {
|
||||
return o.Payload
|
||||
}
|
||||
|
||||
func (o *DeleteScaleSetDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
151
client/scalesets/get_scale_set_parameters.go
Normal file
151
client/scalesets/get_scale_set_parameters.go
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package scalesets
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
cr "github.com/go-openapi/runtime/client"
|
||||
"github.com/go-openapi/strfmt"
|
||||
)
|
||||
|
||||
// NewGetScaleSetParams creates a new GetScaleSetParams object,
|
||||
// with the default timeout for this client.
|
||||
//
|
||||
// Default values are not hydrated, since defaults are normally applied by the API server side.
|
||||
//
|
||||
// To enforce default values in parameter, use SetDefaults or WithDefaults.
|
||||
func NewGetScaleSetParams() *GetScaleSetParams {
|
||||
return &GetScaleSetParams{
|
||||
timeout: cr.DefaultTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
// NewGetScaleSetParamsWithTimeout creates a new GetScaleSetParams object
|
||||
// with the ability to set a timeout on a request.
|
||||
func NewGetScaleSetParamsWithTimeout(timeout time.Duration) *GetScaleSetParams {
|
||||
return &GetScaleSetParams{
|
||||
timeout: timeout,
|
||||
}
|
||||
}
|
||||
|
||||
// NewGetScaleSetParamsWithContext creates a new GetScaleSetParams object
|
||||
// with the ability to set a context for a request.
|
||||
func NewGetScaleSetParamsWithContext(ctx context.Context) *GetScaleSetParams {
|
||||
return &GetScaleSetParams{
|
||||
Context: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
// NewGetScaleSetParamsWithHTTPClient creates a new GetScaleSetParams object
|
||||
// with the ability to set a custom HTTPClient for a request.
|
||||
func NewGetScaleSetParamsWithHTTPClient(client *http.Client) *GetScaleSetParams {
|
||||
return &GetScaleSetParams{
|
||||
HTTPClient: client,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
GetScaleSetParams contains all the parameters to send to the API endpoint
|
||||
|
||||
for the get scale set operation.
|
||||
|
||||
Typically these are written to a http.Request.
|
||||
*/
|
||||
type GetScaleSetParams struct {
|
||||
|
||||
/* ScalesetID.
|
||||
|
||||
ID of the scale set to fetch.
|
||||
*/
|
||||
ScalesetID string
|
||||
|
||||
timeout time.Duration
|
||||
Context context.Context
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// WithDefaults hydrates default values in the get scale set params (not the query body).
|
||||
//
|
||||
// All values with no default are reset to their zero value.
|
||||
func (o *GetScaleSetParams) WithDefaults() *GetScaleSetParams {
|
||||
o.SetDefaults()
|
||||
return o
|
||||
}
|
||||
|
||||
// SetDefaults hydrates default values in the get scale set params (not the query body).
|
||||
//
|
||||
// All values with no default are reset to their zero value.
|
||||
func (o *GetScaleSetParams) SetDefaults() {
|
||||
// no default values defined for this parameter
|
||||
}
|
||||
|
||||
// WithTimeout adds the timeout to the get scale set params
|
||||
func (o *GetScaleSetParams) WithTimeout(timeout time.Duration) *GetScaleSetParams {
|
||||
o.SetTimeout(timeout)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetTimeout adds the timeout to the get scale set params
|
||||
func (o *GetScaleSetParams) SetTimeout(timeout time.Duration) {
|
||||
o.timeout = timeout
|
||||
}
|
||||
|
||||
// WithContext adds the context to the get scale set params
|
||||
func (o *GetScaleSetParams) WithContext(ctx context.Context) *GetScaleSetParams {
|
||||
o.SetContext(ctx)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetContext adds the context to the get scale set params
|
||||
func (o *GetScaleSetParams) SetContext(ctx context.Context) {
|
||||
o.Context = ctx
|
||||
}
|
||||
|
||||
// WithHTTPClient adds the HTTPClient to the get scale set params
|
||||
func (o *GetScaleSetParams) WithHTTPClient(client *http.Client) *GetScaleSetParams {
|
||||
o.SetHTTPClient(client)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetHTTPClient adds the HTTPClient to the get scale set params
|
||||
func (o *GetScaleSetParams) SetHTTPClient(client *http.Client) {
|
||||
o.HTTPClient = client
|
||||
}
|
||||
|
||||
// WithScalesetID adds the scalesetID to the get scale set params
|
||||
func (o *GetScaleSetParams) WithScalesetID(scalesetID string) *GetScaleSetParams {
|
||||
o.SetScalesetID(scalesetID)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetScalesetID adds the scalesetId to the get scale set params
|
||||
func (o *GetScaleSetParams) SetScalesetID(scalesetID string) {
|
||||
o.ScalesetID = scalesetID
|
||||
}
|
||||
|
||||
// WriteToRequest writes these params to a swagger request
|
||||
func (o *GetScaleSetParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
|
||||
|
||||
if err := r.SetTimeout(o.timeout); err != nil {
|
||||
return err
|
||||
}
|
||||
var res []error
|
||||
|
||||
// path param scalesetID
|
||||
if err := r.SetPathParam("scalesetID", o.ScalesetID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
184
client/scalesets/get_scale_set_responses.go
Normal file
184
client/scalesets/get_scale_set_responses.go
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package scalesets
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
apiserver_params "github.com/cloudbase/garm/apiserver/params"
|
||||
garm_params "github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
// GetScaleSetReader is a Reader for the GetScaleSet structure.
|
||||
type GetScaleSetReader struct {
|
||||
formats strfmt.Registry
|
||||
}
|
||||
|
||||
// ReadResponse reads a server response into the received o.
|
||||
func (o *GetScaleSetReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
switch response.Code() {
|
||||
case 200:
|
||||
result := NewGetScaleSetOK()
|
||||
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
default:
|
||||
result := NewGetScaleSetDefault(response.Code())
|
||||
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if response.Code()/100 == 2 {
|
||||
return result, nil
|
||||
}
|
||||
return nil, result
|
||||
}
|
||||
}
|
||||
|
||||
// NewGetScaleSetOK creates a GetScaleSetOK with default headers values
|
||||
func NewGetScaleSetOK() *GetScaleSetOK {
|
||||
return &GetScaleSetOK{}
|
||||
}
|
||||
|
||||
/*
|
||||
GetScaleSetOK describes a response with status code 200, with default header values.
|
||||
|
||||
ScaleSet
|
||||
*/
|
||||
type GetScaleSetOK struct {
|
||||
Payload garm_params.ScaleSet
|
||||
}
|
||||
|
||||
// IsSuccess returns true when this get scale set o k response has a 2xx status code
|
||||
func (o *GetScaleSetOK) IsSuccess() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// IsRedirect returns true when this get scale set o k response has a 3xx status code
|
||||
func (o *GetScaleSetOK) IsRedirect() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsClientError returns true when this get scale set o k response has a 4xx status code
|
||||
func (o *GetScaleSetOK) IsClientError() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsServerError returns true when this get scale set o k response has a 5xx status code
|
||||
func (o *GetScaleSetOK) IsServerError() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsCode returns true when this get scale set o k response a status code equal to that given
|
||||
func (o *GetScaleSetOK) IsCode(code int) bool {
|
||||
return code == 200
|
||||
}
|
||||
|
||||
// Code gets the status code for the get scale set o k response
|
||||
func (o *GetScaleSetOK) Code() int {
|
||||
return 200
|
||||
}
|
||||
|
||||
func (o *GetScaleSetOK) Error() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /scalesets/{scalesetID}][%d] getScaleSetOK %s", 200, payload)
|
||||
}
|
||||
|
||||
func (o *GetScaleSetOK) String() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /scalesets/{scalesetID}][%d] getScaleSetOK %s", 200, payload)
|
||||
}
|
||||
|
||||
func (o *GetScaleSetOK) GetPayload() garm_params.ScaleSet {
|
||||
return o.Payload
|
||||
}
|
||||
|
||||
func (o *GetScaleSetOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewGetScaleSetDefault creates a GetScaleSetDefault with default headers values
|
||||
func NewGetScaleSetDefault(code int) *GetScaleSetDefault {
|
||||
return &GetScaleSetDefault{
|
||||
_statusCode: code,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
GetScaleSetDefault describes a response with status code -1, with default header values.
|
||||
|
||||
APIErrorResponse
|
||||
*/
|
||||
type GetScaleSetDefault struct {
|
||||
_statusCode int
|
||||
|
||||
Payload apiserver_params.APIErrorResponse
|
||||
}
|
||||
|
||||
// IsSuccess returns true when this get scale set default response has a 2xx status code
|
||||
func (o *GetScaleSetDefault) IsSuccess() bool {
|
||||
return o._statusCode/100 == 2
|
||||
}
|
||||
|
||||
// IsRedirect returns true when this get scale set default response has a 3xx status code
|
||||
func (o *GetScaleSetDefault) IsRedirect() bool {
|
||||
return o._statusCode/100 == 3
|
||||
}
|
||||
|
||||
// IsClientError returns true when this get scale set default response has a 4xx status code
|
||||
func (o *GetScaleSetDefault) IsClientError() bool {
|
||||
return o._statusCode/100 == 4
|
||||
}
|
||||
|
||||
// IsServerError returns true when this get scale set default response has a 5xx status code
|
||||
func (o *GetScaleSetDefault) IsServerError() bool {
|
||||
return o._statusCode/100 == 5
|
||||
}
|
||||
|
||||
// IsCode returns true when this get scale set default response a status code equal to that given
|
||||
func (o *GetScaleSetDefault) IsCode(code int) bool {
|
||||
return o._statusCode == code
|
||||
}
|
||||
|
||||
// Code gets the status code for the get scale set default response
|
||||
func (o *GetScaleSetDefault) Code() int {
|
||||
return o._statusCode
|
||||
}
|
||||
|
||||
func (o *GetScaleSetDefault) Error() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /scalesets/{scalesetID}][%d] GetScaleSet default %s", o._statusCode, payload)
|
||||
}
|
||||
|
||||
func (o *GetScaleSetDefault) String() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /scalesets/{scalesetID}][%d] GetScaleSet default %s", o._statusCode, payload)
|
||||
}
|
||||
|
||||
func (o *GetScaleSetDefault) GetPayload() apiserver_params.APIErrorResponse {
|
||||
return o.Payload
|
||||
}
|
||||
|
||||
func (o *GetScaleSetDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
128
client/scalesets/list_scalesets_parameters.go
Normal file
128
client/scalesets/list_scalesets_parameters.go
Normal file
|
|
@ -0,0 +1,128 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package scalesets
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
cr "github.com/go-openapi/runtime/client"
|
||||
"github.com/go-openapi/strfmt"
|
||||
)
|
||||
|
||||
// NewListScalesetsParams creates a new ListScalesetsParams object,
|
||||
// with the default timeout for this client.
|
||||
//
|
||||
// Default values are not hydrated, since defaults are normally applied by the API server side.
|
||||
//
|
||||
// To enforce default values in parameter, use SetDefaults or WithDefaults.
|
||||
func NewListScalesetsParams() *ListScalesetsParams {
|
||||
return &ListScalesetsParams{
|
||||
timeout: cr.DefaultTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
// NewListScalesetsParamsWithTimeout creates a new ListScalesetsParams object
|
||||
// with the ability to set a timeout on a request.
|
||||
func NewListScalesetsParamsWithTimeout(timeout time.Duration) *ListScalesetsParams {
|
||||
return &ListScalesetsParams{
|
||||
timeout: timeout,
|
||||
}
|
||||
}
|
||||
|
||||
// NewListScalesetsParamsWithContext creates a new ListScalesetsParams object
|
||||
// with the ability to set a context for a request.
|
||||
func NewListScalesetsParamsWithContext(ctx context.Context) *ListScalesetsParams {
|
||||
return &ListScalesetsParams{
|
||||
Context: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
// NewListScalesetsParamsWithHTTPClient creates a new ListScalesetsParams object
|
||||
// with the ability to set a custom HTTPClient for a request.
|
||||
func NewListScalesetsParamsWithHTTPClient(client *http.Client) *ListScalesetsParams {
|
||||
return &ListScalesetsParams{
|
||||
HTTPClient: client,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
ListScalesetsParams contains all the parameters to send to the API endpoint
|
||||
|
||||
for the list scalesets operation.
|
||||
|
||||
Typically these are written to a http.Request.
|
||||
*/
|
||||
type ListScalesetsParams struct {
|
||||
timeout time.Duration
|
||||
Context context.Context
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// WithDefaults hydrates default values in the list scalesets params (not the query body).
|
||||
//
|
||||
// All values with no default are reset to their zero value.
|
||||
func (o *ListScalesetsParams) WithDefaults() *ListScalesetsParams {
|
||||
o.SetDefaults()
|
||||
return o
|
||||
}
|
||||
|
||||
// SetDefaults hydrates default values in the list scalesets params (not the query body).
|
||||
//
|
||||
// All values with no default are reset to their zero value.
|
||||
func (o *ListScalesetsParams) SetDefaults() {
|
||||
// no default values defined for this parameter
|
||||
}
|
||||
|
||||
// WithTimeout adds the timeout to the list scalesets params
|
||||
func (o *ListScalesetsParams) WithTimeout(timeout time.Duration) *ListScalesetsParams {
|
||||
o.SetTimeout(timeout)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetTimeout adds the timeout to the list scalesets params
|
||||
func (o *ListScalesetsParams) SetTimeout(timeout time.Duration) {
|
||||
o.timeout = timeout
|
||||
}
|
||||
|
||||
// WithContext adds the context to the list scalesets params
|
||||
func (o *ListScalesetsParams) WithContext(ctx context.Context) *ListScalesetsParams {
|
||||
o.SetContext(ctx)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetContext adds the context to the list scalesets params
|
||||
func (o *ListScalesetsParams) SetContext(ctx context.Context) {
|
||||
o.Context = ctx
|
||||
}
|
||||
|
||||
// WithHTTPClient adds the HTTPClient to the list scalesets params
|
||||
func (o *ListScalesetsParams) WithHTTPClient(client *http.Client) *ListScalesetsParams {
|
||||
o.SetHTTPClient(client)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetHTTPClient adds the HTTPClient to the list scalesets params
|
||||
func (o *ListScalesetsParams) SetHTTPClient(client *http.Client) {
|
||||
o.HTTPClient = client
|
||||
}
|
||||
|
||||
// WriteToRequest writes these params to a swagger request
|
||||
func (o *ListScalesetsParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
|
||||
|
||||
if err := r.SetTimeout(o.timeout); err != nil {
|
||||
return err
|
||||
}
|
||||
var res []error
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
184
client/scalesets/list_scalesets_responses.go
Normal file
184
client/scalesets/list_scalesets_responses.go
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package scalesets
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
apiserver_params "github.com/cloudbase/garm/apiserver/params"
|
||||
garm_params "github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
// ListScalesetsReader is a Reader for the ListScalesets structure.
|
||||
type ListScalesetsReader struct {
|
||||
formats strfmt.Registry
|
||||
}
|
||||
|
||||
// ReadResponse reads a server response into the received o.
|
||||
func (o *ListScalesetsReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
switch response.Code() {
|
||||
case 200:
|
||||
result := NewListScalesetsOK()
|
||||
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
default:
|
||||
result := NewListScalesetsDefault(response.Code())
|
||||
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if response.Code()/100 == 2 {
|
||||
return result, nil
|
||||
}
|
||||
return nil, result
|
||||
}
|
||||
}
|
||||
|
||||
// NewListScalesetsOK creates a ListScalesetsOK with default headers values
|
||||
func NewListScalesetsOK() *ListScalesetsOK {
|
||||
return &ListScalesetsOK{}
|
||||
}
|
||||
|
||||
/*
|
||||
ListScalesetsOK describes a response with status code 200, with default header values.
|
||||
|
||||
ScaleSets
|
||||
*/
|
||||
type ListScalesetsOK struct {
|
||||
Payload garm_params.ScaleSets
|
||||
}
|
||||
|
||||
// IsSuccess returns true when this list scalesets o k response has a 2xx status code
|
||||
func (o *ListScalesetsOK) IsSuccess() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// IsRedirect returns true when this list scalesets o k response has a 3xx status code
|
||||
func (o *ListScalesetsOK) IsRedirect() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsClientError returns true when this list scalesets o k response has a 4xx status code
|
||||
func (o *ListScalesetsOK) IsClientError() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsServerError returns true when this list scalesets o k response has a 5xx status code
|
||||
func (o *ListScalesetsOK) IsServerError() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsCode returns true when this list scalesets o k response a status code equal to that given
|
||||
func (o *ListScalesetsOK) IsCode(code int) bool {
|
||||
return code == 200
|
||||
}
|
||||
|
||||
// Code gets the status code for the list scalesets o k response
|
||||
func (o *ListScalesetsOK) Code() int {
|
||||
return 200
|
||||
}
|
||||
|
||||
func (o *ListScalesetsOK) Error() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /scalesets][%d] listScalesetsOK %s", 200, payload)
|
||||
}
|
||||
|
||||
func (o *ListScalesetsOK) String() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /scalesets][%d] listScalesetsOK %s", 200, payload)
|
||||
}
|
||||
|
||||
func (o *ListScalesetsOK) GetPayload() garm_params.ScaleSets {
|
||||
return o.Payload
|
||||
}
|
||||
|
||||
func (o *ListScalesetsOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewListScalesetsDefault creates a ListScalesetsDefault with default headers values
|
||||
func NewListScalesetsDefault(code int) *ListScalesetsDefault {
|
||||
return &ListScalesetsDefault{
|
||||
_statusCode: code,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
ListScalesetsDefault describes a response with status code -1, with default header values.
|
||||
|
||||
APIErrorResponse
|
||||
*/
|
||||
type ListScalesetsDefault struct {
|
||||
_statusCode int
|
||||
|
||||
Payload apiserver_params.APIErrorResponse
|
||||
}
|
||||
|
||||
// IsSuccess returns true when this list scalesets default response has a 2xx status code
|
||||
func (o *ListScalesetsDefault) IsSuccess() bool {
|
||||
return o._statusCode/100 == 2
|
||||
}
|
||||
|
||||
// IsRedirect returns true when this list scalesets default response has a 3xx status code
|
||||
func (o *ListScalesetsDefault) IsRedirect() bool {
|
||||
return o._statusCode/100 == 3
|
||||
}
|
||||
|
||||
// IsClientError returns true when this list scalesets default response has a 4xx status code
|
||||
func (o *ListScalesetsDefault) IsClientError() bool {
|
||||
return o._statusCode/100 == 4
|
||||
}
|
||||
|
||||
// IsServerError returns true when this list scalesets default response has a 5xx status code
|
||||
func (o *ListScalesetsDefault) IsServerError() bool {
|
||||
return o._statusCode/100 == 5
|
||||
}
|
||||
|
||||
// IsCode returns true when this list scalesets default response a status code equal to that given
|
||||
func (o *ListScalesetsDefault) IsCode(code int) bool {
|
||||
return o._statusCode == code
|
||||
}
|
||||
|
||||
// Code gets the status code for the list scalesets default response
|
||||
func (o *ListScalesetsDefault) Code() int {
|
||||
return o._statusCode
|
||||
}
|
||||
|
||||
func (o *ListScalesetsDefault) Error() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /scalesets][%d] ListScalesets default %s", o._statusCode, payload)
|
||||
}
|
||||
|
||||
func (o *ListScalesetsDefault) String() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[GET /scalesets][%d] ListScalesets default %s", o._statusCode, payload)
|
||||
}
|
||||
|
||||
func (o *ListScalesetsDefault) GetPayload() apiserver_params.APIErrorResponse {
|
||||
return o.Payload
|
||||
}
|
||||
|
||||
func (o *ListScalesetsDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
217
client/scalesets/scalesets_client.go
Normal file
217
client/scalesets/scalesets_client.go
Normal file
|
|
@ -0,0 +1,217 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package scalesets
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"github.com/go-openapi/runtime"
|
||||
httptransport "github.com/go-openapi/runtime/client"
|
||||
"github.com/go-openapi/strfmt"
|
||||
)
|
||||
|
||||
// New creates a new scalesets API client.
|
||||
func New(transport runtime.ClientTransport, formats strfmt.Registry) ClientService {
|
||||
return &Client{transport: transport, formats: formats}
|
||||
}
|
||||
|
||||
// New creates a new scalesets API client with basic auth credentials.
|
||||
// It takes the following parameters:
|
||||
// - host: http host (github.com).
|
||||
// - basePath: any base path for the API client ("/v1", "/v3").
|
||||
// - scheme: http scheme ("http", "https").
|
||||
// - user: user for basic authentication header.
|
||||
// - password: password for basic authentication header.
|
||||
func NewClientWithBasicAuth(host, basePath, scheme, user, password string) ClientService {
|
||||
transport := httptransport.New(host, basePath, []string{scheme})
|
||||
transport.DefaultAuthentication = httptransport.BasicAuth(user, password)
|
||||
return &Client{transport: transport, formats: strfmt.Default}
|
||||
}
|
||||
|
||||
// New creates a new scalesets API client with a bearer token for authentication.
|
||||
// It takes the following parameters:
|
||||
// - host: http host (github.com).
|
||||
// - basePath: any base path for the API client ("/v1", "/v3").
|
||||
// - scheme: http scheme ("http", "https").
|
||||
// - bearerToken: bearer token for Bearer authentication header.
|
||||
func NewClientWithBearerToken(host, basePath, scheme, bearerToken string) ClientService {
|
||||
transport := httptransport.New(host, basePath, []string{scheme})
|
||||
transport.DefaultAuthentication = httptransport.BearerToken(bearerToken)
|
||||
return &Client{transport: transport, formats: strfmt.Default}
|
||||
}
|
||||
|
||||
/*
|
||||
Client for scalesets API
|
||||
*/
|
||||
type Client struct {
|
||||
transport runtime.ClientTransport
|
||||
formats strfmt.Registry
|
||||
}
|
||||
|
||||
// ClientOption may be used to customize the behavior of Client methods.
|
||||
type ClientOption func(*runtime.ClientOperation)
|
||||
|
||||
// ClientService is the interface for Client methods
|
||||
type ClientService interface {
|
||||
DeleteScaleSet(params *DeleteScaleSetParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) error
|
||||
|
||||
GetScaleSet(params *GetScaleSetParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*GetScaleSetOK, error)
|
||||
|
||||
ListScalesets(params *ListScalesetsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ListScalesetsOK, error)
|
||||
|
||||
UpdateScaleSet(params *UpdateScaleSetParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*UpdateScaleSetOK, error)
|
||||
|
||||
SetTransport(transport runtime.ClientTransport)
|
||||
}
|
||||
|
||||
/*
|
||||
DeleteScaleSet deletes scale set by ID
|
||||
*/
|
||||
func (a *Client) DeleteScaleSet(params *DeleteScaleSetParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) error {
|
||||
// TODO: Validate the params before sending
|
||||
if params == nil {
|
||||
params = NewDeleteScaleSetParams()
|
||||
}
|
||||
op := &runtime.ClientOperation{
|
||||
ID: "DeleteScaleSet",
|
||||
Method: "DELETE",
|
||||
PathPattern: "/scalesets/{scalesetID}",
|
||||
ProducesMediaTypes: []string{"application/json"},
|
||||
ConsumesMediaTypes: []string{"application/json"},
|
||||
Schemes: []string{"http"},
|
||||
Params: params,
|
||||
Reader: &DeleteScaleSetReader{formats: a.formats},
|
||||
AuthInfo: authInfo,
|
||||
Context: params.Context,
|
||||
Client: params.HTTPClient,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(op)
|
||||
}
|
||||
|
||||
_, err := a.transport.Submit(op)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
GetScaleSet gets scale set by ID
|
||||
*/
|
||||
func (a *Client) GetScaleSet(params *GetScaleSetParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*GetScaleSetOK, error) {
|
||||
// TODO: Validate the params before sending
|
||||
if params == nil {
|
||||
params = NewGetScaleSetParams()
|
||||
}
|
||||
op := &runtime.ClientOperation{
|
||||
ID: "GetScaleSet",
|
||||
Method: "GET",
|
||||
PathPattern: "/scalesets/{scalesetID}",
|
||||
ProducesMediaTypes: []string{"application/json"},
|
||||
ConsumesMediaTypes: []string{"application/json"},
|
||||
Schemes: []string{"http"},
|
||||
Params: params,
|
||||
Reader: &GetScaleSetReader{formats: a.formats},
|
||||
AuthInfo: authInfo,
|
||||
Context: params.Context,
|
||||
Client: params.HTTPClient,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(op)
|
||||
}
|
||||
|
||||
result, err := a.transport.Submit(op)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
success, ok := result.(*GetScaleSetOK)
|
||||
if ok {
|
||||
return success, nil
|
||||
}
|
||||
// unexpected success response
|
||||
unexpectedSuccess := result.(*GetScaleSetDefault)
|
||||
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
|
||||
}
|
||||
|
||||
/*
|
||||
ListScalesets lists all scalesets
|
||||
*/
|
||||
func (a *Client) ListScalesets(params *ListScalesetsParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*ListScalesetsOK, error) {
|
||||
// TODO: Validate the params before sending
|
||||
if params == nil {
|
||||
params = NewListScalesetsParams()
|
||||
}
|
||||
op := &runtime.ClientOperation{
|
||||
ID: "ListScalesets",
|
||||
Method: "GET",
|
||||
PathPattern: "/scalesets",
|
||||
ProducesMediaTypes: []string{"application/json"},
|
||||
ConsumesMediaTypes: []string{"application/json"},
|
||||
Schemes: []string{"http"},
|
||||
Params: params,
|
||||
Reader: &ListScalesetsReader{formats: a.formats},
|
||||
AuthInfo: authInfo,
|
||||
Context: params.Context,
|
||||
Client: params.HTTPClient,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(op)
|
||||
}
|
||||
|
||||
result, err := a.transport.Submit(op)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
success, ok := result.(*ListScalesetsOK)
|
||||
if ok {
|
||||
return success, nil
|
||||
}
|
||||
// unexpected success response
|
||||
unexpectedSuccess := result.(*ListScalesetsDefault)
|
||||
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
|
||||
}
|
||||
|
||||
/*
|
||||
UpdateScaleSet updates scale set by ID
|
||||
*/
|
||||
func (a *Client) UpdateScaleSet(params *UpdateScaleSetParams, authInfo runtime.ClientAuthInfoWriter, opts ...ClientOption) (*UpdateScaleSetOK, error) {
|
||||
// TODO: Validate the params before sending
|
||||
if params == nil {
|
||||
params = NewUpdateScaleSetParams()
|
||||
}
|
||||
op := &runtime.ClientOperation{
|
||||
ID: "UpdateScaleSet",
|
||||
Method: "PUT",
|
||||
PathPattern: "/scalesets/{scalesetID}",
|
||||
ProducesMediaTypes: []string{"application/json"},
|
||||
ConsumesMediaTypes: []string{"application/json"},
|
||||
Schemes: []string{"http"},
|
||||
Params: params,
|
||||
Reader: &UpdateScaleSetReader{formats: a.formats},
|
||||
AuthInfo: authInfo,
|
||||
Context: params.Context,
|
||||
Client: params.HTTPClient,
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(op)
|
||||
}
|
||||
|
||||
result, err := a.transport.Submit(op)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
success, ok := result.(*UpdateScaleSetOK)
|
||||
if ok {
|
||||
return success, nil
|
||||
}
|
||||
// unexpected success response
|
||||
unexpectedSuccess := result.(*UpdateScaleSetDefault)
|
||||
return nil, runtime.NewAPIError("unexpected success response: content available as default response in error", unexpectedSuccess, unexpectedSuccess.Code())
|
||||
}
|
||||
|
||||
// SetTransport changes the transport on the client
|
||||
func (a *Client) SetTransport(transport runtime.ClientTransport) {
|
||||
a.transport = transport
|
||||
}
|
||||
173
client/scalesets/update_scale_set_parameters.go
Normal file
173
client/scalesets/update_scale_set_parameters.go
Normal file
|
|
@ -0,0 +1,173 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package scalesets
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/go-openapi/errors"
|
||||
"github.com/go-openapi/runtime"
|
||||
cr "github.com/go-openapi/runtime/client"
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
garm_params "github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
// NewUpdateScaleSetParams creates a new UpdateScaleSetParams object,
|
||||
// with the default timeout for this client.
|
||||
//
|
||||
// Default values are not hydrated, since defaults are normally applied by the API server side.
|
||||
//
|
||||
// To enforce default values in parameter, use SetDefaults or WithDefaults.
|
||||
func NewUpdateScaleSetParams() *UpdateScaleSetParams {
|
||||
return &UpdateScaleSetParams{
|
||||
timeout: cr.DefaultTimeout,
|
||||
}
|
||||
}
|
||||
|
||||
// NewUpdateScaleSetParamsWithTimeout creates a new UpdateScaleSetParams object
|
||||
// with the ability to set a timeout on a request.
|
||||
func NewUpdateScaleSetParamsWithTimeout(timeout time.Duration) *UpdateScaleSetParams {
|
||||
return &UpdateScaleSetParams{
|
||||
timeout: timeout,
|
||||
}
|
||||
}
|
||||
|
||||
// NewUpdateScaleSetParamsWithContext creates a new UpdateScaleSetParams object
|
||||
// with the ability to set a context for a request.
|
||||
func NewUpdateScaleSetParamsWithContext(ctx context.Context) *UpdateScaleSetParams {
|
||||
return &UpdateScaleSetParams{
|
||||
Context: ctx,
|
||||
}
|
||||
}
|
||||
|
||||
// NewUpdateScaleSetParamsWithHTTPClient creates a new UpdateScaleSetParams object
|
||||
// with the ability to set a custom HTTPClient for a request.
|
||||
func NewUpdateScaleSetParamsWithHTTPClient(client *http.Client) *UpdateScaleSetParams {
|
||||
return &UpdateScaleSetParams{
|
||||
HTTPClient: client,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
UpdateScaleSetParams contains all the parameters to send to the API endpoint
|
||||
|
||||
for the update scale set operation.
|
||||
|
||||
Typically these are written to a http.Request.
|
||||
*/
|
||||
type UpdateScaleSetParams struct {
|
||||
|
||||
/* Body.
|
||||
|
||||
Parameters to update the scale set with.
|
||||
*/
|
||||
Body garm_params.UpdateScaleSetParams
|
||||
|
||||
/* ScalesetID.
|
||||
|
||||
ID of the scale set to update.
|
||||
*/
|
||||
ScalesetID string
|
||||
|
||||
timeout time.Duration
|
||||
Context context.Context
|
||||
HTTPClient *http.Client
|
||||
}
|
||||
|
||||
// WithDefaults hydrates default values in the update scale set params (not the query body).
|
||||
//
|
||||
// All values with no default are reset to their zero value.
|
||||
func (o *UpdateScaleSetParams) WithDefaults() *UpdateScaleSetParams {
|
||||
o.SetDefaults()
|
||||
return o
|
||||
}
|
||||
|
||||
// SetDefaults hydrates default values in the update scale set params (not the query body).
|
||||
//
|
||||
// All values with no default are reset to their zero value.
|
||||
func (o *UpdateScaleSetParams) SetDefaults() {
|
||||
// no default values defined for this parameter
|
||||
}
|
||||
|
||||
// WithTimeout adds the timeout to the update scale set params
|
||||
func (o *UpdateScaleSetParams) WithTimeout(timeout time.Duration) *UpdateScaleSetParams {
|
||||
o.SetTimeout(timeout)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetTimeout adds the timeout to the update scale set params
|
||||
func (o *UpdateScaleSetParams) SetTimeout(timeout time.Duration) {
|
||||
o.timeout = timeout
|
||||
}
|
||||
|
||||
// WithContext adds the context to the update scale set params
|
||||
func (o *UpdateScaleSetParams) WithContext(ctx context.Context) *UpdateScaleSetParams {
|
||||
o.SetContext(ctx)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetContext adds the context to the update scale set params
|
||||
func (o *UpdateScaleSetParams) SetContext(ctx context.Context) {
|
||||
o.Context = ctx
|
||||
}
|
||||
|
||||
// WithHTTPClient adds the HTTPClient to the update scale set params
|
||||
func (o *UpdateScaleSetParams) WithHTTPClient(client *http.Client) *UpdateScaleSetParams {
|
||||
o.SetHTTPClient(client)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetHTTPClient adds the HTTPClient to the update scale set params
|
||||
func (o *UpdateScaleSetParams) SetHTTPClient(client *http.Client) {
|
||||
o.HTTPClient = client
|
||||
}
|
||||
|
||||
// WithBody adds the body to the update scale set params
|
||||
func (o *UpdateScaleSetParams) WithBody(body garm_params.UpdateScaleSetParams) *UpdateScaleSetParams {
|
||||
o.SetBody(body)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetBody adds the body to the update scale set params
|
||||
func (o *UpdateScaleSetParams) SetBody(body garm_params.UpdateScaleSetParams) {
|
||||
o.Body = body
|
||||
}
|
||||
|
||||
// WithScalesetID adds the scalesetID to the update scale set params
|
||||
func (o *UpdateScaleSetParams) WithScalesetID(scalesetID string) *UpdateScaleSetParams {
|
||||
o.SetScalesetID(scalesetID)
|
||||
return o
|
||||
}
|
||||
|
||||
// SetScalesetID adds the scalesetId to the update scale set params
|
||||
func (o *UpdateScaleSetParams) SetScalesetID(scalesetID string) {
|
||||
o.ScalesetID = scalesetID
|
||||
}
|
||||
|
||||
// WriteToRequest writes these params to a swagger request
|
||||
func (o *UpdateScaleSetParams) WriteToRequest(r runtime.ClientRequest, reg strfmt.Registry) error {
|
||||
|
||||
if err := r.SetTimeout(o.timeout); err != nil {
|
||||
return err
|
||||
}
|
||||
var res []error
|
||||
if err := r.SetBodyParam(o.Body); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// path param scalesetID
|
||||
if err := r.SetPathParam("scalesetID", o.ScalesetID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(res) > 0 {
|
||||
return errors.CompositeValidationError(res...)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
184
client/scalesets/update_scale_set_responses.go
Normal file
184
client/scalesets/update_scale_set_responses.go
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
// Code generated by go-swagger; DO NOT EDIT.
|
||||
|
||||
package scalesets
|
||||
|
||||
// This file was generated by the swagger tool.
|
||||
// Editing this file might prove futile when you re-run the swagger generate command
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/go-openapi/runtime"
|
||||
"github.com/go-openapi/strfmt"
|
||||
|
||||
apiserver_params "github.com/cloudbase/garm/apiserver/params"
|
||||
garm_params "github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
// UpdateScaleSetReader is a Reader for the UpdateScaleSet structure.
|
||||
type UpdateScaleSetReader struct {
|
||||
formats strfmt.Registry
|
||||
}
|
||||
|
||||
// ReadResponse reads a server response into the received o.
|
||||
func (o *UpdateScaleSetReader) ReadResponse(response runtime.ClientResponse, consumer runtime.Consumer) (interface{}, error) {
|
||||
switch response.Code() {
|
||||
case 200:
|
||||
result := NewUpdateScaleSetOK()
|
||||
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
default:
|
||||
result := NewUpdateScaleSetDefault(response.Code())
|
||||
if err := result.readResponse(response, consumer, o.formats); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if response.Code()/100 == 2 {
|
||||
return result, nil
|
||||
}
|
||||
return nil, result
|
||||
}
|
||||
}
|
||||
|
||||
// NewUpdateScaleSetOK creates a UpdateScaleSetOK with default headers values
|
||||
func NewUpdateScaleSetOK() *UpdateScaleSetOK {
|
||||
return &UpdateScaleSetOK{}
|
||||
}
|
||||
|
||||
/*
|
||||
UpdateScaleSetOK describes a response with status code 200, with default header values.
|
||||
|
||||
ScaleSet
|
||||
*/
|
||||
type UpdateScaleSetOK struct {
|
||||
Payload garm_params.ScaleSet
|
||||
}
|
||||
|
||||
// IsSuccess returns true when this update scale set o k response has a 2xx status code
|
||||
func (o *UpdateScaleSetOK) IsSuccess() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
// IsRedirect returns true when this update scale set o k response has a 3xx status code
|
||||
func (o *UpdateScaleSetOK) IsRedirect() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsClientError returns true when this update scale set o k response has a 4xx status code
|
||||
func (o *UpdateScaleSetOK) IsClientError() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsServerError returns true when this update scale set o k response has a 5xx status code
|
||||
func (o *UpdateScaleSetOK) IsServerError() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// IsCode returns true when this update scale set o k response a status code equal to that given
|
||||
func (o *UpdateScaleSetOK) IsCode(code int) bool {
|
||||
return code == 200
|
||||
}
|
||||
|
||||
// Code gets the status code for the update scale set o k response
|
||||
func (o *UpdateScaleSetOK) Code() int {
|
||||
return 200
|
||||
}
|
||||
|
||||
func (o *UpdateScaleSetOK) Error() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[PUT /scalesets/{scalesetID}][%d] updateScaleSetOK %s", 200, payload)
|
||||
}
|
||||
|
||||
func (o *UpdateScaleSetOK) String() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[PUT /scalesets/{scalesetID}][%d] updateScaleSetOK %s", 200, payload)
|
||||
}
|
||||
|
||||
func (o *UpdateScaleSetOK) GetPayload() garm_params.ScaleSet {
|
||||
return o.Payload
|
||||
}
|
||||
|
||||
func (o *UpdateScaleSetOK) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// NewUpdateScaleSetDefault creates a UpdateScaleSetDefault with default headers values
|
||||
func NewUpdateScaleSetDefault(code int) *UpdateScaleSetDefault {
|
||||
return &UpdateScaleSetDefault{
|
||||
_statusCode: code,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
UpdateScaleSetDefault describes a response with status code -1, with default header values.
|
||||
|
||||
APIErrorResponse
|
||||
*/
|
||||
type UpdateScaleSetDefault struct {
|
||||
_statusCode int
|
||||
|
||||
Payload apiserver_params.APIErrorResponse
|
||||
}
|
||||
|
||||
// IsSuccess returns true when this update scale set default response has a 2xx status code
|
||||
func (o *UpdateScaleSetDefault) IsSuccess() bool {
|
||||
return o._statusCode/100 == 2
|
||||
}
|
||||
|
||||
// IsRedirect returns true when this update scale set default response has a 3xx status code
|
||||
func (o *UpdateScaleSetDefault) IsRedirect() bool {
|
||||
return o._statusCode/100 == 3
|
||||
}
|
||||
|
||||
// IsClientError returns true when this update scale set default response has a 4xx status code
|
||||
func (o *UpdateScaleSetDefault) IsClientError() bool {
|
||||
return o._statusCode/100 == 4
|
||||
}
|
||||
|
||||
// IsServerError returns true when this update scale set default response has a 5xx status code
|
||||
func (o *UpdateScaleSetDefault) IsServerError() bool {
|
||||
return o._statusCode/100 == 5
|
||||
}
|
||||
|
||||
// IsCode returns true when this update scale set default response a status code equal to that given
|
||||
func (o *UpdateScaleSetDefault) IsCode(code int) bool {
|
||||
return o._statusCode == code
|
||||
}
|
||||
|
||||
// Code gets the status code for the update scale set default response
|
||||
func (o *UpdateScaleSetDefault) Code() int {
|
||||
return o._statusCode
|
||||
}
|
||||
|
||||
func (o *UpdateScaleSetDefault) Error() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[PUT /scalesets/{scalesetID}][%d] UpdateScaleSet default %s", o._statusCode, payload)
|
||||
}
|
||||
|
||||
func (o *UpdateScaleSetDefault) String() string {
|
||||
payload, _ := json.Marshal(o.Payload)
|
||||
return fmt.Sprintf("[PUT /scalesets/{scalesetID}][%d] UpdateScaleSet default %s", o._statusCode, payload)
|
||||
}
|
||||
|
||||
func (o *UpdateScaleSetDefault) GetPayload() apiserver_params.APIErrorResponse {
|
||||
return o.Payload
|
||||
}
|
||||
|
||||
func (o *UpdateScaleSetDefault) readResponse(response runtime.ClientResponse, consumer runtime.Consumer, formats strfmt.Registry) error {
|
||||
|
||||
// response payload
|
||||
if err := consumer.Consume(response.Body(), &o.Payload); err != nil && err != io.EOF {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -379,8 +379,6 @@ func formatOneOrganization(org params.Organization) {
|
|||
t.AppendRow(table.Row{"Endpoint", org.Endpoint.Name})
|
||||
t.AppendRow(table.Row{"Pool balancer type", org.GetBalancerType()})
|
||||
t.AppendRow(table.Row{"Credentials", org.CredentialsName})
|
||||
t.AppendRow(table.Row{"Created at", org.CreatedAt})
|
||||
t.AppendRow(table.Row{"Updated at", org.UpdatedAt})
|
||||
t.AppendRow(table.Row{"Pool manager running", org.PoolManagerStatus.IsRunning})
|
||||
if !org.PoolManagerStatus.IsRunning {
|
||||
t.AppendRow(table.Row{"Failure reason", org.PoolManagerStatus.FailureReason})
|
||||
|
|
|
|||
|
|
@ -493,13 +493,13 @@ func formatPools(pools []params.Pool) {
|
|||
switch {
|
||||
case pool.RepoID != "" && pool.RepoName != "":
|
||||
belongsTo = pool.RepoName
|
||||
level = "repo"
|
||||
level = entityTypeRepo
|
||||
case pool.OrgID != "" && pool.OrgName != "":
|
||||
belongsTo = pool.OrgName
|
||||
level = "org"
|
||||
level = entityTypeOrg
|
||||
case pool.EnterpriseID != "" && pool.EnterpriseName != "":
|
||||
belongsTo = pool.EnterpriseName
|
||||
level = "enterprise"
|
||||
level = entityTypeEnterprise
|
||||
}
|
||||
row := table.Row{pool.ID, pool.Image, pool.Flavor, strings.Join(tags, " "), belongsTo, pool.Enabled}
|
||||
if long {
|
||||
|
|
@ -532,13 +532,13 @@ func formatOnePool(pool params.Pool) {
|
|||
switch {
|
||||
case pool.RepoID != "" && pool.RepoName != "":
|
||||
belongsTo = pool.RepoName
|
||||
level = "repo"
|
||||
level = entityTypeRepo
|
||||
case pool.OrgID != "" && pool.OrgName != "":
|
||||
belongsTo = pool.OrgName
|
||||
level = "org"
|
||||
level = entityTypeOrg
|
||||
case pool.EnterpriseID != "" && pool.EnterpriseName != "":
|
||||
belongsTo = pool.EnterpriseName
|
||||
level = "enterprise"
|
||||
level = entityTypeEnterprise
|
||||
}
|
||||
|
||||
t.AppendHeader(header)
|
||||
|
|
|
|||
|
|
@ -31,6 +31,12 @@ import (
|
|||
"github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
const (
|
||||
entityTypeOrg string = "org"
|
||||
entityTypeRepo string = "repo"
|
||||
entityTypeEnterprise string = "enterprise"
|
||||
)
|
||||
|
||||
var (
|
||||
cfg *config.Config
|
||||
mgr config.Manager
|
||||
|
|
|
|||
|
|
@ -228,14 +228,14 @@ func formatInstances(param []params.Instance, detailed bool) {
|
|||
return
|
||||
}
|
||||
t := table.NewWriter()
|
||||
header := table.Row{"Nr", "Name", "Status", "Runner Status", "Pool ID"}
|
||||
header := table.Row{"Nr", "Name", "Status", "Runner Status", "Pool ID", "Scalse Set ID"}
|
||||
if detailed {
|
||||
header = append(header, "Created At", "Updated At", "Job Name", "Started At", "Run ID", "Repository")
|
||||
}
|
||||
t.AppendHeader(header)
|
||||
|
||||
for idx, inst := range param {
|
||||
row := table.Row{idx + 1, inst.Name, inst.Status, inst.RunnerStatus, inst.PoolID}
|
||||
row := table.Row{idx + 1, inst.Name, inst.Status, inst.RunnerStatus, inst.PoolID, inst.ScaleSetID}
|
||||
if detailed {
|
||||
row = append(row, inst.CreatedAt, inst.UpdatedAt)
|
||||
if inst.Job != nil {
|
||||
|
|
@ -270,7 +270,11 @@ func formatSingleInstance(instance params.Instance) {
|
|||
t.AppendRow(table.Row{"OS Version", instance.OSVersion}, table.RowConfig{AutoMerge: false})
|
||||
t.AppendRow(table.Row{"Status", instance.Status}, table.RowConfig{AutoMerge: false})
|
||||
t.AppendRow(table.Row{"Runner Status", instance.RunnerStatus}, table.RowConfig{AutoMerge: false})
|
||||
t.AppendRow(table.Row{"Pool ID", instance.PoolID}, table.RowConfig{AutoMerge: false})
|
||||
if instance.PoolID != "" {
|
||||
t.AppendRow(table.Row{"Pool ID", instance.PoolID}, table.RowConfig{AutoMerge: false})
|
||||
} else if instance.ScaleSetID != 0 {
|
||||
t.AppendRow(table.Row{"Scale Set ID", instance.ScaleSetID}, table.RowConfig{AutoMerge: false})
|
||||
}
|
||||
|
||||
if len(instance.Addresses) > 0 {
|
||||
for _, addr := range instance.Addresses {
|
||||
|
|
|
|||
518
cmd/garm-cli/cmd/scalesets.go
Normal file
518
cmd/garm-cli/cmd/scalesets.go
Normal file
|
|
@ -0,0 +1,518 @@
|
|||
// Copyright 2022 Cloudbase Solutions SRL
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/jedib0t/go-pretty/v6/table"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
commonParams "github.com/cloudbase/garm-provider-common/params"
|
||||
apiClientEnterprises "github.com/cloudbase/garm/client/enterprises"
|
||||
apiClientOrgs "github.com/cloudbase/garm/client/organizations"
|
||||
apiClientRepos "github.com/cloudbase/garm/client/repositories"
|
||||
apiClientScaleSets "github.com/cloudbase/garm/client/scalesets"
|
||||
"github.com/cloudbase/garm/cmd/garm-cli/common"
|
||||
"github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
var (
|
||||
scalesetProvider string
|
||||
scalesetMaxRunners uint
|
||||
scalesetMinIdleRunners uint
|
||||
scalesetRunnerPrefix string
|
||||
scalesetName string
|
||||
scalesetImage string
|
||||
scalesetFlavor string
|
||||
scalesetOSType string
|
||||
scalesetOSArch string
|
||||
scalesetEnabled bool
|
||||
scalesetRunnerBootstrapTimeout uint
|
||||
scalesetRepository string
|
||||
scalesetOrganization string
|
||||
scalesetEnterprise string
|
||||
scalesetExtraSpecsFile string
|
||||
scalesetExtraSpecs string
|
||||
scalesetAll bool
|
||||
scalesetGitHubRunnerGroup string
|
||||
)
|
||||
|
||||
type scalesetPayloadGetter interface {
|
||||
GetPayload() params.ScaleSet
|
||||
}
|
||||
|
||||
type scalesetsPayloadGetter interface {
|
||||
GetPayload() params.ScaleSets
|
||||
}
|
||||
|
||||
// scalesetCmd represents the scale set command
|
||||
var scalesetCmd = &cobra.Command{
|
||||
Use: "scaleset",
|
||||
SilenceUsage: true,
|
||||
Short: "List scale sets",
|
||||
Long: `Query information or perform operations on scale sets.`,
|
||||
Run: nil,
|
||||
}
|
||||
|
||||
var scalesetListCmd = &cobra.Command{
|
||||
Use: "list",
|
||||
Aliases: []string{"ls"},
|
||||
Short: "List scale sets",
|
||||
Long: `List scale sets of repositories, orgs or all of the above.
|
||||
|
||||
This command will list scale sets from one repo, one org or all scale sets
|
||||
on the system. The list flags are mutually exclusive. You must however
|
||||
specify one of them.
|
||||
|
||||
Example:
|
||||
|
||||
List scalesets from one repo:
|
||||
garm-cli scaleset list --repo=05e7eac6-4705-486d-89c9-0170bbb576af
|
||||
|
||||
List scalesets from one org:
|
||||
garm-cli scaleset list --org=5493e51f-3170-4ce3-9f05-3fe690fc6ec6
|
||||
|
||||
List scalesets from one enterprise:
|
||||
garm-cli scaleset list --enterprise=a8ee4c66-e762-4cbe-a35d-175dba2c9e62
|
||||
|
||||
List all scalesets from all repos, orgs and enterprises:
|
||||
garm-cli scaleset list --all
|
||||
|
||||
`,
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if needsInit {
|
||||
return errNeedsInitError
|
||||
}
|
||||
|
||||
var response scalesetsPayloadGetter
|
||||
var err error
|
||||
|
||||
switch len(args) {
|
||||
case 0:
|
||||
if cmd.Flags().Changed("repo") {
|
||||
listRepoScaleSetsReq := apiClientRepos.NewListRepoScaleSetsParams()
|
||||
listRepoScaleSetsReq.RepoID = scalesetRepository
|
||||
response, err = apiCli.Repositories.ListRepoScaleSets(listRepoScaleSetsReq, authToken)
|
||||
} else if cmd.Flags().Changed("org") {
|
||||
listOrgScaleSetsReq := apiClientOrgs.NewListOrgScaleSetsParams()
|
||||
listOrgScaleSetsReq.OrgID = scalesetOrganization
|
||||
response, err = apiCli.Organizations.ListOrgScaleSets(listOrgScaleSetsReq, authToken)
|
||||
} else if cmd.Flags().Changed("enterprise") {
|
||||
listEnterpriseScaleSetsReq := apiClientEnterprises.NewListEnterpriseScaleSetsParams()
|
||||
listEnterpriseScaleSetsReq.EnterpriseID = scalesetEnterprise
|
||||
response, err = apiCli.Enterprises.ListEnterpriseScaleSets(listEnterpriseScaleSetsReq, authToken)
|
||||
} else if cmd.Flags().Changed("all") {
|
||||
listScaleSetsReq := apiClientScaleSets.NewListScalesetsParams()
|
||||
response, err = apiCli.Scalesets.ListScalesets(listScaleSetsReq, authToken)
|
||||
} else {
|
||||
cmd.Help() //nolint
|
||||
os.Exit(0)
|
||||
}
|
||||
default:
|
||||
cmd.Help() //nolint
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
formatScaleSets(response.GetPayload())
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var scaleSetShowCmd = &cobra.Command{
|
||||
Use: "show",
|
||||
Short: "Show details for a scale set",
|
||||
Long: `Displays a detailed view of a single scale set.`,
|
||||
SilenceUsage: true,
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
if needsInit {
|
||||
return errNeedsInitError
|
||||
}
|
||||
|
||||
if len(args) == 0 {
|
||||
return fmt.Errorf("requires a scale set ID")
|
||||
}
|
||||
|
||||
if len(args) > 1 {
|
||||
return fmt.Errorf("too many arguments")
|
||||
}
|
||||
|
||||
getScaleSetReq := apiClientScaleSets.NewGetScaleSetParams()
|
||||
getScaleSetReq.ScalesetID = args[0]
|
||||
response, err := apiCli.Scalesets.GetScaleSet(getScaleSetReq, authToken)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
formatOneScaleSet(response.Payload)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var scaleSetDeleteCmd = &cobra.Command{
|
||||
Use: "delete",
|
||||
Aliases: []string{"remove", "rm", "del"},
|
||||
Short: "Delete scale set by ID",
|
||||
Long: `Delete one scale set by referencing it's ID, regardless of repo or org.`,
|
||||
SilenceUsage: true,
|
||||
RunE: func(_ *cobra.Command, args []string) error {
|
||||
if needsInit {
|
||||
return errNeedsInitError
|
||||
}
|
||||
|
||||
if len(args) == 0 {
|
||||
return fmt.Errorf("requires a scale set ID")
|
||||
}
|
||||
|
||||
if len(args) > 1 {
|
||||
return fmt.Errorf("too many arguments")
|
||||
}
|
||||
|
||||
deleteScaleSetReq := apiClientScaleSets.NewDeleteScaleSetParams()
|
||||
deleteScaleSetReq.ScalesetID = args[0]
|
||||
if err := apiCli.Scalesets.DeleteScaleSet(deleteScaleSetReq, authToken); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var scaleSetAddCmd = &cobra.Command{
|
||||
Use: "add",
|
||||
Aliases: []string{"create"},
|
||||
Short: "Add scale set",
|
||||
Long: `Add a new scale set.`,
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
if needsInit {
|
||||
return errNeedsInitError
|
||||
}
|
||||
|
||||
newScaleSetParams := params.CreateScaleSetParams{
|
||||
RunnerPrefix: params.RunnerPrefix{
|
||||
Prefix: scalesetRunnerPrefix,
|
||||
},
|
||||
ProviderName: scalesetProvider,
|
||||
Name: scalesetName,
|
||||
MaxRunners: scalesetMaxRunners,
|
||||
MinIdleRunners: scalesetMinIdleRunners,
|
||||
Image: scalesetImage,
|
||||
Flavor: scalesetFlavor,
|
||||
OSType: commonParams.OSType(scalesetOSType),
|
||||
OSArch: commonParams.OSArch(scalesetOSArch),
|
||||
Enabled: scalesetEnabled,
|
||||
RunnerBootstrapTimeout: scalesetRunnerBootstrapTimeout,
|
||||
GitHubRunnerGroup: scalesetGitHubRunnerGroup,
|
||||
}
|
||||
|
||||
if cmd.Flags().Changed("extra-specs") {
|
||||
data, err := asRawMessage([]byte(scalesetExtraSpecs))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newScaleSetParams.ExtraSpecs = data
|
||||
}
|
||||
|
||||
if scalesetExtraSpecsFile != "" {
|
||||
data, err := extraSpecsFromFile(scalesetExtraSpecsFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newScaleSetParams.ExtraSpecs = data
|
||||
}
|
||||
|
||||
if err := newScaleSetParams.Validate(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var err error
|
||||
var response scalesetPayloadGetter
|
||||
if cmd.Flags().Changed("repo") {
|
||||
newRepoScaleSetReq := apiClientRepos.NewCreateRepoScaleSetParams()
|
||||
newRepoScaleSetReq.RepoID = scalesetRepository
|
||||
newRepoScaleSetReq.Body = newScaleSetParams
|
||||
response, err = apiCli.Repositories.CreateRepoScaleSet(newRepoScaleSetReq, authToken)
|
||||
} else if cmd.Flags().Changed("org") {
|
||||
newOrgScaleSetReq := apiClientOrgs.NewCreateOrgScaleSetParams()
|
||||
newOrgScaleSetReq.OrgID = scalesetOrganization
|
||||
newOrgScaleSetReq.Body = newScaleSetParams
|
||||
response, err = apiCli.Organizations.CreateOrgScaleSet(newOrgScaleSetReq, authToken)
|
||||
} else if cmd.Flags().Changed("enterprise") {
|
||||
newEnterpriseScaleSetReq := apiClientEnterprises.NewCreateEnterpriseScaleSetParams()
|
||||
newEnterpriseScaleSetReq.EnterpriseID = scalesetEnterprise
|
||||
newEnterpriseScaleSetReq.Body = newScaleSetParams
|
||||
response, err = apiCli.Enterprises.CreateEnterpriseScaleSet(newEnterpriseScaleSetReq, authToken)
|
||||
} else {
|
||||
cmd.Help() //nolint
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
formatOneScaleSet(response.GetPayload())
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
var scaleSetUpdateCmd = &cobra.Command{
|
||||
Use: "update",
|
||||
Short: "Update one scale set",
|
||||
Long: `Updates scale set characteristics.
|
||||
|
||||
This command updates the scale set characteristics. Runners already created prior to updating
|
||||
the scale set, will not be recreated. If they no longer suit your needs, you will need to
|
||||
explicitly remove them using the runner delete command.
|
||||
`,
|
||||
SilenceUsage: true,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if needsInit {
|
||||
return errNeedsInitError
|
||||
}
|
||||
|
||||
if len(args) == 0 {
|
||||
return fmt.Errorf("command requires a scale set ID")
|
||||
}
|
||||
|
||||
if len(args) > 1 {
|
||||
return fmt.Errorf("too many arguments")
|
||||
}
|
||||
|
||||
updateScaleSetReq := apiClientScaleSets.NewUpdateScaleSetParams()
|
||||
scaleSetUpdateParams := params.UpdateScaleSetParams{}
|
||||
|
||||
if cmd.Flags().Changed("image") {
|
||||
scaleSetUpdateParams.Image = scalesetImage
|
||||
}
|
||||
|
||||
if cmd.Flags().Changed("name") {
|
||||
scaleSetUpdateParams.Name = scalesetName
|
||||
}
|
||||
|
||||
if cmd.Flags().Changed("flavor") {
|
||||
scaleSetUpdateParams.Flavor = scalesetFlavor
|
||||
}
|
||||
|
||||
if cmd.Flags().Changed("os-type") {
|
||||
scaleSetUpdateParams.OSType = commonParams.OSType(scalesetOSType)
|
||||
}
|
||||
|
||||
if cmd.Flags().Changed("os-arch") {
|
||||
scaleSetUpdateParams.OSArch = commonParams.OSArch(scalesetOSArch)
|
||||
}
|
||||
|
||||
if cmd.Flags().Changed("max-runners") {
|
||||
scaleSetUpdateParams.MaxRunners = &scalesetMaxRunners
|
||||
}
|
||||
|
||||
if cmd.Flags().Changed("min-idle-runners") {
|
||||
scaleSetUpdateParams.MinIdleRunners = &scalesetMinIdleRunners
|
||||
}
|
||||
|
||||
if cmd.Flags().Changed("runner-prefix") {
|
||||
scaleSetUpdateParams.RunnerPrefix = params.RunnerPrefix{
|
||||
Prefix: scalesetRunnerPrefix,
|
||||
}
|
||||
}
|
||||
|
||||
if cmd.Flags().Changed("runner-group") {
|
||||
scaleSetUpdateParams.GitHubRunnerGroup = &scalesetGitHubRunnerGroup
|
||||
}
|
||||
|
||||
if cmd.Flags().Changed("enabled") {
|
||||
scaleSetUpdateParams.Enabled = &scalesetEnabled
|
||||
}
|
||||
|
||||
if cmd.Flags().Changed("runner-bootstrap-timeout") {
|
||||
scaleSetUpdateParams.RunnerBootstrapTimeout = &scalesetRunnerBootstrapTimeout
|
||||
}
|
||||
|
||||
if cmd.Flags().Changed("extra-specs") {
|
||||
data, err := asRawMessage([]byte(scalesetExtraSpecs))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
scaleSetUpdateParams.ExtraSpecs = data
|
||||
}
|
||||
|
||||
if scalesetExtraSpecsFile != "" {
|
||||
data, err := extraSpecsFromFile(scalesetExtraSpecsFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
scaleSetUpdateParams.ExtraSpecs = data
|
||||
}
|
||||
|
||||
updateScaleSetReq.ScalesetID = args[0]
|
||||
updateScaleSetReq.Body = scaleSetUpdateParams
|
||||
response, err := apiCli.Scalesets.UpdateScaleSet(updateScaleSetReq, authToken)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
formatOneScaleSet(response.Payload)
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
scalesetListCmd.Flags().StringVarP(&scalesetRepository, "repo", "r", "", "List all scale sets within this repository.")
|
||||
scalesetListCmd.Flags().StringVarP(&scalesetOrganization, "org", "o", "", "List all scale sets within this organization.")
|
||||
scalesetListCmd.Flags().StringVarP(&scalesetEnterprise, "enterprise", "e", "", "List all scale sets within this enterprise.")
|
||||
scalesetListCmd.Flags().BoolVarP(&scalesetAll, "all", "a", false, "List all scale sets, regardless of org or repo.")
|
||||
scalesetListCmd.MarkFlagsMutuallyExclusive("repo", "org", "all", "enterprise")
|
||||
|
||||
scaleSetUpdateCmd.Flags().StringVar(&scalesetImage, "image", "", "The provider-specific image name to use for runners in this scale set.")
|
||||
scaleSetUpdateCmd.Flags().StringVar(&scalesetFlavor, "flavor", "", "The flavor to use for the runners in this scale set.")
|
||||
scaleSetUpdateCmd.Flags().StringVar(&scalesetName, "name", "", "The name of the scale set. This option is mandatory.")
|
||||
scaleSetUpdateCmd.Flags().StringVar(&scalesetOSType, "os-type", "linux", "Operating system type (windows, linux, etc).")
|
||||
scaleSetUpdateCmd.Flags().StringVar(&scalesetOSArch, "os-arch", "amd64", "Operating system architecture (amd64, arm, etc).")
|
||||
scaleSetUpdateCmd.Flags().StringVar(&scalesetRunnerPrefix, "runner-prefix", "", "The name prefix to use for runners in this scale set.")
|
||||
scaleSetUpdateCmd.Flags().UintVar(&scalesetMaxRunners, "max-runners", 5, "The maximum number of runner this scale set will create.")
|
||||
scaleSetUpdateCmd.Flags().UintVar(&scalesetMinIdleRunners, "min-idle-runners", 1, "Attempt to maintain a minimum of idle self-hosted runners of this type.")
|
||||
scaleSetUpdateCmd.Flags().StringVar(&scalesetGitHubRunnerGroup, "runner-group", "", "The GitHub runner group in which all runners of this scale set will be added.")
|
||||
scaleSetUpdateCmd.Flags().BoolVar(&scalesetEnabled, "enabled", false, "Enable this scale set.")
|
||||
scaleSetUpdateCmd.Flags().UintVar(&scalesetRunnerBootstrapTimeout, "runner-bootstrap-timeout", 20, "Duration in minutes after which a runner is considered failed if it does not join Github.")
|
||||
scaleSetUpdateCmd.Flags().StringVar(&scalesetExtraSpecsFile, "extra-specs-file", "", "A file containing a valid json which will be passed to the IaaS provider managing the scale set.")
|
||||
scaleSetUpdateCmd.Flags().StringVar(&scalesetExtraSpecs, "extra-specs", "", "A valid json which will be passed to the IaaS provider managing the scale set.")
|
||||
scaleSetUpdateCmd.MarkFlagsMutuallyExclusive("extra-specs-file", "extra-specs")
|
||||
|
||||
scaleSetAddCmd.Flags().StringVar(&scalesetProvider, "provider-name", "", "The name of the provider where runners will be created.")
|
||||
scaleSetAddCmd.Flags().StringVar(&scalesetImage, "image", "", "The provider-specific image name to use for runners in this scale set.")
|
||||
scaleSetAddCmd.Flags().StringVar(&scalesetName, "name", "", "The name of the scale set. This option is mandatory.")
|
||||
scaleSetAddCmd.Flags().StringVar(&scalesetFlavor, "flavor", "", "The flavor to use for this runner.")
|
||||
scaleSetAddCmd.Flags().StringVar(&scalesetRunnerPrefix, "runner-prefix", "", "The name prefix to use for runners in this scale set.")
|
||||
scaleSetAddCmd.Flags().StringVar(&scalesetOSType, "os-type", "linux", "Operating system type (windows, linux, etc).")
|
||||
scaleSetAddCmd.Flags().StringVar(&scalesetOSArch, "os-arch", "amd64", "Operating system architecture (amd64, arm, etc).")
|
||||
scaleSetAddCmd.Flags().StringVar(&scalesetExtraSpecsFile, "extra-specs-file", "", "A file containing a valid json which will be passed to the IaaS provider managing the scale set.")
|
||||
scaleSetAddCmd.Flags().StringVar(&scalesetExtraSpecs, "extra-specs", "", "A valid json which will be passed to the IaaS provider managing the scale set.")
|
||||
scaleSetAddCmd.Flags().StringVar(&scalesetGitHubRunnerGroup, "runner-group", "", "The GitHub runner group in which all runners of this scale set will be added.")
|
||||
scaleSetAddCmd.Flags().UintVar(&scalesetMaxRunners, "max-runners", 5, "The maximum number of runner this scale set will create.")
|
||||
scaleSetAddCmd.Flags().UintVar(&scalesetRunnerBootstrapTimeout, "runner-bootstrap-timeout", 20, "Duration in minutes after which a runner is considered failed if it does not join Github.")
|
||||
scaleSetAddCmd.Flags().UintVar(&scalesetMinIdleRunners, "min-idle-runners", 1, "Attempt to maintain a minimum of idle self-hosted runners of this type.")
|
||||
scaleSetAddCmd.Flags().BoolVar(&scalesetEnabled, "enabled", false, "Enable this scale set.")
|
||||
scaleSetAddCmd.MarkFlagRequired("provider-name") //nolint
|
||||
scaleSetAddCmd.MarkFlagRequired("name") //nolint
|
||||
scaleSetAddCmd.MarkFlagRequired("image") //nolint
|
||||
scaleSetAddCmd.MarkFlagRequired("flavor") //nolint
|
||||
|
||||
scaleSetAddCmd.Flags().StringVarP(&scalesetRepository, "repo", "r", "", "Add the new scale set within this repository.")
|
||||
scaleSetAddCmd.Flags().StringVarP(&scalesetOrganization, "org", "o", "", "Add the new scale set within this organization.")
|
||||
scaleSetAddCmd.Flags().StringVarP(&scalesetEnterprise, "enterprise", "e", "", "Add the new scale set within this enterprise.")
|
||||
scaleSetAddCmd.MarkFlagsMutuallyExclusive("repo", "org", "enterprise")
|
||||
scaleSetAddCmd.MarkFlagsMutuallyExclusive("extra-specs-file", "extra-specs")
|
||||
|
||||
scalesetCmd.AddCommand(
|
||||
scalesetListCmd,
|
||||
scaleSetShowCmd,
|
||||
scaleSetDeleteCmd,
|
||||
scaleSetUpdateCmd,
|
||||
scaleSetAddCmd,
|
||||
)
|
||||
|
||||
rootCmd.AddCommand(scalesetCmd)
|
||||
}
|
||||
|
||||
func formatScaleSets(scaleSets []params.ScaleSet) {
|
||||
if outputFormat == common.OutputFormatJSON {
|
||||
printAsJSON(scaleSets)
|
||||
return
|
||||
}
|
||||
t := table.NewWriter()
|
||||
header := table.Row{"ID", "Scale Set Name", "Image", "Flavor", "Belongs to", "Level", "Enabled", "Runner Prefix", "Provider"}
|
||||
t.AppendHeader(header)
|
||||
|
||||
for _, scaleSet := range scaleSets {
|
||||
var belongsTo string
|
||||
var level string
|
||||
|
||||
switch {
|
||||
case scaleSet.RepoID != "" && scaleSet.RepoName != "":
|
||||
belongsTo = scaleSet.RepoName
|
||||
level = entityTypeRepo
|
||||
case scaleSet.OrgID != "" && scaleSet.OrgName != "":
|
||||
belongsTo = scaleSet.OrgName
|
||||
level = entityTypeOrg
|
||||
case scaleSet.EnterpriseID != "" && scaleSet.EnterpriseName != "":
|
||||
belongsTo = scaleSet.EnterpriseName
|
||||
level = entityTypeEnterprise
|
||||
}
|
||||
t.AppendRow(table.Row{scaleSet.ID, scaleSet.Name, scaleSet.Image, scaleSet.Flavor, belongsTo, level, scaleSet.Enabled, scaleSet.GetRunnerPrefix(), scaleSet.ProviderName})
|
||||
t.AppendSeparator()
|
||||
}
|
||||
fmt.Println(t.Render())
|
||||
}
|
||||
|
||||
func formatOneScaleSet(scaleSet params.ScaleSet) {
|
||||
if outputFormat == common.OutputFormatJSON {
|
||||
printAsJSON(scaleSet)
|
||||
return
|
||||
}
|
||||
t := table.NewWriter()
|
||||
rowConfigAutoMerge := table.RowConfig{AutoMerge: true}
|
||||
|
||||
header := table.Row{"Field", "Value"}
|
||||
|
||||
var belongsTo string
|
||||
var level string
|
||||
|
||||
switch {
|
||||
case scaleSet.RepoID != "" && scaleSet.RepoName != "":
|
||||
belongsTo = scaleSet.RepoName
|
||||
level = entityTypeRepo
|
||||
case scaleSet.OrgID != "" && scaleSet.OrgName != "":
|
||||
belongsTo = scaleSet.OrgName
|
||||
level = entityTypeOrg
|
||||
case scaleSet.EnterpriseID != "" && scaleSet.EnterpriseName != "":
|
||||
belongsTo = scaleSet.EnterpriseName
|
||||
level = entityTypeEnterprise
|
||||
}
|
||||
|
||||
t.AppendHeader(header)
|
||||
t.AppendRow(table.Row{"ID", scaleSet.ID})
|
||||
t.AppendRow(table.Row{"Scale Set ID", scaleSet.ScaleSetID})
|
||||
t.AppendRow(table.Row{"Scale Name", scaleSet.Name})
|
||||
t.AppendRow(table.Row{"Provider Name", scaleSet.ProviderName})
|
||||
t.AppendRow(table.Row{"Image", scaleSet.Image})
|
||||
t.AppendRow(table.Row{"Flavor", scaleSet.Flavor})
|
||||
t.AppendRow(table.Row{"OS Type", scaleSet.OSType})
|
||||
t.AppendRow(table.Row{"OS Architecture", scaleSet.OSArch})
|
||||
t.AppendRow(table.Row{"Max Runners", scaleSet.MaxRunners})
|
||||
t.AppendRow(table.Row{"Min Idle Runners", scaleSet.MinIdleRunners})
|
||||
t.AppendRow(table.Row{"Runner Bootstrap Timeout", scaleSet.RunnerBootstrapTimeout})
|
||||
t.AppendRow(table.Row{"Belongs to", belongsTo})
|
||||
t.AppendRow(table.Row{"Level", level})
|
||||
t.AppendRow(table.Row{"Enabled", scaleSet.Enabled})
|
||||
t.AppendRow(table.Row{"Runner Prefix", scaleSet.GetRunnerPrefix()})
|
||||
t.AppendRow(table.Row{"Extra specs", string(scaleSet.ExtraSpecs)})
|
||||
t.AppendRow(table.Row{"GitHub Runner Group", scaleSet.GitHubRunnerGroup})
|
||||
|
||||
if len(scaleSet.Instances) > 0 {
|
||||
for _, instance := range scaleSet.Instances {
|
||||
t.AppendRow(table.Row{"Instances", fmt.Sprintf("%s (%s)", instance.Name, instance.ID)}, rowConfigAutoMerge)
|
||||
}
|
||||
}
|
||||
|
||||
t.SetColumnConfigs([]table.ColumnConfig{
|
||||
{Number: 1, AutoMerge: true},
|
||||
{Number: 2, AutoMerge: false, WidthMax: 100},
|
||||
})
|
||||
fmt.Println(t.Render())
|
||||
}
|
||||
|
|
@ -25,6 +25,7 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"os/signal"
|
||||
"runtime"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
|
|
@ -41,13 +42,18 @@ import (
|
|||
"github.com/cloudbase/garm/database"
|
||||
"github.com/cloudbase/garm/database/common"
|
||||
"github.com/cloudbase/garm/database/watcher"
|
||||
"github.com/cloudbase/garm/locking"
|
||||
"github.com/cloudbase/garm/metrics"
|
||||
"github.com/cloudbase/garm/params"
|
||||
"github.com/cloudbase/garm/runner" //nolint:typecheck
|
||||
runnerMetrics "github.com/cloudbase/garm/runner/metrics"
|
||||
"github.com/cloudbase/garm/runner/providers"
|
||||
garmUtil "github.com/cloudbase/garm/util"
|
||||
"github.com/cloudbase/garm/util/appdefaults"
|
||||
"github.com/cloudbase/garm/websocket"
|
||||
"github.com/cloudbase/garm/workers/credentials"
|
||||
"github.com/cloudbase/garm/workers/entity"
|
||||
"github.com/cloudbase/garm/workers/provider"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -60,16 +66,17 @@ var signals = []os.Signal{
|
|||
syscall.SIGTERM,
|
||||
}
|
||||
|
||||
func maybeInitController(db common.Store) error {
|
||||
if _, err := db.ControllerInfo(); err == nil {
|
||||
return nil
|
||||
func maybeInitController(db common.Store) (params.ControllerInfo, error) {
|
||||
if info, err := db.ControllerInfo(); err == nil {
|
||||
return info, nil
|
||||
}
|
||||
|
||||
if _, err := db.InitController(); err != nil {
|
||||
return errors.Wrap(err, "initializing controller")
|
||||
info, err := db.InitController()
|
||||
if err != nil {
|
||||
return params.ControllerInfo{}, errors.Wrap(err, "initializing controller")
|
||||
}
|
||||
|
||||
return nil
|
||||
return info, nil
|
||||
}
|
||||
|
||||
func setupLogging(ctx context.Context, logCfg config.Logging, hub *websocket.Hub) {
|
||||
|
|
@ -174,6 +181,7 @@ func maybeUpdateURLsFromConfig(cfg config.Config, store common.Store) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
//gocyclo:ignore
|
||||
func main() {
|
||||
flag.Parse()
|
||||
if *version {
|
||||
|
|
@ -210,14 +218,60 @@ func main() {
|
|||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if err := maybeInitController(db); err != nil {
|
||||
controllerInfo, err := maybeInitController(db)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Local locker for now. Will be configurable in the future,
|
||||
// as we add scale-out capability to GARM.
|
||||
lock, err := locking.NewLocalLocker(ctx, db)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to create locker: %q", err)
|
||||
}
|
||||
|
||||
if err := locking.RegisterLocker(lock); err != nil {
|
||||
log.Fatalf("failed to register locker: %q", err)
|
||||
}
|
||||
|
||||
if err := maybeUpdateURLsFromConfig(*cfg, db); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
credsWorker, err := credentials.NewWorker(ctx, db)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to create credentials worker: %+v", err)
|
||||
}
|
||||
if err := credsWorker.Start(); err != nil {
|
||||
log.Fatalf("failed to start credentials worker: %+v", err)
|
||||
}
|
||||
|
||||
providers, err := providers.LoadProvidersFromConfig(ctx, *cfg, controllerInfo.ControllerID.String())
|
||||
if err != nil {
|
||||
log.Fatalf("loading providers: %+v", err)
|
||||
}
|
||||
|
||||
entityController, err := entity.NewController(ctx, db, providers)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to create entity controller: %+v", err)
|
||||
}
|
||||
if err := entityController.Start(); err != nil {
|
||||
log.Fatalf("failed to start entity controller: %+v", err)
|
||||
}
|
||||
|
||||
instanceTokenGetter, err := auth.NewInstanceTokenGetter(cfg.JWTAuth.Secret)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to create instance token getter: %+v", err)
|
||||
}
|
||||
|
||||
providerWorker, err := provider.NewWorker(ctx, db, providers, instanceTokenGetter)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to create provider worker: %+v", err)
|
||||
}
|
||||
if err := providerWorker.Start(); err != nil {
|
||||
log.Fatalf("failed to start provider worker: %+v", err)
|
||||
}
|
||||
|
||||
runner, err := runner.NewRunner(ctx, *cfg, db)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to create controller: %+v", err)
|
||||
|
|
@ -276,6 +330,8 @@ func main() {
|
|||
}
|
||||
|
||||
if cfg.Default.DebugServer {
|
||||
runtime.SetBlockProfileRate(1)
|
||||
runtime.SetMutexProfileFraction(1)
|
||||
slog.InfoContext(ctx, "setting up debug routes")
|
||||
router = routers.WithDebugServer(router)
|
||||
}
|
||||
|
|
@ -314,6 +370,20 @@ func main() {
|
|||
|
||||
<-ctx.Done()
|
||||
|
||||
if err := credsWorker.Stop(); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to stop credentials worker")
|
||||
}
|
||||
|
||||
slog.InfoContext(ctx, "shutting down entity controller")
|
||||
if err := entityController.Stop(); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to stop entity controller")
|
||||
}
|
||||
|
||||
slog.InfoContext(ctx, "shutting down provider worker")
|
||||
if err := providerWorker.Stop(); err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(ctx, "failed to stop provider worker")
|
||||
}
|
||||
|
||||
shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 60*time.Second)
|
||||
defer shutdownCancel()
|
||||
if err := srv.Shutdown(shutdownCtx); err != nil {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Code generated by mockery v2.42.0. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.3. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
|
|
@ -14,6 +14,24 @@ type Store struct {
|
|||
mock.Mock
|
||||
}
|
||||
|
||||
// AddEntityEvent provides a mock function with given fields: ctx, entity, event, eventLevel, statusMessage, maxEvents
|
||||
func (_m *Store) AddEntityEvent(ctx context.Context, entity params.GithubEntity, event params.EventType, eventLevel params.EventLevel, statusMessage string, maxEvents int) error {
|
||||
ret := _m.Called(ctx, entity, event, eventLevel, statusMessage, maxEvents)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for AddEntityEvent")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, params.GithubEntity, params.EventType, params.EventLevel, string, int) error); ok {
|
||||
r0 = rf(ctx, entity, event, eventLevel, statusMessage, maxEvents)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// AddInstanceEvent provides a mock function with given fields: ctx, instanceName, event, eventLevel, eventMessage
|
||||
func (_m *Store) AddInstanceEvent(ctx context.Context, instanceName string, event params.EventType, eventLevel params.EventLevel, eventMessage string) error {
|
||||
ret := _m.Called(ctx, instanceName, event, eventLevel, eventMessage)
|
||||
|
|
@ -50,7 +68,7 @@ func (_m *Store) BreakLockJobIsQueued(ctx context.Context, jobID int64) error {
|
|||
return r0
|
||||
}
|
||||
|
||||
// ControllerInfo provides a mock function with given fields:
|
||||
// ControllerInfo provides a mock function with no fields
|
||||
func (_m *Store) ControllerInfo() (params.ControllerInfo, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
|
|
@ -134,6 +152,34 @@ func (_m *Store) CreateEntityPool(ctx context.Context, entity params.GithubEntit
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// CreateEntityScaleSet provides a mock function with given fields: _a0, entity, param
|
||||
func (_m *Store) CreateEntityScaleSet(_a0 context.Context, entity params.GithubEntity, param params.CreateScaleSetParams) (params.ScaleSet, error) {
|
||||
ret := _m.Called(_a0, entity, param)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for CreateEntityScaleSet")
|
||||
}
|
||||
|
||||
var r0 params.ScaleSet
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, params.GithubEntity, params.CreateScaleSetParams) (params.ScaleSet, error)); ok {
|
||||
return rf(_a0, entity, param)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, params.GithubEntity, params.CreateScaleSetParams) params.ScaleSet); ok {
|
||||
r0 = rf(_a0, entity, param)
|
||||
} else {
|
||||
r0 = ret.Get(0).(params.ScaleSet)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, params.GithubEntity, params.CreateScaleSetParams) error); ok {
|
||||
r1 = rf(_a0, entity, param)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// CreateGithubCredentials provides a mock function with given fields: ctx, param
|
||||
func (_m *Store) CreateGithubCredentials(ctx context.Context, param params.CreateGithubCredentialsParams) (params.GithubCredentials, error) {
|
||||
ret := _m.Called(ctx, param)
|
||||
|
|
@ -302,6 +348,34 @@ func (_m *Store) CreateRepository(ctx context.Context, owner string, name string
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// CreateScaleSetInstance provides a mock function with given fields: _a0, scaleSetID, param
|
||||
func (_m *Store) CreateScaleSetInstance(_a0 context.Context, scaleSetID uint, param params.CreateInstanceParams) (params.Instance, error) {
|
||||
ret := _m.Called(_a0, scaleSetID, param)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for CreateScaleSetInstance")
|
||||
}
|
||||
|
||||
var r0 params.Instance
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, uint, params.CreateInstanceParams) (params.Instance, error)); ok {
|
||||
return rf(_a0, scaleSetID, param)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, uint, params.CreateInstanceParams) params.Instance); ok {
|
||||
r0 = rf(_a0, scaleSetID, param)
|
||||
} else {
|
||||
r0 = ret.Get(0).(params.Instance)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, uint, params.CreateInstanceParams) error); ok {
|
||||
r1 = rf(_a0, scaleSetID, param)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// CreateUser provides a mock function with given fields: ctx, user
|
||||
func (_m *Store) CreateUser(ctx context.Context, user params.NewUserParams) (params.User, error) {
|
||||
ret := _m.Called(ctx, user)
|
||||
|
|
@ -438,6 +512,24 @@ func (_m *Store) DeleteInstance(ctx context.Context, poolID string, instanceName
|
|||
return r0
|
||||
}
|
||||
|
||||
// DeleteInstanceByName provides a mock function with given fields: ctx, instanceName
|
||||
func (_m *Store) DeleteInstanceByName(ctx context.Context, instanceName string) error {
|
||||
ret := _m.Called(ctx, instanceName)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for DeleteInstanceByName")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) error); ok {
|
||||
r0 = rf(ctx, instanceName)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// DeleteJob provides a mock function with given fields: ctx, jobID
|
||||
func (_m *Store) DeleteJob(ctx context.Context, jobID int64) error {
|
||||
ret := _m.Called(ctx, jobID)
|
||||
|
|
@ -510,6 +602,24 @@ func (_m *Store) DeleteRepository(ctx context.Context, repoID string) error {
|
|||
return r0
|
||||
}
|
||||
|
||||
// DeleteScaleSetByID provides a mock function with given fields: ctx, scaleSetID
|
||||
func (_m *Store) DeleteScaleSetByID(ctx context.Context, scaleSetID uint) error {
|
||||
ret := _m.Called(ctx, scaleSetID)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for DeleteScaleSetByID")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, uint) error); ok {
|
||||
r0 = rf(ctx, scaleSetID)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// FindPoolsMatchingAllTags provides a mock function with given fields: ctx, entityType, entityID, tags
|
||||
func (_m *Store) FindPoolsMatchingAllTags(ctx context.Context, entityType params.GithubEntityType, entityID string, tags []string) ([]params.Pool, error) {
|
||||
ret := _m.Called(ctx, entityType, entityID, tags)
|
||||
|
|
@ -736,6 +846,34 @@ func (_m *Store) GetGithubEndpoint(ctx context.Context, name string) (params.Git
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// GetGithubEntity provides a mock function with given fields: _a0, entityType, entityID
|
||||
func (_m *Store) GetGithubEntity(_a0 context.Context, entityType params.GithubEntityType, entityID string) (params.GithubEntity, error) {
|
||||
ret := _m.Called(_a0, entityType, entityID)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetGithubEntity")
|
||||
}
|
||||
|
||||
var r0 params.GithubEntity
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, params.GithubEntityType, string) (params.GithubEntity, error)); ok {
|
||||
return rf(_a0, entityType, entityID)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, params.GithubEntityType, string) params.GithubEntity); ok {
|
||||
r0 = rf(_a0, entityType, entityID)
|
||||
} else {
|
||||
r0 = ret.Get(0).(params.GithubEntity)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, params.GithubEntityType, string) error); ok {
|
||||
r1 = rf(_a0, entityType, entityID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetInstanceByName provides a mock function with given fields: ctx, instanceName
|
||||
func (_m *Store) GetInstanceByName(ctx context.Context, instanceName string) (params.Instance, error) {
|
||||
ret := _m.Called(ctx, instanceName)
|
||||
|
|
@ -960,6 +1098,34 @@ func (_m *Store) GetRepositoryByID(ctx context.Context, repoID string) (params.R
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// GetScaleSetByID provides a mock function with given fields: ctx, scaleSet
|
||||
func (_m *Store) GetScaleSetByID(ctx context.Context, scaleSet uint) (params.ScaleSet, error) {
|
||||
ret := _m.Called(ctx, scaleSet)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetScaleSetByID")
|
||||
}
|
||||
|
||||
var r0 params.ScaleSet
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, uint) (params.ScaleSet, error)); ok {
|
||||
return rf(ctx, scaleSet)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, uint) params.ScaleSet); ok {
|
||||
r0 = rf(ctx, scaleSet)
|
||||
} else {
|
||||
r0 = ret.Get(0).(params.ScaleSet)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, uint) error); ok {
|
||||
r1 = rf(ctx, scaleSet)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetUser provides a mock function with given fields: ctx, user
|
||||
func (_m *Store) GetUser(ctx context.Context, user string) (params.User, error) {
|
||||
ret := _m.Called(ctx, user)
|
||||
|
|
@ -1034,7 +1200,7 @@ func (_m *Store) HasAdminUser(ctx context.Context) bool {
|
|||
return r0
|
||||
}
|
||||
|
||||
// InitController provides a mock function with given fields:
|
||||
// InitController provides a mock function with no fields
|
||||
func (_m *Store) InitController() (params.ControllerInfo, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
|
|
@ -1152,6 +1318,36 @@ func (_m *Store) ListAllPools(ctx context.Context) ([]params.Pool, error) {
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// ListAllScaleSets provides a mock function with given fields: ctx
|
||||
func (_m *Store) ListAllScaleSets(ctx context.Context) ([]params.ScaleSet, error) {
|
||||
ret := _m.Called(ctx)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListAllScaleSets")
|
||||
}
|
||||
|
||||
var r0 []params.ScaleSet
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context) ([]params.ScaleSet, error)); ok {
|
||||
return rf(ctx)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context) []params.ScaleSet); ok {
|
||||
r0 = rf(ctx)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]params.ScaleSet)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context) error); ok {
|
||||
r1 = rf(ctx)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ListEnterprises provides a mock function with given fields: ctx
|
||||
func (_m *Store) ListEnterprises(ctx context.Context) ([]params.Enterprise, error) {
|
||||
ret := _m.Called(ctx)
|
||||
|
|
@ -1272,6 +1468,36 @@ func (_m *Store) ListEntityPools(ctx context.Context, entity params.GithubEntity
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// ListEntityScaleSets provides a mock function with given fields: _a0, entity
|
||||
func (_m *Store) ListEntityScaleSets(_a0 context.Context, entity params.GithubEntity) ([]params.ScaleSet, error) {
|
||||
ret := _m.Called(_a0, entity)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListEntityScaleSets")
|
||||
}
|
||||
|
||||
var r0 []params.ScaleSet
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, params.GithubEntity) ([]params.ScaleSet, error)); ok {
|
||||
return rf(_a0, entity)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, params.GithubEntity) []params.ScaleSet); ok {
|
||||
r0 = rf(_a0, entity)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]params.ScaleSet)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, params.GithubEntity) error); ok {
|
||||
r1 = rf(_a0, entity)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ListGithubCredentials provides a mock function with given fields: ctx
|
||||
func (_m *Store) ListGithubCredentials(ctx context.Context) ([]params.GithubCredentials, error) {
|
||||
ret := _m.Called(ctx)
|
||||
|
|
@ -1452,6 +1678,36 @@ func (_m *Store) ListRepositories(ctx context.Context) ([]params.Repository, err
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// ListScaleSetInstances provides a mock function with given fields: _a0, scalesetID
|
||||
func (_m *Store) ListScaleSetInstances(_a0 context.Context, scalesetID uint) ([]params.Instance, error) {
|
||||
ret := _m.Called(_a0, scalesetID)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListScaleSetInstances")
|
||||
}
|
||||
|
||||
var r0 []params.Instance
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, uint) ([]params.Instance, error)); ok {
|
||||
return rf(_a0, scalesetID)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, uint) []params.Instance); ok {
|
||||
r0 = rf(_a0, scalesetID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]params.Instance)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, uint) error); ok {
|
||||
r1 = rf(_a0, scalesetID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// LockJob provides a mock function with given fields: ctx, jobID, entityID
|
||||
func (_m *Store) LockJob(ctx context.Context, jobID int64, entityID string) error {
|
||||
ret := _m.Called(ctx, jobID, entityID)
|
||||
|
|
@ -1498,6 +1754,42 @@ func (_m *Store) PoolInstanceCount(ctx context.Context, poolID string) (int64, e
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// SetScaleSetDesiredRunnerCount provides a mock function with given fields: ctx, scaleSetID, desiredRunnerCount
|
||||
func (_m *Store) SetScaleSetDesiredRunnerCount(ctx context.Context, scaleSetID uint, desiredRunnerCount int) error {
|
||||
ret := _m.Called(ctx, scaleSetID, desiredRunnerCount)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for SetScaleSetDesiredRunnerCount")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, uint, int) error); ok {
|
||||
r0 = rf(ctx, scaleSetID, desiredRunnerCount)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// SetScaleSetLastMessageID provides a mock function with given fields: ctx, scaleSetID, lastMessageID
|
||||
func (_m *Store) SetScaleSetLastMessageID(ctx context.Context, scaleSetID uint, lastMessageID int64) error {
|
||||
ret := _m.Called(ctx, scaleSetID, lastMessageID)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for SetScaleSetLastMessageID")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, uint, int64) error); ok {
|
||||
r0 = rf(ctx, scaleSetID, lastMessageID)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// UnlockJob provides a mock function with given fields: ctx, jobID, entityID
|
||||
func (_m *Store) UnlockJob(ctx context.Context, jobID int64, entityID string) error {
|
||||
ret := _m.Called(ctx, jobID, entityID)
|
||||
|
|
@ -1600,6 +1892,34 @@ func (_m *Store) UpdateEntityPool(ctx context.Context, entity params.GithubEntit
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// UpdateEntityScaleSet provides a mock function with given fields: _a0, entity, scaleSetID, param, callback
|
||||
func (_m *Store) UpdateEntityScaleSet(_a0 context.Context, entity params.GithubEntity, scaleSetID uint, param params.UpdateScaleSetParams, callback func(params.ScaleSet, params.ScaleSet) error) (params.ScaleSet, error) {
|
||||
ret := _m.Called(_a0, entity, scaleSetID, param, callback)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for UpdateEntityScaleSet")
|
||||
}
|
||||
|
||||
var r0 params.ScaleSet
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, params.GithubEntity, uint, params.UpdateScaleSetParams, func(params.ScaleSet, params.ScaleSet) error) (params.ScaleSet, error)); ok {
|
||||
return rf(_a0, entity, scaleSetID, param, callback)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, params.GithubEntity, uint, params.UpdateScaleSetParams, func(params.ScaleSet, params.ScaleSet) error) params.ScaleSet); ok {
|
||||
r0 = rf(_a0, entity, scaleSetID, param, callback)
|
||||
} else {
|
||||
r0 = ret.Get(0).(params.ScaleSet)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, params.GithubEntity, uint, params.UpdateScaleSetParams, func(params.ScaleSet, params.ScaleSet) error) error); ok {
|
||||
r1 = rf(_a0, entity, scaleSetID, param, callback)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// UpdateGithubCredentials provides a mock function with given fields: ctx, id, param
|
||||
func (_m *Store) UpdateGithubCredentials(ctx context.Context, id uint, param params.UpdateGithubCredentialsParams) (params.GithubCredentials, error) {
|
||||
ret := _m.Called(ctx, id, param)
|
||||
|
|
|
|||
|
|
@ -92,6 +92,7 @@ type UserStore interface {
|
|||
type InstanceStore interface {
|
||||
CreateInstance(ctx context.Context, poolID string, param params.CreateInstanceParams) (params.Instance, error)
|
||||
DeleteInstance(ctx context.Context, poolID string, instanceName string) error
|
||||
DeleteInstanceByName(ctx context.Context, instanceName string) error
|
||||
UpdateInstance(ctx context.Context, instanceName string, param params.UpdateInstanceParams) (params.Instance, error)
|
||||
|
||||
// Probably a bad idea without some king of filter or at least pagination
|
||||
|
|
@ -135,6 +136,22 @@ type ControllerStore interface {
|
|||
UpdateController(info params.UpdateControllerParams) (params.ControllerInfo, error)
|
||||
}
|
||||
|
||||
type ScaleSetsStore interface {
|
||||
ListAllScaleSets(ctx context.Context) ([]params.ScaleSet, error)
|
||||
CreateEntityScaleSet(_ context.Context, entity params.GithubEntity, param params.CreateScaleSetParams) (scaleSet params.ScaleSet, err error)
|
||||
ListEntityScaleSets(_ context.Context, entity params.GithubEntity) ([]params.ScaleSet, error)
|
||||
UpdateEntityScaleSet(_ context.Context, entity params.GithubEntity, scaleSetID uint, param params.UpdateScaleSetParams, callback func(old, newSet params.ScaleSet) error) (updatedScaleSet params.ScaleSet, err error)
|
||||
GetScaleSetByID(ctx context.Context, scaleSet uint) (params.ScaleSet, error)
|
||||
DeleteScaleSetByID(ctx context.Context, scaleSetID uint) (err error)
|
||||
SetScaleSetLastMessageID(ctx context.Context, scaleSetID uint, lastMessageID int64) error
|
||||
SetScaleSetDesiredRunnerCount(ctx context.Context, scaleSetID uint, desiredRunnerCount int) error
|
||||
}
|
||||
|
||||
type ScaleSetInstanceStore interface {
|
||||
ListScaleSetInstances(_ context.Context, scalesetID uint) ([]params.Instance, error)
|
||||
CreateScaleSetInstance(_ context.Context, scaleSetID uint, param params.CreateInstanceParams) (instance params.Instance, err error)
|
||||
}
|
||||
|
||||
//go:generate mockery --name=Store
|
||||
type Store interface {
|
||||
RepoStore
|
||||
|
|
@ -148,7 +165,11 @@ type Store interface {
|
|||
GithubCredentialsStore
|
||||
ControllerStore
|
||||
EntityPoolStore
|
||||
ScaleSetsStore
|
||||
ScaleSetInstanceStore
|
||||
|
||||
ControllerInfo() (params.ControllerInfo, error)
|
||||
InitController() (params.ControllerInfo, error)
|
||||
GetGithubEntity(_ context.Context, entityType params.GithubEntityType, entityID string) (params.GithubEntity, error)
|
||||
AddEntityEvent(ctx context.Context, entity params.GithubEntity, event params.EventType, eventLevel params.EventLevel, statusMessage string, maxEvents int) error
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ const (
|
|||
ControllerEntityType DatabaseEntityType = "controller"
|
||||
GithubCredentialsEntityType DatabaseEntityType = "github_credentials" // #nosec G101
|
||||
GithubEndpointEntityType DatabaseEntityType = "github_endpoint"
|
||||
ScaleSetEntityType DatabaseEntityType = "scaleset"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
|||
|
|
@ -69,6 +69,5 @@ func (s *CtrlTestSuite) TestInitControllerAlreadyInitialized() {
|
|||
}
|
||||
|
||||
func TestCtrlTestSuite(t *testing.T) {
|
||||
t.Parallel()
|
||||
suite.Run(t, new(CtrlTestSuite))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ func (s *sqlDatabase) GetEnterprise(ctx context.Context, name, endpointName stri
|
|||
}
|
||||
|
||||
func (s *sqlDatabase) GetEnterpriseByID(ctx context.Context, enterpriseID string) (params.Enterprise, error) {
|
||||
enterprise, err := s.getEnterpriseByID(ctx, s.conn, enterpriseID, "Pools", "Credentials", "Endpoint")
|
||||
enterprise, err := s.getEnterpriseByID(ctx, s.conn, enterpriseID, "Pools", "Credentials", "Endpoint", "Credentials.Endpoint")
|
||||
if err != nil {
|
||||
return params.Enterprise{}, errors.Wrap(err, "fetching enterprise")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -782,6 +782,5 @@ func (s *EnterpriseTestSuite) TestUpdateEnterprisePoolInvalidEnterpriseID() {
|
|||
}
|
||||
|
||||
func TestEnterpriseTestSuite(t *testing.T) {
|
||||
t.Parallel()
|
||||
suite.Run(t, new(EnterpriseTestSuite))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -738,7 +738,6 @@ func (s *GithubTestSuite) TestAdminUserCanUpdateAnyGithubCredentials() {
|
|||
}
|
||||
|
||||
func TestGithubTestSuite(t *testing.T) {
|
||||
t.Parallel()
|
||||
suite.Run(t, new(GithubTestSuite))
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -97,6 +97,8 @@ func (s *sqlDatabase) getPoolInstanceByName(poolID string, instanceName string)
|
|||
}
|
||||
return Instance{}, errors.Wrap(q.Error, "fetching pool instance by name")
|
||||
}
|
||||
|
||||
instance.Pool = pool
|
||||
return instance, nil
|
||||
}
|
||||
|
||||
|
|
@ -134,7 +136,7 @@ func (s *sqlDatabase) GetPoolInstanceByName(_ context.Context, poolID string, in
|
|||
}
|
||||
|
||||
func (s *sqlDatabase) GetInstanceByName(ctx context.Context, instanceName string) (params.Instance, error) {
|
||||
instance, err := s.getInstanceByName(ctx, instanceName, "StatusMessages")
|
||||
instance, err := s.getInstanceByName(ctx, instanceName, "StatusMessages", "Pool", "ScaleSet")
|
||||
if err != nil {
|
||||
return params.Instance{}, errors.Wrap(err, "fetching instance")
|
||||
}
|
||||
|
|
@ -145,6 +147,9 @@ func (s *sqlDatabase) GetInstanceByName(ctx context.Context, instanceName string
|
|||
func (s *sqlDatabase) DeleteInstance(_ context.Context, poolID string, instanceName string) (err error) {
|
||||
instance, err := s.getPoolInstanceByName(poolID, instanceName)
|
||||
if err != nil {
|
||||
if errors.Is(err, runnerErrors.ErrNotFound) {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "deleting instance")
|
||||
}
|
||||
|
||||
|
|
@ -154,13 +159,62 @@ func (s *sqlDatabase) DeleteInstance(_ context.Context, poolID string, instanceN
|
|||
if instance.ProviderID != nil {
|
||||
providerID = *instance.ProviderID
|
||||
}
|
||||
if notifyErr := s.sendNotify(common.InstanceEntityType, common.DeleteOperation, params.Instance{
|
||||
instanceNotif := params.Instance{
|
||||
ID: instance.ID.String(),
|
||||
Name: instance.Name,
|
||||
ProviderID: providerID,
|
||||
AgentID: instance.AgentID,
|
||||
PoolID: instance.PoolID.String(),
|
||||
}); notifyErr != nil {
|
||||
}
|
||||
switch {
|
||||
case instance.PoolID != nil:
|
||||
instanceNotif.PoolID = instance.PoolID.String()
|
||||
case instance.ScaleSetFkID != nil:
|
||||
instanceNotif.ScaleSetID = *instance.ScaleSetFkID
|
||||
}
|
||||
|
||||
if notifyErr := s.sendNotify(common.InstanceEntityType, common.DeleteOperation, instanceNotif); notifyErr != nil {
|
||||
slog.With(slog.Any("error", notifyErr)).Error("failed to send notify")
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
||||
if q := s.conn.Unscoped().Delete(&instance); q.Error != nil {
|
||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(q.Error, "deleting instance")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) DeleteInstanceByName(ctx context.Context, instanceName string) error {
|
||||
instance, err := s.getInstanceByName(ctx, instanceName, "Pool", "ScaleSet")
|
||||
if err != nil {
|
||||
if errors.Is(err, runnerErrors.ErrNotFound) {
|
||||
return nil
|
||||
}
|
||||
return errors.Wrap(err, "deleting instance")
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err == nil {
|
||||
var providerID string
|
||||
if instance.ProviderID != nil {
|
||||
providerID = *instance.ProviderID
|
||||
}
|
||||
payload := params.Instance{
|
||||
ID: instance.ID.String(),
|
||||
Name: instance.Name,
|
||||
ProviderID: providerID,
|
||||
AgentID: instance.AgentID,
|
||||
}
|
||||
if instance.PoolID != nil {
|
||||
payload.PoolID = instance.PoolID.String()
|
||||
}
|
||||
if instance.ScaleSetFkID != nil {
|
||||
payload.ScaleSetID = *instance.ScaleSetFkID
|
||||
}
|
||||
if notifyErr := s.sendNotify(common.InstanceEntityType, common.DeleteOperation, payload); notifyErr != nil {
|
||||
slog.With(slog.Any("error", notifyErr)).Error("failed to send notify")
|
||||
}
|
||||
}
|
||||
|
|
@ -194,7 +248,7 @@ func (s *sqlDatabase) AddInstanceEvent(ctx context.Context, instanceName string,
|
|||
}
|
||||
|
||||
func (s *sqlDatabase) UpdateInstance(ctx context.Context, instanceName string, param params.UpdateInstanceParams) (params.Instance, error) {
|
||||
instance, err := s.getInstanceByName(ctx, instanceName)
|
||||
instance, err := s.getInstanceByName(ctx, instanceName, "Pool", "ScaleSet")
|
||||
if err != nil {
|
||||
return params.Instance{}, errors.Wrap(err, "updating instance")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -119,6 +119,12 @@ func (s *InstancesTestSuite) SetupTest() {
|
|||
CallbackURL: "https://garm.example.com/",
|
||||
Status: commonParams.InstanceRunning,
|
||||
RunnerStatus: params.RunnerIdle,
|
||||
JitConfiguration: map[string]string{
|
||||
"secret": fmt.Sprintf("secret-%d", i),
|
||||
},
|
||||
AditionalLabels: []string{
|
||||
fmt.Sprintf("label-%d", i),
|
||||
},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
|
|
@ -277,6 +283,23 @@ func (s *InstancesTestSuite) TestDeleteInstance() {
|
|||
|
||||
_, err = s.Store.GetPoolInstanceByName(s.adminCtx, s.Fixtures.Pool.ID, storeInstance.Name)
|
||||
s.Require().Equal("fetching instance: fetching pool instance by name: not found", err.Error())
|
||||
|
||||
err = s.Store.DeleteInstance(s.adminCtx, s.Fixtures.Pool.ID, storeInstance.Name)
|
||||
s.Require().Nil(err)
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestDeleteInstanceByName() {
|
||||
storeInstance := s.Fixtures.Instances[0]
|
||||
|
||||
err := s.Store.DeleteInstanceByName(s.adminCtx, storeInstance.Name)
|
||||
|
||||
s.Require().Nil(err)
|
||||
|
||||
_, err = s.Store.GetPoolInstanceByName(s.adminCtx, s.Fixtures.Pool.ID, storeInstance.Name)
|
||||
s.Require().Equal("fetching instance: fetching pool instance by name: not found", err.Error())
|
||||
|
||||
err = s.Store.DeleteInstanceByName(s.adminCtx, storeInstance.Name)
|
||||
s.Require().Nil(err)
|
||||
}
|
||||
|
||||
func (s *InstancesTestSuite) TestDeleteInstanceInvalidPoolID() {
|
||||
|
|
@ -568,6 +591,5 @@ func (s *InstancesTestSuite) TestPoolInstanceCountDBCountErr() {
|
|||
}
|
||||
|
||||
func TestInstTestSuite(t *testing.T) {
|
||||
t.Parallel()
|
||||
suite.Run(t, new(InstancesTestSuite))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,6 +86,69 @@ type Pool struct {
|
|||
Priority uint `gorm:"index:idx_pool_priority"`
|
||||
}
|
||||
|
||||
// ScaleSet represents a github scale set. Scale sets are almost identical to pools with a few
|
||||
// notable exceptions:
|
||||
// - Labels are no longer relevant
|
||||
// - Workflows will use the scaleset name to target runners.
|
||||
// - A scale set is a stand alone unit. If a workflow targets a scale set, no other runner will pick up that job.
|
||||
type ScaleSet struct {
|
||||
gorm.Model
|
||||
|
||||
// ScaleSetID is the github ID of the scale set. This field may not be set if
|
||||
// the scale set was ceated in GARM but has not yet been created in GitHub.
|
||||
// The scale set ID is also not globally unique. It is only unique within the context
|
||||
// of an entity.
|
||||
ScaleSetID int `gorm:"index:idx_scale_set"`
|
||||
Name string `gorm:"unique_index:idx_name"`
|
||||
GitHubRunnerGroup string `gorm:"unique_index:idx_name"`
|
||||
DisableUpdate bool
|
||||
|
||||
// State stores the provisioning state of the scale set in GitHub
|
||||
State params.ScaleSetState
|
||||
// ExtendedState stores a more detailed message regarding the State.
|
||||
// If an error occurs, the reason for the error will be stored here.
|
||||
ExtendedState string
|
||||
|
||||
ProviderName string
|
||||
RunnerPrefix string
|
||||
MaxRunners uint
|
||||
MinIdleRunners uint
|
||||
RunnerBootstrapTimeout uint
|
||||
Image string
|
||||
Flavor string
|
||||
OSType commonParams.OSType
|
||||
OSArch commonParams.OSArch
|
||||
Enabled bool
|
||||
LastMessageID int64
|
||||
DesiredRunnerCount int
|
||||
// ExtraSpecs is an opaque json that gets sent to the provider
|
||||
// as part of the bootstrap params for instances. It can contain
|
||||
// any kind of data needed by providers.
|
||||
ExtraSpecs datatypes.JSON
|
||||
|
||||
RepoID *uuid.UUID `gorm:"index"`
|
||||
Repository Repository `gorm:"foreignKey:RepoID;"`
|
||||
|
||||
OrgID *uuid.UUID `gorm:"index"`
|
||||
Organization Organization `gorm:"foreignKey:OrgID"`
|
||||
|
||||
EnterpriseID *uuid.UUID `gorm:"index"`
|
||||
Enterprise Enterprise `gorm:"foreignKey:EnterpriseID"`
|
||||
|
||||
Instances []Instance `gorm:"foreignKey:ScaleSetFkID"`
|
||||
}
|
||||
|
||||
type RepositoryEvent struct {
|
||||
gorm.Model
|
||||
|
||||
EventType params.EventType
|
||||
EventLevel params.EventLevel
|
||||
Message string `gorm:"type:text"`
|
||||
|
||||
RepoID uuid.UUID `gorm:"index:idx_repo_event"`
|
||||
Repo Repository `gorm:"foreignKey:RepoID"`
|
||||
}
|
||||
|
||||
type Repository struct {
|
||||
Base
|
||||
|
||||
|
|
@ -98,13 +161,26 @@ type Repository struct {
|
|||
Name string `gorm:"index:idx_owner_nocase,unique,collate:nocase"`
|
||||
WebhookSecret []byte
|
||||
Pools []Pool `gorm:"foreignKey:RepoID"`
|
||||
ScaleSets []ScaleSet `gorm:"foreignKey:RepoID"`
|
||||
Jobs []WorkflowJob `gorm:"foreignKey:RepoID;constraint:OnDelete:SET NULL"`
|
||||
PoolBalancerType params.PoolBalancerType `gorm:"type:varchar(64)"`
|
||||
|
||||
EndpointName *string `gorm:"index:idx_owner_nocase,unique,collate:nocase"`
|
||||
Endpoint GithubEndpoint `gorm:"foreignKey:EndpointName;constraint:OnDelete:SET NULL"`
|
||||
|
||||
Events []RepositoryEvent `gorm:"foreignKey:RepoID;constraint:OnDelete:CASCADE,OnUpdate:CASCADE;"`
|
||||
}
|
||||
|
||||
type OrganizationEvent struct {
|
||||
gorm.Model
|
||||
|
||||
EventType params.EventType
|
||||
EventLevel params.EventLevel
|
||||
Message string `gorm:"type:text"`
|
||||
|
||||
OrgID uuid.UUID `gorm:"index:idx_org_event"`
|
||||
Org Organization `gorm:"foreignKey:OrgID"`
|
||||
}
|
||||
type Organization struct {
|
||||
Base
|
||||
|
||||
|
|
@ -116,11 +192,25 @@ type Organization struct {
|
|||
Name string `gorm:"index:idx_org_name_nocase,collate:nocase"`
|
||||
WebhookSecret []byte
|
||||
Pools []Pool `gorm:"foreignKey:OrgID"`
|
||||
ScaleSet []ScaleSet `gorm:"foreignKey:OrgID"`
|
||||
Jobs []WorkflowJob `gorm:"foreignKey:OrgID;constraint:OnDelete:SET NULL"`
|
||||
PoolBalancerType params.PoolBalancerType `gorm:"type:varchar(64)"`
|
||||
|
||||
EndpointName *string `gorm:"index:idx_org_name_nocase,collate:nocase"`
|
||||
Endpoint GithubEndpoint `gorm:"foreignKey:EndpointName;constraint:OnDelete:SET NULL"`
|
||||
|
||||
Events []OrganizationEvent `gorm:"foreignKey:OrgID;constraint:OnDelete:CASCADE,OnUpdate:CASCADE;"`
|
||||
}
|
||||
|
||||
type EnterpriseEvent struct {
|
||||
gorm.Model
|
||||
|
||||
EventType params.EventType
|
||||
EventLevel params.EventLevel
|
||||
Message string `gorm:"type:text"`
|
||||
|
||||
EnterpriseID uuid.UUID `gorm:"index:idx_enterprise_event"`
|
||||
Enterprise Enterprise `gorm:"foreignKey:EnterpriseID"`
|
||||
}
|
||||
|
||||
type Enterprise struct {
|
||||
|
|
@ -134,11 +224,14 @@ type Enterprise struct {
|
|||
Name string `gorm:"index:idx_ent_name_nocase,collate:nocase"`
|
||||
WebhookSecret []byte
|
||||
Pools []Pool `gorm:"foreignKey:EnterpriseID"`
|
||||
ScaleSet []ScaleSet `gorm:"foreignKey:EnterpriseID"`
|
||||
Jobs []WorkflowJob `gorm:"foreignKey:EnterpriseID;constraint:OnDelete:SET NULL"`
|
||||
PoolBalancerType params.PoolBalancerType `gorm:"type:varchar(64)"`
|
||||
|
||||
EndpointName *string `gorm:"index:idx_ent_name_nocase,collate:nocase"`
|
||||
Endpoint GithubEndpoint `gorm:"foreignKey:EndpointName;constraint:OnDelete:SET NULL"`
|
||||
|
||||
Events []EnterpriseEvent `gorm:"foreignKey:EnterpriseID;constraint:OnDelete:CASCADE,OnUpdate:CASCADE;"`
|
||||
}
|
||||
|
||||
type Address struct {
|
||||
|
|
@ -184,9 +277,12 @@ type Instance struct {
|
|||
GitHubRunnerGroup string
|
||||
AditionalLabels datatypes.JSON
|
||||
|
||||
PoolID uuid.UUID
|
||||
PoolID *uuid.UUID
|
||||
Pool Pool `gorm:"foreignKey:PoolID"`
|
||||
|
||||
ScaleSetFkID *uint
|
||||
ScaleSet ScaleSet `gorm:"foreignKey:ScaleSetFkID"`
|
||||
|
||||
StatusMessages []InstanceStatusUpdate `gorm:"foreignKey:InstanceID;constraint:OnDelete:CASCADE,OnUpdate:CASCADE;"`
|
||||
|
||||
Job *WorkflowJob `gorm:"foreignKey:InstanceID;constraint:OnDelete:CASCADE,OnUpdate:CASCADE;"`
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ func (s *sqlDatabase) UpdateOrganization(ctx context.Context, orgID string, para
|
|||
}
|
||||
|
||||
func (s *sqlDatabase) GetOrganizationByID(ctx context.Context, orgID string) (params.Organization, error) {
|
||||
org, err := s.getOrgByID(ctx, s.conn, orgID, "Pools", "Credentials", "Endpoint")
|
||||
org, err := s.getOrgByID(ctx, s.conn, orgID, "Pools", "Credentials", "Endpoint", "Credentials.Endpoint")
|
||||
if err != nil {
|
||||
return params.Organization{}, errors.Wrap(err, "fetching org")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -787,6 +787,5 @@ func (s *OrgTestSuite) TestUpdateOrganizationPoolInvalidOrgID() {
|
|||
}
|
||||
|
||||
func TestOrgTestSuite(t *testing.T) {
|
||||
t.Parallel()
|
||||
suite.Run(t, new(OrgTestSuite))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -101,13 +101,13 @@ func (s *sqlDatabase) getEntityPool(tx *gorm.DB, entityType params.GithubEntityT
|
|||
switch entityType {
|
||||
case params.GithubEntityTypeRepository:
|
||||
fieldName = entityTypeRepoName
|
||||
entityField = "Repository"
|
||||
entityField = repositoryFieldName
|
||||
case params.GithubEntityTypeOrganization:
|
||||
fieldName = entityTypeOrgName
|
||||
entityField = "Organization"
|
||||
entityField = organizationFieldName
|
||||
case params.GithubEntityTypeEnterprise:
|
||||
fieldName = entityTypeEnterpriseName
|
||||
entityField = "Enterprise"
|
||||
entityField = enterpriseFieldName
|
||||
default:
|
||||
return Pool{}, fmt.Errorf("invalid entityType: %v", entityType)
|
||||
}
|
||||
|
|
@ -427,7 +427,10 @@ func (s *sqlDatabase) ListEntityInstances(_ context.Context, entity params.Githu
|
|||
}
|
||||
ret := []params.Instance{}
|
||||
for _, pool := range pools {
|
||||
for _, instance := range pool.Instances {
|
||||
instances := pool.Instances
|
||||
pool.Instances = nil
|
||||
for _, instance := range instances {
|
||||
instance.Pool = pool
|
||||
paramsInstance, err := s.sqlToParamsInstance(instance)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching instance")
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ package sql
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"regexp"
|
||||
|
|
@ -27,7 +28,9 @@ import (
|
|||
"gorm.io/gorm"
|
||||
"gorm.io/gorm/logger"
|
||||
|
||||
commonParams "github.com/cloudbase/garm-provider-common/params"
|
||||
dbCommon "github.com/cloudbase/garm/database/common"
|
||||
"github.com/cloudbase/garm/database/watcher"
|
||||
garmTesting "github.com/cloudbase/garm/internal/testing"
|
||||
"github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
|
@ -40,7 +43,9 @@ type PoolsTestFixtures struct {
|
|||
|
||||
type PoolsTestSuite struct {
|
||||
suite.Suite
|
||||
Store dbCommon.Store
|
||||
Store dbCommon.Store
|
||||
ctx context.Context
|
||||
|
||||
StoreSQLMocked *sqlDatabase
|
||||
Fixtures *PoolsTestFixtures
|
||||
adminCtx context.Context
|
||||
|
|
@ -53,13 +58,21 @@ func (s *PoolsTestSuite) assertSQLMockExpectations() {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *PoolsTestSuite) TearDownTest() {
|
||||
watcher.CloseWatcher()
|
||||
}
|
||||
|
||||
func (s *PoolsTestSuite) SetupTest() {
|
||||
// create testing sqlite database
|
||||
ctx := context.Background()
|
||||
watcher.InitWatcher(ctx)
|
||||
|
||||
db, err := NewSQLDatabase(context.Background(), garmTesting.GetTestSqliteDBConfig(s.T()))
|
||||
if err != nil {
|
||||
s.FailNow(fmt.Sprintf("failed to create db connection: %s", err))
|
||||
}
|
||||
s.Store = db
|
||||
s.ctx = garmTesting.ImpersonateAdminContext(ctx, s.Store, s.T())
|
||||
|
||||
adminCtx := garmTesting.ImpersonateAdminContext(context.Background(), db, s.T())
|
||||
s.adminCtx = adminCtx
|
||||
|
|
@ -194,7 +207,132 @@ func (s *PoolsTestSuite) TestDeletePoolByIDDBRemoveErr() {
|
|||
s.Require().Equal("removing pool: mocked removing pool error", err.Error())
|
||||
}
|
||||
|
||||
func (s *PoolsTestSuite) TestEntityPoolOperations() {
|
||||
ep := garmTesting.CreateDefaultGithubEndpoint(s.ctx, s.Store, s.T())
|
||||
creds := garmTesting.CreateTestGithubCredentials(s.ctx, "test-creds", s.Store, s.T(), ep)
|
||||
s.T().Cleanup(func() { s.Store.DeleteGithubCredentials(s.ctx, creds.ID) })
|
||||
repo, err := s.Store.CreateRepository(s.ctx, "test-owner", "test-repo", creds.Name, "test-secret", params.PoolBalancerTypeRoundRobin)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotEmpty(repo.ID)
|
||||
s.T().Cleanup(func() { s.Store.DeleteRepository(s.ctx, repo.ID) })
|
||||
|
||||
entity, err := repo.GetEntity()
|
||||
s.Require().NoError(err)
|
||||
|
||||
createPoolParams := params.CreatePoolParams{
|
||||
ProviderName: "test-provider",
|
||||
Image: "test-image",
|
||||
Flavor: "test-flavor",
|
||||
OSType: commonParams.Linux,
|
||||
OSArch: commonParams.Amd64,
|
||||
Tags: []string{"test-tag"},
|
||||
}
|
||||
|
||||
pool, err := s.Store.CreateEntityPool(s.ctx, entity, createPoolParams)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotEmpty(pool.ID)
|
||||
s.T().Cleanup(func() { s.Store.DeleteEntityPool(s.ctx, entity, pool.ID) })
|
||||
|
||||
entityPool, err := s.Store.GetEntityPool(s.ctx, entity, pool.ID)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(pool.ID, entityPool.ID)
|
||||
s.Require().Equal(pool.ProviderName, entityPool.ProviderName)
|
||||
|
||||
updatePoolParams := params.UpdatePoolParams{
|
||||
Enabled: garmTesting.Ptr(true),
|
||||
Flavor: "new-flavor",
|
||||
Image: "new-image",
|
||||
RunnerPrefix: params.RunnerPrefix{
|
||||
Prefix: "new-prefix",
|
||||
},
|
||||
MaxRunners: garmTesting.Ptr(uint(100)),
|
||||
MinIdleRunners: garmTesting.Ptr(uint(50)),
|
||||
OSType: commonParams.Windows,
|
||||
OSArch: commonParams.Amd64,
|
||||
Tags: []string{"new-tag"},
|
||||
RunnerBootstrapTimeout: garmTesting.Ptr(uint(10)),
|
||||
ExtraSpecs: json.RawMessage(`{"extra": "specs"}`),
|
||||
GitHubRunnerGroup: garmTesting.Ptr("new-group"),
|
||||
Priority: garmTesting.Ptr(uint(1)),
|
||||
}
|
||||
pool, err = s.Store.UpdateEntityPool(s.ctx, entity, pool.ID, updatePoolParams)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Equal(*updatePoolParams.Enabled, pool.Enabled)
|
||||
s.Require().Equal(updatePoolParams.Flavor, pool.Flavor)
|
||||
s.Require().Equal(updatePoolParams.Image, pool.Image)
|
||||
s.Require().Equal(updatePoolParams.RunnerPrefix.Prefix, pool.RunnerPrefix.Prefix)
|
||||
s.Require().Equal(*updatePoolParams.MaxRunners, pool.MaxRunners)
|
||||
s.Require().Equal(*updatePoolParams.MinIdleRunners, pool.MinIdleRunners)
|
||||
s.Require().Equal(updatePoolParams.OSType, pool.OSType)
|
||||
s.Require().Equal(updatePoolParams.OSArch, pool.OSArch)
|
||||
s.Require().Equal(*updatePoolParams.RunnerBootstrapTimeout, pool.RunnerBootstrapTimeout)
|
||||
s.Require().Equal(updatePoolParams.ExtraSpecs, pool.ExtraSpecs)
|
||||
s.Require().Equal(*updatePoolParams.GitHubRunnerGroup, pool.GitHubRunnerGroup)
|
||||
s.Require().Equal(*updatePoolParams.Priority, pool.Priority)
|
||||
|
||||
entityPools, err := s.Store.ListEntityPools(s.ctx, entity)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(entityPools, 1)
|
||||
s.Require().Equal(pool.ID, entityPools[0].ID)
|
||||
|
||||
tagsToMatch := []string{"new-tag"}
|
||||
pools, err := s.Store.FindPoolsMatchingAllTags(s.ctx, entity.EntityType, entity.ID, tagsToMatch)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(pools, 1)
|
||||
s.Require().Equal(pool.ID, pools[0].ID)
|
||||
|
||||
invalidTagsToMatch := []string{"invalid-tag"}
|
||||
pools, err = s.Store.FindPoolsMatchingAllTags(s.ctx, entity.EntityType, entity.ID, invalidTagsToMatch)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(pools, 0)
|
||||
}
|
||||
|
||||
func (s *PoolsTestSuite) TestListEntityInstances() {
|
||||
ep := garmTesting.CreateDefaultGithubEndpoint(s.ctx, s.Store, s.T())
|
||||
creds := garmTesting.CreateTestGithubCredentials(s.ctx, "test-creds", s.Store, s.T(), ep)
|
||||
s.T().Cleanup(func() { s.Store.DeleteGithubCredentials(s.ctx, creds.ID) })
|
||||
repo, err := s.Store.CreateRepository(s.ctx, "test-owner", "test-repo", creds.Name, "test-secret", params.PoolBalancerTypeRoundRobin)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotEmpty(repo.ID)
|
||||
s.T().Cleanup(func() { s.Store.DeleteRepository(s.ctx, repo.ID) })
|
||||
|
||||
entity, err := repo.GetEntity()
|
||||
s.Require().NoError(err)
|
||||
|
||||
createPoolParams := params.CreatePoolParams{
|
||||
ProviderName: "test-provider",
|
||||
Image: "test-image",
|
||||
Flavor: "test-flavor",
|
||||
OSType: commonParams.Linux,
|
||||
OSArch: commonParams.Amd64,
|
||||
Tags: []string{"test-tag"},
|
||||
}
|
||||
|
||||
pool, err := s.Store.CreateEntityPool(s.ctx, entity, createPoolParams)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotEmpty(pool.ID)
|
||||
s.T().Cleanup(func() { s.Store.DeleteEntityPool(s.ctx, entity, pool.ID) })
|
||||
|
||||
createInstanceParams := params.CreateInstanceParams{
|
||||
Name: "test-instance",
|
||||
OSType: commonParams.Linux,
|
||||
OSArch: commonParams.Amd64,
|
||||
Status: commonParams.InstanceCreating,
|
||||
}
|
||||
instance, err := s.Store.CreateInstance(s.ctx, pool.ID, createInstanceParams)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotEmpty(instance.ID)
|
||||
|
||||
s.T().Cleanup(func() { s.Store.DeleteInstance(s.ctx, pool.ID, instance.ID) })
|
||||
|
||||
instances, err := s.Store.ListEntityInstances(s.ctx, entity)
|
||||
s.Require().NoError(err)
|
||||
s.Require().Len(instances, 1)
|
||||
s.Require().Equal(instance.ID, instances[0].ID)
|
||||
s.Require().Equal(instance.Name, instances[0].Name)
|
||||
s.Require().Equal(instance.ProviderName, pool.ProviderName)
|
||||
}
|
||||
|
||||
func TestPoolsTestSuite(t *testing.T) {
|
||||
t.Parallel()
|
||||
suite.Run(t, new(PoolsTestSuite))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -216,7 +216,7 @@ func (s *sqlDatabase) UpdateRepository(ctx context.Context, repoID string, param
|
|||
}
|
||||
|
||||
func (s *sqlDatabase) GetRepositoryByID(ctx context.Context, repoID string) (params.Repository, error) {
|
||||
repo, err := s.getRepoByID(ctx, s.conn, repoID, "Pools", "Credentials", "Endpoint")
|
||||
repo, err := s.getRepoByID(ctx, s.conn, repoID, "Pools", "Credentials", "Endpoint", "Credentials.Endpoint")
|
||||
if err != nil {
|
||||
return params.Repository{}, errors.Wrap(err, "fetching repo")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -94,6 +94,9 @@ func (s *RepoTestSuite) assertSQLMockExpectations() {
|
|||
|
||||
func (s *RepoTestSuite) SetupTest() {
|
||||
// create testing sqlite database
|
||||
ctx := context.Background()
|
||||
watcher.InitWatcher(ctx)
|
||||
|
||||
db, err := NewSQLDatabase(context.Background(), garmTesting.GetTestSqliteDBConfig(s.T()))
|
||||
if err != nil {
|
||||
s.FailNow(fmt.Sprintf("failed to create db connection: %s", err))
|
||||
|
|
@ -191,6 +194,10 @@ func (s *RepoTestSuite) SetupTest() {
|
|||
s.Fixtures = fixtures
|
||||
}
|
||||
|
||||
func (s *RepoTestSuite) TearDownTest() {
|
||||
watcher.CloseWatcher()
|
||||
}
|
||||
|
||||
func (s *RepoTestSuite) TestCreateRepository() {
|
||||
// call tested function
|
||||
repo, err := s.Store.CreateRepository(
|
||||
|
|
@ -831,7 +838,5 @@ func (s *RepoTestSuite) TestUpdateRepositoryPoolInvalidRepoID() {
|
|||
}
|
||||
|
||||
func TestRepoTestSuite(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
suite.Run(t, new(RepoTestSuite))
|
||||
}
|
||||
|
|
|
|||
70
database/sql/scaleset_instances.go
Normal file
70
database/sql/scaleset_instances.go
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
package sql
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/cloudbase/garm/database/common"
|
||||
"github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
func (s *sqlDatabase) CreateScaleSetInstance(_ context.Context, scaleSetID uint, param params.CreateInstanceParams) (instance params.Instance, err error) {
|
||||
scaleSet, err := s.getScaleSetByID(s.conn, scaleSetID)
|
||||
if err != nil {
|
||||
return params.Instance{}, errors.Wrap(err, "fetching scale set")
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err == nil {
|
||||
s.sendNotify(common.InstanceEntityType, common.CreateOperation, instance)
|
||||
}
|
||||
}()
|
||||
|
||||
var secret []byte
|
||||
if len(param.JitConfiguration) > 0 {
|
||||
secret, err = s.marshalAndSeal(param.JitConfiguration)
|
||||
if err != nil {
|
||||
return params.Instance{}, errors.Wrap(err, "marshalling jit config")
|
||||
}
|
||||
}
|
||||
|
||||
newInstance := Instance{
|
||||
ScaleSet: scaleSet,
|
||||
Name: param.Name,
|
||||
Status: param.Status,
|
||||
RunnerStatus: param.RunnerStatus,
|
||||
OSType: param.OSType,
|
||||
OSArch: param.OSArch,
|
||||
CallbackURL: param.CallbackURL,
|
||||
MetadataURL: param.MetadataURL,
|
||||
GitHubRunnerGroup: param.GitHubRunnerGroup,
|
||||
JitConfiguration: secret,
|
||||
AgentID: param.AgentID,
|
||||
}
|
||||
q := s.conn.Create(&newInstance)
|
||||
if q.Error != nil {
|
||||
return params.Instance{}, errors.Wrap(q.Error, "creating instance")
|
||||
}
|
||||
|
||||
return s.sqlToParamsInstance(newInstance)
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) ListScaleSetInstances(_ context.Context, scalesetID uint) ([]params.Instance, error) {
|
||||
var instances []Instance
|
||||
query := s.conn.Model(&Instance{}).Preload("Job").Where("scale_set_fk_id = ?", scalesetID)
|
||||
|
||||
if err := query.Find(&instances); err.Error != nil {
|
||||
return nil, errors.Wrap(err.Error, "fetching instances")
|
||||
}
|
||||
|
||||
var err error
|
||||
ret := make([]params.Instance, len(instances))
|
||||
for idx, inst := range instances {
|
||||
ret[idx], err = s.sqlToParamsInstance(inst)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "converting instance")
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
436
database/sql/scalesets.go
Normal file
436
database/sql/scalesets.go
Normal file
|
|
@ -0,0 +1,436 @@
|
|||
// Copyright 2024 Cloudbase Solutions SRL
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package sql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"gorm.io/datatypes"
|
||||
"gorm.io/gorm"
|
||||
|
||||
runnerErrors "github.com/cloudbase/garm-provider-common/errors"
|
||||
"github.com/cloudbase/garm/database/common"
|
||||
"github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
func (s *sqlDatabase) ListAllScaleSets(_ context.Context) ([]params.ScaleSet, error) {
|
||||
var scaleSets []ScaleSet
|
||||
|
||||
q := s.conn.Model(&ScaleSet{}).
|
||||
Preload("Organization").
|
||||
Preload("Repository").
|
||||
Preload("Enterprise").
|
||||
Omit("extra_specs").
|
||||
Omit("status_messages").
|
||||
Find(&scaleSets)
|
||||
if q.Error != nil {
|
||||
return nil, errors.Wrap(q.Error, "fetching all scale sets")
|
||||
}
|
||||
|
||||
ret := make([]params.ScaleSet, len(scaleSets))
|
||||
var err error
|
||||
for idx, val := range scaleSets {
|
||||
ret[idx], err = s.sqlToCommonScaleSet(val)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "converting scale sets")
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) CreateEntityScaleSet(_ context.Context, entity params.GithubEntity, param params.CreateScaleSetParams) (scaleSet params.ScaleSet, err error) {
|
||||
if err := param.Validate(); err != nil {
|
||||
return params.ScaleSet{}, fmt.Errorf("failed to validate create params: %w", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err == nil {
|
||||
s.sendNotify(common.ScaleSetEntityType, common.CreateOperation, scaleSet)
|
||||
}
|
||||
}()
|
||||
|
||||
newScaleSet := ScaleSet{
|
||||
Name: param.Name,
|
||||
ScaleSetID: param.ScaleSetID,
|
||||
DisableUpdate: param.DisableUpdate,
|
||||
ProviderName: param.ProviderName,
|
||||
RunnerPrefix: param.GetRunnerPrefix(),
|
||||
MaxRunners: param.MaxRunners,
|
||||
MinIdleRunners: param.MinIdleRunners,
|
||||
RunnerBootstrapTimeout: param.RunnerBootstrapTimeout,
|
||||
Image: param.Image,
|
||||
Flavor: param.Flavor,
|
||||
OSType: param.OSType,
|
||||
OSArch: param.OSArch,
|
||||
Enabled: param.Enabled,
|
||||
GitHubRunnerGroup: param.GitHubRunnerGroup,
|
||||
State: params.ScaleSetPendingCreate,
|
||||
}
|
||||
|
||||
if len(param.ExtraSpecs) > 0 {
|
||||
newScaleSet.ExtraSpecs = datatypes.JSON(param.ExtraSpecs)
|
||||
}
|
||||
|
||||
entityID, err := uuid.Parse(entity.ID)
|
||||
if err != nil {
|
||||
return params.ScaleSet{}, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
||||
}
|
||||
|
||||
switch entity.EntityType {
|
||||
case params.GithubEntityTypeRepository:
|
||||
newScaleSet.RepoID = &entityID
|
||||
case params.GithubEntityTypeOrganization:
|
||||
newScaleSet.OrgID = &entityID
|
||||
case params.GithubEntityTypeEnterprise:
|
||||
newScaleSet.EnterpriseID = &entityID
|
||||
}
|
||||
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
||||
if err := s.hasGithubEntity(tx, entity.EntityType, entity.ID); err != nil {
|
||||
return errors.Wrap(err, "checking entity existence")
|
||||
}
|
||||
|
||||
q := tx.Create(&newScaleSet)
|
||||
if q.Error != nil {
|
||||
return errors.Wrap(q.Error, "creating scale set")
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return params.ScaleSet{}, err
|
||||
}
|
||||
|
||||
dbScaleSet, err := s.getScaleSetByID(s.conn, newScaleSet.ID, "Instances", "Enterprise", "Organization", "Repository")
|
||||
if err != nil {
|
||||
return params.ScaleSet{}, errors.Wrap(err, "fetching scale set")
|
||||
}
|
||||
|
||||
return s.sqlToCommonScaleSet(dbScaleSet)
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) listEntityScaleSets(tx *gorm.DB, entityType params.GithubEntityType, entityID string, preload ...string) ([]ScaleSet, error) {
|
||||
if _, err := uuid.Parse(entityID); err != nil {
|
||||
return nil, errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
||||
}
|
||||
|
||||
if err := s.hasGithubEntity(tx, entityType, entityID); err != nil {
|
||||
return nil, errors.Wrap(err, "checking entity existence")
|
||||
}
|
||||
|
||||
var preloadEntity string
|
||||
var fieldName string
|
||||
switch entityType {
|
||||
case params.GithubEntityTypeRepository:
|
||||
fieldName = entityTypeRepoName
|
||||
preloadEntity = repositoryFieldName
|
||||
case params.GithubEntityTypeOrganization:
|
||||
fieldName = entityTypeOrgName
|
||||
preloadEntity = organizationFieldName
|
||||
case params.GithubEntityTypeEnterprise:
|
||||
fieldName = entityTypeEnterpriseName
|
||||
preloadEntity = enterpriseFieldName
|
||||
default:
|
||||
return nil, fmt.Errorf("invalid entityType: %v", entityType)
|
||||
}
|
||||
|
||||
q := tx
|
||||
q = q.Preload(preloadEntity)
|
||||
if len(preload) > 0 {
|
||||
for _, item := range preload {
|
||||
q = q.Preload(item)
|
||||
}
|
||||
}
|
||||
|
||||
var scaleSets []ScaleSet
|
||||
condition := fmt.Sprintf("%s = ?", fieldName)
|
||||
err := q.Model(&ScaleSet{}).
|
||||
Where(condition, entityID).
|
||||
Omit("extra_specs").
|
||||
Omit("status_messages").
|
||||
Find(&scaleSets).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return []ScaleSet{}, nil
|
||||
}
|
||||
return nil, errors.Wrap(err, "fetching scale sets")
|
||||
}
|
||||
|
||||
return scaleSets, nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) ListEntityScaleSets(_ context.Context, entity params.GithubEntity) ([]params.ScaleSet, error) {
|
||||
scaleSets, err := s.listEntityScaleSets(s.conn, entity.EntityType, entity.ID)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "fetching scale sets")
|
||||
}
|
||||
|
||||
ret := make([]params.ScaleSet, len(scaleSets))
|
||||
for idx, set := range scaleSets {
|
||||
ret[idx], err = s.sqlToCommonScaleSet(set)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "conbverting scale set")
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) UpdateEntityScaleSet(_ context.Context, entity params.GithubEntity, scaleSetID uint, param params.UpdateScaleSetParams, callback func(old, newSet params.ScaleSet) error) (updatedScaleSet params.ScaleSet, err error) {
|
||||
defer func() {
|
||||
if err == nil {
|
||||
s.sendNotify(common.ScaleSetEntityType, common.UpdateOperation, updatedScaleSet)
|
||||
}
|
||||
}()
|
||||
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
||||
scaleSet, err := s.getEntityScaleSet(tx, entity.EntityType, entity.ID, scaleSetID, "Instances")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching scale set")
|
||||
}
|
||||
|
||||
old, err := s.sqlToCommonScaleSet(scaleSet)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "converting scale set")
|
||||
}
|
||||
|
||||
updatedScaleSet, err = s.updateScaleSet(tx, scaleSet, param)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "updating scale set")
|
||||
}
|
||||
|
||||
if callback != nil {
|
||||
if err := callback(old, updatedScaleSet); err != nil {
|
||||
return errors.Wrap(err, "executing update callback")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return params.ScaleSet{}, err
|
||||
}
|
||||
return updatedScaleSet, nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) getEntityScaleSet(tx *gorm.DB, entityType params.GithubEntityType, entityID string, scaleSetID uint, preload ...string) (ScaleSet, error) {
|
||||
if entityID == "" {
|
||||
return ScaleSet{}, errors.Wrap(runnerErrors.ErrBadRequest, "missing entity id")
|
||||
}
|
||||
|
||||
if scaleSetID == 0 {
|
||||
return ScaleSet{}, errors.Wrap(runnerErrors.ErrBadRequest, "missing scaleset id")
|
||||
}
|
||||
|
||||
var fieldName string
|
||||
var entityField string
|
||||
switch entityType {
|
||||
case params.GithubEntityTypeRepository:
|
||||
fieldName = entityTypeRepoName
|
||||
entityField = "Repository"
|
||||
case params.GithubEntityTypeOrganization:
|
||||
fieldName = entityTypeOrgName
|
||||
entityField = "Organization"
|
||||
case params.GithubEntityTypeEnterprise:
|
||||
fieldName = entityTypeEnterpriseName
|
||||
entityField = "Enterprise"
|
||||
default:
|
||||
return ScaleSet{}, fmt.Errorf("invalid entityType: %v", entityType)
|
||||
}
|
||||
|
||||
q := tx
|
||||
q = q.Preload(entityField)
|
||||
if len(preload) > 0 {
|
||||
for _, item := range preload {
|
||||
q = q.Preload(item)
|
||||
}
|
||||
}
|
||||
|
||||
var scaleSet ScaleSet
|
||||
condition := fmt.Sprintf("id = ? and %s = ?", fieldName)
|
||||
err := q.Model(&ScaleSet{}).
|
||||
Where(condition, scaleSetID, entityID).
|
||||
First(&scaleSet).Error
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return ScaleSet{}, errors.Wrap(runnerErrors.ErrNotFound, "finding scale set")
|
||||
}
|
||||
return ScaleSet{}, errors.Wrap(err, "fetching scale set")
|
||||
}
|
||||
|
||||
return scaleSet, nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) updateScaleSet(tx *gorm.DB, scaleSet ScaleSet, param params.UpdateScaleSetParams) (params.ScaleSet, error) {
|
||||
if param.Enabled != nil && scaleSet.Enabled != *param.Enabled {
|
||||
scaleSet.Enabled = *param.Enabled
|
||||
}
|
||||
|
||||
if param.State != nil && *param.State != scaleSet.State {
|
||||
scaleSet.State = *param.State
|
||||
}
|
||||
|
||||
if param.ExtendedState != nil && *param.ExtendedState != scaleSet.ExtendedState {
|
||||
scaleSet.ExtendedState = *param.ExtendedState
|
||||
}
|
||||
|
||||
if param.Name != "" {
|
||||
scaleSet.Name = param.Name
|
||||
}
|
||||
|
||||
if param.GitHubRunnerGroup != nil && *param.GitHubRunnerGroup != "" {
|
||||
scaleSet.GitHubRunnerGroup = *param.GitHubRunnerGroup
|
||||
}
|
||||
|
||||
if param.Flavor != "" {
|
||||
scaleSet.Flavor = param.Flavor
|
||||
}
|
||||
|
||||
if param.Image != "" {
|
||||
scaleSet.Image = param.Image
|
||||
}
|
||||
|
||||
if param.Prefix != "" {
|
||||
scaleSet.RunnerPrefix = param.Prefix
|
||||
}
|
||||
|
||||
if param.MaxRunners != nil {
|
||||
scaleSet.MaxRunners = *param.MaxRunners
|
||||
}
|
||||
|
||||
if param.MinIdleRunners != nil {
|
||||
scaleSet.MinIdleRunners = *param.MinIdleRunners
|
||||
}
|
||||
|
||||
if param.OSArch != "" {
|
||||
scaleSet.OSArch = param.OSArch
|
||||
}
|
||||
|
||||
if param.OSType != "" {
|
||||
scaleSet.OSType = param.OSType
|
||||
}
|
||||
|
||||
if param.ExtraSpecs != nil {
|
||||
scaleSet.ExtraSpecs = datatypes.JSON(param.ExtraSpecs)
|
||||
}
|
||||
|
||||
if param.RunnerBootstrapTimeout != nil && *param.RunnerBootstrapTimeout > 0 {
|
||||
scaleSet.RunnerBootstrapTimeout = *param.RunnerBootstrapTimeout
|
||||
}
|
||||
|
||||
if param.GitHubRunnerGroup != nil {
|
||||
scaleSet.GitHubRunnerGroup = *param.GitHubRunnerGroup
|
||||
}
|
||||
|
||||
if q := tx.Save(&scaleSet); q.Error != nil {
|
||||
return params.ScaleSet{}, errors.Wrap(q.Error, "saving database entry")
|
||||
}
|
||||
|
||||
return s.sqlToCommonScaleSet(scaleSet)
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) GetScaleSetByID(_ context.Context, scaleSet uint) (params.ScaleSet, error) {
|
||||
set, err := s.getScaleSetByID(s.conn, scaleSet, "Instances", "Enterprise", "Organization", "Repository")
|
||||
if err != nil {
|
||||
return params.ScaleSet{}, errors.Wrap(err, "fetching scale set by ID")
|
||||
}
|
||||
return s.sqlToCommonScaleSet(set)
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) DeleteScaleSetByID(_ context.Context, scaleSetID uint) (err error) {
|
||||
var scaleSet params.ScaleSet
|
||||
defer func() {
|
||||
if err == nil && scaleSet.ID != 0 {
|
||||
s.sendNotify(common.ScaleSetEntityType, common.DeleteOperation, scaleSet)
|
||||
}
|
||||
}()
|
||||
err = s.conn.Transaction(func(tx *gorm.DB) error {
|
||||
dbSet, err := s.getScaleSetByID(tx, scaleSetID, "Instances", "Enterprise", "Organization", "Repository")
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching scale set")
|
||||
}
|
||||
|
||||
if len(dbSet.Instances) > 0 {
|
||||
return runnerErrors.NewBadRequestError("cannot delete scaleset with runners")
|
||||
}
|
||||
scaleSet, err = s.sqlToCommonScaleSet(dbSet)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "converting scale set")
|
||||
}
|
||||
|
||||
if q := tx.Unscoped().Delete(&dbSet); q.Error != nil {
|
||||
return errors.Wrap(q.Error, "deleting scale set")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "removing scale set")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) SetScaleSetLastMessageID(_ context.Context, scaleSetID uint, lastMessageID int64) (err error) {
|
||||
var scaleSet params.ScaleSet
|
||||
defer func() {
|
||||
if err == nil && scaleSet.ID != 0 {
|
||||
s.sendNotify(common.ScaleSetEntityType, common.UpdateOperation, scaleSet)
|
||||
}
|
||||
}()
|
||||
if err := s.conn.Transaction(func(tx *gorm.DB) error {
|
||||
dbSet, err := s.getScaleSetByID(tx, scaleSetID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching scale set")
|
||||
}
|
||||
dbSet.LastMessageID = lastMessageID
|
||||
if err := tx.Save(&dbSet).Error; err != nil {
|
||||
return errors.Wrap(err, "saving database entry")
|
||||
}
|
||||
scaleSet, err = s.sqlToCommonScaleSet(dbSet)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "converting scale set")
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return errors.Wrap(err, "setting last message ID")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) SetScaleSetDesiredRunnerCount(_ context.Context, scaleSetID uint, desiredRunnerCount int) (err error) {
|
||||
var scaleSet params.ScaleSet
|
||||
defer func() {
|
||||
if err == nil && scaleSet.ID != 0 {
|
||||
s.sendNotify(common.ScaleSetEntityType, common.UpdateOperation, scaleSet)
|
||||
}
|
||||
}()
|
||||
if err := s.conn.Transaction(func(tx *gorm.DB) error {
|
||||
dbSet, err := s.getScaleSetByID(tx, scaleSetID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching scale set")
|
||||
}
|
||||
dbSet.DesiredRunnerCount = desiredRunnerCount
|
||||
if err := tx.Save(&dbSet).Error; err != nil {
|
||||
return errors.Wrap(err, "saving database entry")
|
||||
}
|
||||
scaleSet, err = s.sqlToCommonScaleSet(dbSet)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "converting scale set")
|
||||
}
|
||||
return nil
|
||||
}); err != nil {
|
||||
return errors.Wrap(err, "setting desired runner count")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
354
database/sql/scalesets_test.go
Normal file
354
database/sql/scalesets_test.go
Normal file
|
|
@ -0,0 +1,354 @@
|
|||
package sql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
|
||||
commonParams "github.com/cloudbase/garm-provider-common/params"
|
||||
dbCommon "github.com/cloudbase/garm/database/common"
|
||||
"github.com/cloudbase/garm/database/watcher"
|
||||
garmTesting "github.com/cloudbase/garm/internal/testing"
|
||||
"github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
type ScaleSetsTestSuite struct {
|
||||
suite.Suite
|
||||
Store dbCommon.Store
|
||||
adminCtx context.Context
|
||||
creds params.GithubCredentials
|
||||
|
||||
org params.Organization
|
||||
repo params.Repository
|
||||
enterprise params.Enterprise
|
||||
|
||||
orgEntity params.GithubEntity
|
||||
repoEntity params.GithubEntity
|
||||
enterpriseEntity params.GithubEntity
|
||||
}
|
||||
|
||||
func (s *ScaleSetsTestSuite) SetupTest() {
|
||||
// create testing sqlite database
|
||||
ctx := context.Background()
|
||||
watcher.InitWatcher(ctx)
|
||||
|
||||
db, err := NewSQLDatabase(context.Background(), garmTesting.GetTestSqliteDBConfig(s.T()))
|
||||
if err != nil {
|
||||
s.FailNow(fmt.Sprintf("failed to create db connection: %s", err))
|
||||
}
|
||||
s.Store = db
|
||||
|
||||
adminCtx := garmTesting.ImpersonateAdminContext(ctx, db, s.T())
|
||||
s.adminCtx = adminCtx
|
||||
|
||||
githubEndpoint := garmTesting.CreateDefaultGithubEndpoint(adminCtx, db, s.T())
|
||||
s.creds = garmTesting.CreateTestGithubCredentials(adminCtx, "new-creds", db, s.T(), githubEndpoint)
|
||||
|
||||
// create an organization for testing purposes
|
||||
s.org, err = s.Store.CreateOrganization(s.adminCtx, "test-org", s.creds.Name, "test-webhookSecret", params.PoolBalancerTypeRoundRobin)
|
||||
if err != nil {
|
||||
s.FailNow(fmt.Sprintf("failed to create org: %s", err))
|
||||
}
|
||||
|
||||
s.repo, err = s.Store.CreateRepository(s.adminCtx, "test-org", "test-repo", s.creds.Name, "test-webhookSecret", params.PoolBalancerTypeRoundRobin)
|
||||
if err != nil {
|
||||
s.FailNow(fmt.Sprintf("failed to create repo: %s", err))
|
||||
}
|
||||
|
||||
s.enterprise, err = s.Store.CreateEnterprise(s.adminCtx, "test-enterprise", s.creds.Name, "test-webhookSecret", params.PoolBalancerTypeRoundRobin)
|
||||
if err != nil {
|
||||
s.FailNow(fmt.Sprintf("failed to create enterprise: %s", err))
|
||||
}
|
||||
|
||||
s.orgEntity, err = s.org.GetEntity()
|
||||
if err != nil {
|
||||
s.FailNow(fmt.Sprintf("failed to get org entity: %s", err))
|
||||
}
|
||||
|
||||
s.repoEntity, err = s.repo.GetEntity()
|
||||
if err != nil {
|
||||
s.FailNow(fmt.Sprintf("failed to get repo entity: %s", err))
|
||||
}
|
||||
|
||||
s.enterpriseEntity, err = s.enterprise.GetEntity()
|
||||
if err != nil {
|
||||
s.FailNow(fmt.Sprintf("failed to get enterprise entity: %s", err))
|
||||
}
|
||||
|
||||
s.T().Cleanup(func() {
|
||||
err := s.Store.DeleteOrganization(s.adminCtx, s.org.ID)
|
||||
if err != nil {
|
||||
s.FailNow(fmt.Sprintf("failed to delete org: %s", err))
|
||||
}
|
||||
err = s.Store.DeleteRepository(s.adminCtx, s.repo.ID)
|
||||
if err != nil {
|
||||
s.FailNow(fmt.Sprintf("failed to delete repo: %s", err))
|
||||
}
|
||||
err = s.Store.DeleteEnterprise(s.adminCtx, s.enterprise.ID)
|
||||
if err != nil {
|
||||
s.FailNow(fmt.Sprintf("failed to delete enterprise: %s", err))
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func (s *ScaleSetsTestSuite) TearDownTest() {
|
||||
watcher.CloseWatcher()
|
||||
}
|
||||
|
||||
func (s *ScaleSetsTestSuite) callback(old, newSet params.ScaleSet) error {
|
||||
s.Require().Equal(old.Name, "test-scaleset")
|
||||
s.Require().Equal(newSet.Name, "test-scaleset-updated")
|
||||
s.Require().Equal(old.OSType, commonParams.Linux)
|
||||
s.Require().Equal(newSet.OSType, commonParams.Windows)
|
||||
s.Require().Equal(old.OSArch, commonParams.Amd64)
|
||||
s.Require().Equal(newSet.OSArch, commonParams.Arm64)
|
||||
s.Require().Equal(old.ExtraSpecs, json.RawMessage(`{"test": 1}`))
|
||||
s.Require().Equal(newSet.ExtraSpecs, json.RawMessage(`{"test": 111}`))
|
||||
s.Require().Equal(old.MaxRunners, uint(10))
|
||||
s.Require().Equal(newSet.MaxRunners, uint(60))
|
||||
s.Require().Equal(old.MinIdleRunners, uint(5))
|
||||
s.Require().Equal(newSet.MinIdleRunners, uint(50))
|
||||
s.Require().Equal(old.Image, "test-image")
|
||||
s.Require().Equal(newSet.Image, "new-test-image")
|
||||
s.Require().Equal(old.Flavor, "test-flavor")
|
||||
s.Require().Equal(newSet.Flavor, "new-test-flavor")
|
||||
s.Require().Equal(old.GitHubRunnerGroup, "test-group")
|
||||
s.Require().Equal(newSet.GitHubRunnerGroup, "new-test-group")
|
||||
s.Require().Equal(old.RunnerPrefix.Prefix, "garm")
|
||||
s.Require().Equal(newSet.RunnerPrefix.Prefix, "test-prefix2")
|
||||
s.Require().Equal(old.Enabled, false)
|
||||
s.Require().Equal(newSet.Enabled, true)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *ScaleSetsTestSuite) TestScaleSetOperations() {
|
||||
// create a scale set for the organization
|
||||
createScaleSetPrams := params.CreateScaleSetParams{
|
||||
Name: "test-scaleset",
|
||||
ProviderName: "test-provider",
|
||||
MaxRunners: 10,
|
||||
MinIdleRunners: 5,
|
||||
Image: "test-image",
|
||||
Flavor: "test-flavor",
|
||||
OSType: commonParams.Linux,
|
||||
OSArch: commonParams.Amd64,
|
||||
ExtraSpecs: json.RawMessage(`{"test": 1}`),
|
||||
GitHubRunnerGroup: "test-group",
|
||||
}
|
||||
|
||||
var orgScaleSet params.ScaleSet
|
||||
var repoScaleSet params.ScaleSet
|
||||
var enterpriseScaleSet params.ScaleSet
|
||||
var err error
|
||||
|
||||
s.T().Run("create org scaleset", func(_ *testing.T) {
|
||||
orgScaleSet, err = s.Store.CreateEntityScaleSet(s.adminCtx, s.orgEntity, createScaleSetPrams)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(orgScaleSet)
|
||||
s.Require().Equal(orgScaleSet.Name, createScaleSetPrams.Name)
|
||||
s.T().Cleanup(func() {
|
||||
err := s.Store.DeleteScaleSetByID(s.adminCtx, orgScaleSet.ID)
|
||||
if err != nil {
|
||||
s.FailNow(fmt.Sprintf("failed to delete scaleset: %s", err))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
s.T().Run("create repo scaleset", func(_ *testing.T) {
|
||||
repoScaleSet, err = s.Store.CreateEntityScaleSet(s.adminCtx, s.repoEntity, createScaleSetPrams)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(repoScaleSet)
|
||||
s.Require().Equal(repoScaleSet.Name, createScaleSetPrams.Name)
|
||||
s.T().Cleanup(func() {
|
||||
err := s.Store.DeleteScaleSetByID(s.adminCtx, repoScaleSet.ID)
|
||||
if err != nil {
|
||||
s.FailNow(fmt.Sprintf("failed to delete scaleset: %s", err))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
s.T().Run("create enterprise scaleset", func(_ *testing.T) {
|
||||
enterpriseScaleSet, err = s.Store.CreateEntityScaleSet(s.adminCtx, s.enterpriseEntity, createScaleSetPrams)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(enterpriseScaleSet)
|
||||
s.Require().Equal(enterpriseScaleSet.Name, createScaleSetPrams.Name)
|
||||
|
||||
s.T().Cleanup(func() {
|
||||
err := s.Store.DeleteScaleSetByID(s.adminCtx, enterpriseScaleSet.ID)
|
||||
if err != nil {
|
||||
s.FailNow(fmt.Sprintf("failed to delete scaleset: %s", err))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
s.T().Run("create list all scalesets", func(_ *testing.T) {
|
||||
allScaleSets, err := s.Store.ListAllScaleSets(s.adminCtx)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotEmpty(allScaleSets)
|
||||
s.Require().Len(allScaleSets, 3)
|
||||
})
|
||||
|
||||
s.T().Run("list repo scalesets", func(_ *testing.T) {
|
||||
repoScaleSets, err := s.Store.ListEntityScaleSets(s.adminCtx, s.repoEntity)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotEmpty(repoScaleSets)
|
||||
s.Require().Len(repoScaleSets, 1)
|
||||
})
|
||||
|
||||
s.T().Run("list org scalesets", func(_ *testing.T) {
|
||||
orgScaleSets, err := s.Store.ListEntityScaleSets(s.adminCtx, s.orgEntity)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotEmpty(orgScaleSets)
|
||||
s.Require().Len(orgScaleSets, 1)
|
||||
})
|
||||
|
||||
s.T().Run("list enterprise scalesets", func(_ *testing.T) {
|
||||
enterpriseScaleSets, err := s.Store.ListEntityScaleSets(s.adminCtx, s.enterpriseEntity)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotEmpty(enterpriseScaleSets)
|
||||
s.Require().Len(enterpriseScaleSets, 1)
|
||||
})
|
||||
|
||||
s.T().Run("get repo scaleset by ID", func(_ *testing.T) {
|
||||
repoScaleSetByID, err := s.Store.GetScaleSetByID(s.adminCtx, repoScaleSet.ID)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(repoScaleSetByID)
|
||||
s.Require().Equal(repoScaleSetByID.ID, repoScaleSet.ID)
|
||||
s.Require().Equal(repoScaleSetByID.Name, repoScaleSet.Name)
|
||||
})
|
||||
|
||||
s.T().Run("get org scaleset by ID", func(_ *testing.T) {
|
||||
orgScaleSetByID, err := s.Store.GetScaleSetByID(s.adminCtx, orgScaleSet.ID)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(orgScaleSetByID)
|
||||
s.Require().Equal(orgScaleSetByID.ID, orgScaleSet.ID)
|
||||
s.Require().Equal(orgScaleSetByID.Name, orgScaleSet.Name)
|
||||
})
|
||||
|
||||
s.T().Run("get enterprise scaleset by ID", func(_ *testing.T) {
|
||||
enterpriseScaleSetByID, err := s.Store.GetScaleSetByID(s.adminCtx, enterpriseScaleSet.ID)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(enterpriseScaleSetByID)
|
||||
s.Require().Equal(enterpriseScaleSetByID.ID, enterpriseScaleSet.ID)
|
||||
s.Require().Equal(enterpriseScaleSetByID.Name, enterpriseScaleSet.Name)
|
||||
})
|
||||
|
||||
s.T().Run("get scaleset by ID not found", func(_ *testing.T) {
|
||||
_, err = s.Store.GetScaleSetByID(s.adminCtx, 999)
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), "not found")
|
||||
})
|
||||
|
||||
s.T().Run("Set scale set last message ID and desired count", func(_ *testing.T) {
|
||||
err = s.Store.SetScaleSetLastMessageID(s.adminCtx, orgScaleSet.ID, 20)
|
||||
s.Require().NoError(err)
|
||||
err = s.Store.SetScaleSetDesiredRunnerCount(s.adminCtx, orgScaleSet.ID, 5)
|
||||
s.Require().NoError(err)
|
||||
orgScaleSetByID, err := s.Store.GetScaleSetByID(s.adminCtx, orgScaleSet.ID)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(orgScaleSetByID)
|
||||
s.Require().Equal(orgScaleSetByID.LastMessageID, int64(20))
|
||||
s.Require().Equal(orgScaleSetByID.DesiredRunnerCount, 5)
|
||||
})
|
||||
|
||||
updateParams := params.UpdateScaleSetParams{
|
||||
Name: "test-scaleset-updated",
|
||||
RunnerPrefix: params.RunnerPrefix{
|
||||
Prefix: "test-prefix2",
|
||||
},
|
||||
OSType: commonParams.Windows,
|
||||
OSArch: commonParams.Arm64,
|
||||
ExtraSpecs: json.RawMessage(`{"test": 111}`),
|
||||
Enabled: garmTesting.Ptr(true),
|
||||
MaxRunners: garmTesting.Ptr(uint(60)),
|
||||
MinIdleRunners: garmTesting.Ptr(uint(50)),
|
||||
Image: "new-test-image",
|
||||
Flavor: "new-test-flavor",
|
||||
GitHubRunnerGroup: garmTesting.Ptr("new-test-group"),
|
||||
}
|
||||
|
||||
s.T().Run("update repo scaleset", func(_ *testing.T) {
|
||||
newRepoScaleSet, err := s.Store.UpdateEntityScaleSet(s.adminCtx, s.repoEntity, repoScaleSet.ID, updateParams, s.callback)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(newRepoScaleSet)
|
||||
s.Require().NoError(s.callback(repoScaleSet, newRepoScaleSet))
|
||||
})
|
||||
|
||||
s.T().Run("update org scaleset", func(_ *testing.T) {
|
||||
newOrgScaleSet, err := s.Store.UpdateEntityScaleSet(s.adminCtx, s.orgEntity, orgScaleSet.ID, updateParams, s.callback)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(newOrgScaleSet)
|
||||
s.Require().NoError(s.callback(orgScaleSet, newOrgScaleSet))
|
||||
})
|
||||
|
||||
s.T().Run("update enterprise scaleset", func(_ *testing.T) {
|
||||
newEnterpriseScaleSet, err := s.Store.UpdateEntityScaleSet(s.adminCtx, s.enterpriseEntity, enterpriseScaleSet.ID, updateParams, s.callback)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(newEnterpriseScaleSet)
|
||||
s.Require().NoError(s.callback(enterpriseScaleSet, newEnterpriseScaleSet))
|
||||
})
|
||||
|
||||
s.T().Run("update scaleset not found", func(_ *testing.T) {
|
||||
_, err = s.Store.UpdateEntityScaleSet(s.adminCtx, s.enterpriseEntity, 99999, updateParams, s.callback)
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), "not found")
|
||||
})
|
||||
|
||||
s.T().Run("update scaleset with invalid entity", func(_ *testing.T) {
|
||||
_, err = s.Store.UpdateEntityScaleSet(s.adminCtx, params.GithubEntity{}, enterpriseScaleSet.ID, params.UpdateScaleSetParams{}, nil)
|
||||
s.Require().Error(err)
|
||||
s.Require().Contains(err.Error(), "missing entity id")
|
||||
})
|
||||
|
||||
s.T().Run("Create repo scale set instance", func(_ *testing.T) {
|
||||
param := params.CreateInstanceParams{
|
||||
Name: "test-instance",
|
||||
Status: commonParams.InstancePendingCreate,
|
||||
RunnerStatus: params.RunnerPending,
|
||||
OSType: commonParams.Linux,
|
||||
OSArch: commonParams.Amd64,
|
||||
CallbackURL: "http://localhost:8080/callback",
|
||||
MetadataURL: "http://localhost:8080/metadata",
|
||||
GitHubRunnerGroup: "test-group",
|
||||
JitConfiguration: map[string]string{
|
||||
"test": "test",
|
||||
},
|
||||
AgentID: 5,
|
||||
}
|
||||
|
||||
instance, err := s.Store.CreateScaleSetInstance(s.adminCtx, repoScaleSet.ID, param)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(instance)
|
||||
s.Require().Equal(instance.Name, param.Name)
|
||||
s.Require().Equal(instance.Status, param.Status)
|
||||
s.Require().Equal(instance.RunnerStatus, param.RunnerStatus)
|
||||
s.Require().Equal(instance.OSType, param.OSType)
|
||||
s.Require().Equal(instance.OSArch, param.OSArch)
|
||||
s.Require().Equal(instance.CallbackURL, param.CallbackURL)
|
||||
s.Require().Equal(instance.MetadataURL, param.MetadataURL)
|
||||
s.Require().Equal(instance.GitHubRunnerGroup, param.GitHubRunnerGroup)
|
||||
s.Require().Equal(instance.JitConfiguration, param.JitConfiguration)
|
||||
s.Require().Equal(instance.AgentID, param.AgentID)
|
||||
|
||||
s.T().Cleanup(func() {
|
||||
err := s.Store.DeleteInstanceByName(s.adminCtx, instance.Name)
|
||||
if err != nil {
|
||||
s.FailNow(fmt.Sprintf("failed to delete scaleset instance: %s", err))
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
s.T().Run("List repo scale set instances", func(_ *testing.T) {
|
||||
instances, err := s.Store.ListScaleSetInstances(s.adminCtx, repoScaleSet.ID)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotEmpty(instances)
|
||||
s.Require().Len(instances, 1)
|
||||
})
|
||||
}
|
||||
|
||||
func TestScaleSetsTestSuite(t *testing.T) {
|
||||
suite.Run(t, new(ScaleSetsTestSuite))
|
||||
}
|
||||
|
|
@ -36,6 +36,12 @@ import (
|
|||
"github.com/cloudbase/garm/util/appdefaults"
|
||||
)
|
||||
|
||||
const (
|
||||
repositoryFieldName string = "Repository"
|
||||
organizationFieldName string = "Organization"
|
||||
enterpriseFieldName string = "Enterprise"
|
||||
)
|
||||
|
||||
// newDBConn returns a new gorm db connection, given the config
|
||||
func newDBConn(dbCfg config.Database) (conn *gorm.DB, err error) {
|
||||
dbType, connURI, err := dbCfg.GormParams()
|
||||
|
|
@ -423,11 +429,15 @@ func (s *sqlDatabase) migrateDB() error {
|
|||
&Repository{},
|
||||
&Organization{},
|
||||
&Enterprise{},
|
||||
&EnterpriseEvent{},
|
||||
&OrganizationEvent{},
|
||||
&RepositoryEvent{},
|
||||
&Address{},
|
||||
&InstanceStatusUpdate{},
|
||||
&Instance{},
|
||||
&ControllerInfo{},
|
||||
&WorkflowJob{},
|
||||
&ScaleSet{},
|
||||
); err != nil {
|
||||
return errors.Wrap(err, "running auto migrate")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ import (
|
|||
"gorm.io/gorm/logger"
|
||||
|
||||
dbCommon "github.com/cloudbase/garm/database/common"
|
||||
"github.com/cloudbase/garm/database/watcher"
|
||||
garmTesting "github.com/cloudbase/garm/internal/testing"
|
||||
"github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
|
@ -53,7 +54,13 @@ func (s *UserTestSuite) assertSQLMockExpectations() {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *UserTestSuite) TearDownTest() {
|
||||
watcher.CloseWatcher()
|
||||
}
|
||||
|
||||
func (s *UserTestSuite) SetupTest() {
|
||||
ctx := context.Background()
|
||||
watcher.InitWatcher(ctx)
|
||||
// create testing sqlite database
|
||||
db, err := NewSQLDatabase(context.Background(), garmTesting.GetTestSqliteDBConfig(s.T()))
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
package sql
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
|
|
@ -60,7 +61,6 @@ func (s *sqlDatabase) sqlToParamsInstance(instance Instance) (params.Instance, e
|
|||
OSArch: instance.OSArch,
|
||||
Status: instance.Status,
|
||||
RunnerStatus: instance.RunnerStatus,
|
||||
PoolID: instance.PoolID.String(),
|
||||
CallbackURL: instance.CallbackURL,
|
||||
MetadataURL: instance.MetadataURL,
|
||||
StatusMessages: []params.StatusMessage{},
|
||||
|
|
@ -73,6 +73,24 @@ func (s *sqlDatabase) sqlToParamsInstance(instance Instance) (params.Instance, e
|
|||
AditionalLabels: labels,
|
||||
}
|
||||
|
||||
if instance.ScaleSetFkID != nil {
|
||||
ret.ScaleSetID = *instance.ScaleSetFkID
|
||||
ret.ProviderName = instance.ScaleSet.ProviderName
|
||||
}
|
||||
|
||||
if instance.PoolID != nil {
|
||||
ret.PoolID = instance.PoolID.String()
|
||||
ret.ProviderName = instance.Pool.ProviderName
|
||||
}
|
||||
|
||||
if ret.ScaleSetID == 0 && ret.PoolID == "" {
|
||||
return params.Instance{}, errors.New("missing pool or scale set id")
|
||||
}
|
||||
|
||||
if ret.ScaleSetID != 0 && ret.PoolID != "" {
|
||||
return params.Instance{}, errors.New("both pool and scale set ids are set")
|
||||
}
|
||||
|
||||
if instance.Job != nil {
|
||||
paramJob, err := sqlWorkflowJobToParamsJob(*instance.Job)
|
||||
if err != nil {
|
||||
|
|
@ -265,6 +283,62 @@ func (s *sqlDatabase) sqlToCommonPool(pool Pool) (params.Pool, error) {
|
|||
return ret, nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) sqlToCommonScaleSet(scaleSet ScaleSet) (params.ScaleSet, error) {
|
||||
ret := params.ScaleSet{
|
||||
ID: scaleSet.ID,
|
||||
ScaleSetID: scaleSet.ScaleSetID,
|
||||
Name: scaleSet.Name,
|
||||
DisableUpdate: scaleSet.DisableUpdate,
|
||||
|
||||
ProviderName: scaleSet.ProviderName,
|
||||
MaxRunners: scaleSet.MaxRunners,
|
||||
MinIdleRunners: scaleSet.MinIdleRunners,
|
||||
RunnerPrefix: params.RunnerPrefix{
|
||||
Prefix: scaleSet.RunnerPrefix,
|
||||
},
|
||||
Image: scaleSet.Image,
|
||||
Flavor: scaleSet.Flavor,
|
||||
OSArch: scaleSet.OSArch,
|
||||
OSType: scaleSet.OSType,
|
||||
Enabled: scaleSet.Enabled,
|
||||
Instances: make([]params.Instance, len(scaleSet.Instances)),
|
||||
RunnerBootstrapTimeout: scaleSet.RunnerBootstrapTimeout,
|
||||
ExtraSpecs: json.RawMessage(scaleSet.ExtraSpecs),
|
||||
GitHubRunnerGroup: scaleSet.GitHubRunnerGroup,
|
||||
State: scaleSet.State,
|
||||
ExtendedState: scaleSet.ExtendedState,
|
||||
LastMessageID: scaleSet.LastMessageID,
|
||||
DesiredRunnerCount: scaleSet.DesiredRunnerCount,
|
||||
}
|
||||
|
||||
if scaleSet.RepoID != nil {
|
||||
ret.RepoID = scaleSet.RepoID.String()
|
||||
if scaleSet.Repository.Owner != "" && scaleSet.Repository.Name != "" {
|
||||
ret.RepoName = fmt.Sprintf("%s/%s", scaleSet.Repository.Owner, scaleSet.Repository.Name)
|
||||
}
|
||||
}
|
||||
|
||||
if scaleSet.OrgID != nil && scaleSet.Organization.Name != "" {
|
||||
ret.OrgID = scaleSet.OrgID.String()
|
||||
ret.OrgName = scaleSet.Organization.Name
|
||||
}
|
||||
|
||||
if scaleSet.EnterpriseID != nil && scaleSet.Enterprise.Name != "" {
|
||||
ret.EnterpriseID = scaleSet.EnterpriseID.String()
|
||||
ret.EnterpriseName = scaleSet.Enterprise.Name
|
||||
}
|
||||
|
||||
var err error
|
||||
for idx, inst := range scaleSet.Instances {
|
||||
ret.Instances[idx], err = s.sqlToParamsInstance(inst)
|
||||
if err != nil {
|
||||
return params.ScaleSet{}, errors.Wrap(err, "converting instance")
|
||||
}
|
||||
}
|
||||
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) sqlToCommonTags(tag Tag) params.Tag {
|
||||
return params.Tag{
|
||||
ID: tag.ID.String(),
|
||||
|
|
@ -452,6 +526,26 @@ func (s *sqlDatabase) getPoolByID(tx *gorm.DB, poolID string, preload ...string)
|
|||
return pool, nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) getScaleSetByID(tx *gorm.DB, scaleSetID uint, preload ...string) (ScaleSet, error) {
|
||||
var scaleSet ScaleSet
|
||||
q := tx.Model(&ScaleSet{})
|
||||
if len(preload) > 0 {
|
||||
for _, item := range preload {
|
||||
q = q.Preload(item)
|
||||
}
|
||||
}
|
||||
|
||||
q = q.Where("id = ?", scaleSetID).First(&scaleSet)
|
||||
|
||||
if q.Error != nil {
|
||||
if errors.Is(q.Error, gorm.ErrRecordNotFound) {
|
||||
return ScaleSet{}, runnerErrors.ErrNotFound
|
||||
}
|
||||
return ScaleSet{}, errors.Wrap(q.Error, "fetching scale set from database")
|
||||
}
|
||||
return scaleSet, nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) hasGithubEntity(tx *gorm.DB, entityType params.GithubEntityType, entityID string) error {
|
||||
u, err := uuid.Parse(entityID)
|
||||
if err != nil {
|
||||
|
|
@ -513,3 +607,159 @@ func (s *sqlDatabase) sendNotify(entityType dbCommon.DatabaseEntityType, op dbCo
|
|||
}
|
||||
return s.producer.Notify(message)
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) GetGithubEntity(_ context.Context, entityType params.GithubEntityType, entityID string) (params.GithubEntity, error) {
|
||||
var ghEntity params.EntityGetter
|
||||
var err error
|
||||
switch entityType {
|
||||
case params.GithubEntityTypeEnterprise:
|
||||
ghEntity, err = s.GetEnterpriseByID(s.ctx, entityID)
|
||||
case params.GithubEntityTypeOrganization:
|
||||
ghEntity, err = s.GetOrganizationByID(s.ctx, entityID)
|
||||
case params.GithubEntityTypeRepository:
|
||||
ghEntity, err = s.GetRepositoryByID(s.ctx, entityID)
|
||||
default:
|
||||
return params.GithubEntity{}, errors.Wrap(runnerErrors.ErrBadRequest, "invalid entity type")
|
||||
}
|
||||
if err != nil {
|
||||
return params.GithubEntity{}, errors.Wrap(err, "failed to get ")
|
||||
}
|
||||
|
||||
entity, err := ghEntity.GetEntity()
|
||||
if err != nil {
|
||||
return params.GithubEntity{}, errors.Wrap(err, "failed to get entity")
|
||||
}
|
||||
return entity, nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) addRepositoryEvent(ctx context.Context, repoID string, event params.EventType, eventLevel params.EventLevel, statusMessage string, maxEvents int) error {
|
||||
repo, err := s.GetRepositoryByID(ctx, repoID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "updating instance")
|
||||
}
|
||||
|
||||
msg := InstanceStatusUpdate{
|
||||
Message: statusMessage,
|
||||
EventType: event,
|
||||
EventLevel: eventLevel,
|
||||
}
|
||||
|
||||
if err := s.conn.Model(&repo).Association("Events").Append(&msg); err != nil {
|
||||
return errors.Wrap(err, "adding status message")
|
||||
}
|
||||
|
||||
if maxEvents > 0 {
|
||||
repoID, err := uuid.Parse(repo.ID)
|
||||
if err != nil {
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
||||
}
|
||||
var latestEvents []OrganizationEvent
|
||||
q := s.conn.Model(&OrganizationEvent{}).
|
||||
Limit(maxEvents).Order("id desc").
|
||||
Where("repo_id = ?", repoID).Find(&latestEvents)
|
||||
if q.Error != nil {
|
||||
return errors.Wrap(q.Error, "fetching latest events")
|
||||
}
|
||||
if len(latestEvents) == maxEvents {
|
||||
lastInList := latestEvents[len(latestEvents)-1]
|
||||
if err := s.conn.Where("repo_id = ? and id < ?", repoID, lastInList.ID).Unscoped().Delete(&OrganizationEvent{}).Error; err != nil {
|
||||
return errors.Wrap(err, "deleting old events")
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) addOrgEvent(ctx context.Context, orgID string, event params.EventType, eventLevel params.EventLevel, statusMessage string, maxEvents int) error {
|
||||
org, err := s.GetOrganizationByID(ctx, orgID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "updating instance")
|
||||
}
|
||||
|
||||
msg := InstanceStatusUpdate{
|
||||
Message: statusMessage,
|
||||
EventType: event,
|
||||
EventLevel: eventLevel,
|
||||
}
|
||||
|
||||
if err := s.conn.Model(&org).Association("Events").Append(&msg); err != nil {
|
||||
return errors.Wrap(err, "adding status message")
|
||||
}
|
||||
|
||||
if maxEvents > 0 {
|
||||
orgID, err := uuid.Parse(org.ID)
|
||||
if err != nil {
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
||||
}
|
||||
var latestEvents []OrganizationEvent
|
||||
q := s.conn.Model(&OrganizationEvent{}).
|
||||
Limit(maxEvents).Order("id desc").
|
||||
Where("org_id = ?", orgID).Find(&latestEvents)
|
||||
if q.Error != nil {
|
||||
return errors.Wrap(q.Error, "fetching latest events")
|
||||
}
|
||||
if len(latestEvents) == maxEvents {
|
||||
lastInList := latestEvents[len(latestEvents)-1]
|
||||
if err := s.conn.Where("org_id = ? and id < ?", orgID, lastInList.ID).Unscoped().Delete(&OrganizationEvent{}).Error; err != nil {
|
||||
return errors.Wrap(err, "deleting old events")
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) addEnterpriseEvent(ctx context.Context, entID string, event params.EventType, eventLevel params.EventLevel, statusMessage string, maxEvents int) error {
|
||||
ent, err := s.GetEnterpriseByID(ctx, entID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "updating instance")
|
||||
}
|
||||
|
||||
msg := InstanceStatusUpdate{
|
||||
Message: statusMessage,
|
||||
EventType: event,
|
||||
EventLevel: eventLevel,
|
||||
}
|
||||
|
||||
if err := s.conn.Model(&ent).Association("Events").Append(&msg); err != nil {
|
||||
return errors.Wrap(err, "adding status message")
|
||||
}
|
||||
|
||||
if maxEvents > 0 {
|
||||
entID, err := uuid.Parse(ent.ID)
|
||||
if err != nil {
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "parsing id")
|
||||
}
|
||||
var latestEvents []EnterpriseEvent
|
||||
q := s.conn.Model(&EnterpriseEvent{}).
|
||||
Limit(maxEvents).Order("id desc").
|
||||
Where("enterprise_id = ?", entID).Find(&latestEvents)
|
||||
if q.Error != nil {
|
||||
return errors.Wrap(q.Error, "fetching latest events")
|
||||
}
|
||||
if len(latestEvents) == maxEvents {
|
||||
lastInList := latestEvents[len(latestEvents)-1]
|
||||
if err := s.conn.Where("enterprise_id = ? and id < ?", entID, lastInList.ID).Unscoped().Delete(&EnterpriseEvent{}).Error; err != nil {
|
||||
return errors.Wrap(err, "deleting old events")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *sqlDatabase) AddEntityEvent(ctx context.Context, entity params.GithubEntity, event params.EventType, eventLevel params.EventLevel, statusMessage string, maxEvents int) error {
|
||||
if maxEvents == 0 {
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "max events cannot be 0")
|
||||
}
|
||||
|
||||
switch entity.EntityType {
|
||||
case params.GithubEntityTypeRepository:
|
||||
return s.addRepositoryEvent(ctx, entity.ID, event, eventLevel, statusMessage, maxEvents)
|
||||
case params.GithubEntityTypeOrganization:
|
||||
return s.addOrgEvent(ctx, entity.ID, event, eventLevel, statusMessage, maxEvents)
|
||||
case params.GithubEntityTypeEnterprise:
|
||||
return s.addEnterpriseEvent(ctx, entity.ID, event, eventLevel, statusMessage, maxEvents)
|
||||
default:
|
||||
return errors.Wrap(runnerErrors.ErrBadRequest, "invalid entity type")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,11 +1,12 @@
|
|||
package watcher
|
||||
|
||||
import (
|
||||
commonParams "github.com/cloudbase/garm-provider-common/params"
|
||||
dbCommon "github.com/cloudbase/garm/database/common"
|
||||
"github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
||||
type idGetter interface {
|
||||
type IDGetter interface {
|
||||
GetID() string
|
||||
}
|
||||
|
||||
|
|
@ -72,21 +73,41 @@ func WithEntityPoolFilter(ghEntity params.GithubEntity) dbCommon.PayloadFilterFu
|
|||
}
|
||||
switch ghEntity.EntityType {
|
||||
case params.GithubEntityTypeRepository:
|
||||
if pool.RepoID != ghEntity.ID {
|
||||
return false
|
||||
}
|
||||
return pool.RepoID == ghEntity.ID
|
||||
case params.GithubEntityTypeOrganization:
|
||||
if pool.OrgID != ghEntity.ID {
|
||||
return false
|
||||
}
|
||||
return pool.OrgID == ghEntity.ID
|
||||
case params.GithubEntityTypeEnterprise:
|
||||
if pool.EnterpriseID != ghEntity.ID {
|
||||
return false
|
||||
}
|
||||
return pool.EnterpriseID == ghEntity.ID
|
||||
default:
|
||||
return false
|
||||
}
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// WithEntityPoolFilter returns true if the change payload is a pool that belongs to the
|
||||
// supplied Github entity. This is useful when an entity worker wants to watch for changes
|
||||
// in pools that belong to it.
|
||||
func WithEntityScaleSetFilter(ghEntity params.GithubEntity) dbCommon.PayloadFilterFunc {
|
||||
return func(payload dbCommon.ChangePayload) bool {
|
||||
switch payload.EntityType {
|
||||
case dbCommon.ScaleSetEntityType:
|
||||
scaleSet, ok := payload.Payload.(params.ScaleSet)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
switch ghEntity.EntityType {
|
||||
case params.GithubEntityTypeRepository:
|
||||
return scaleSet.RepoID == ghEntity.ID
|
||||
case params.GithubEntityTypeOrganization:
|
||||
return scaleSet.OrgID == ghEntity.ID
|
||||
case params.GithubEntityTypeEnterprise:
|
||||
return scaleSet.EnterpriseID == ghEntity.ID
|
||||
default:
|
||||
return false
|
||||
}
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
|
@ -100,7 +121,7 @@ func WithEntityFilter(entity params.GithubEntity) dbCommon.PayloadFilterFunc {
|
|||
if params.GithubEntityType(payload.EntityType) != entity.EntityType {
|
||||
return false
|
||||
}
|
||||
var ent idGetter
|
||||
var ent IDGetter
|
||||
var ok bool
|
||||
switch payload.EntityType {
|
||||
case dbCommon.RepositoryEntityType:
|
||||
|
|
@ -210,3 +231,76 @@ func WithExcludeEntityTypeFilter(entityType dbCommon.DatabaseEntityType) dbCommo
|
|||
return payload.EntityType != entityType
|
||||
}
|
||||
}
|
||||
|
||||
// WithScaleSetFilter returns a filter function that matches a particular scale set.
|
||||
func WithScaleSetFilter(scaleset params.ScaleSet) dbCommon.PayloadFilterFunc {
|
||||
return func(payload dbCommon.ChangePayload) bool {
|
||||
if payload.EntityType != dbCommon.ScaleSetEntityType {
|
||||
return false
|
||||
}
|
||||
|
||||
ss, ok := payload.Payload.(params.ScaleSet)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return ss.ID == scaleset.ID
|
||||
}
|
||||
}
|
||||
|
||||
func WithScaleSetInstanceFilter(scaleset params.ScaleSet) dbCommon.PayloadFilterFunc {
|
||||
return func(payload dbCommon.ChangePayload) bool {
|
||||
if payload.EntityType != dbCommon.InstanceEntityType {
|
||||
return false
|
||||
}
|
||||
|
||||
instance, ok := payload.Payload.(params.Instance)
|
||||
if !ok || instance.ScaleSetID == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
return instance.ScaleSetID == scaleset.ID
|
||||
}
|
||||
}
|
||||
|
||||
// EntityTypeCallbackFilter is a callback function that takes a ChangePayload and returns a boolean.
|
||||
// This callback type is used in the WithEntityTypeAndCallbackFilter (and potentially others) when
|
||||
// a filter needs to delegate logic to a specific callback function.
|
||||
type EntityTypeCallbackFilter func(payload dbCommon.ChangePayload) (bool, error)
|
||||
|
||||
// WithEntityTypeAndCallbackFilter returns a filter function that filters payloads by entity type and the
|
||||
// result of a callback function.
|
||||
func WithEntityTypeAndCallbackFilter(entityType dbCommon.DatabaseEntityType, callback EntityTypeCallbackFilter) dbCommon.PayloadFilterFunc {
|
||||
return func(payload dbCommon.ChangePayload) bool {
|
||||
if payload.EntityType != entityType {
|
||||
return false
|
||||
}
|
||||
|
||||
ok, err := callback(payload)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return ok
|
||||
}
|
||||
}
|
||||
|
||||
func WithInstanceStatusFilter(statuses ...commonParams.InstanceStatus) dbCommon.PayloadFilterFunc {
|
||||
return func(payload dbCommon.ChangePayload) bool {
|
||||
if payload.EntityType != dbCommon.InstanceEntityType {
|
||||
return false
|
||||
}
|
||||
instance, ok := payload.Payload.(params.Instance)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
if len(statuses) == 0 {
|
||||
return false
|
||||
}
|
||||
for _, status := range statuses {
|
||||
if instance.Status == status {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ func InitWatcher(ctx context.Context) {
|
|||
if databaseWatcher != nil {
|
||||
return
|
||||
}
|
||||
ctx = garmUtil.WithContext(ctx, slog.Any("watcher", "database"))
|
||||
ctx = garmUtil.WithSlogContext(ctx, slog.Any("watcher", "database"))
|
||||
w := &watcher{
|
||||
producers: make(map[string]*producer),
|
||||
consumers: make(map[string]*consumer),
|
||||
|
|
@ -29,11 +29,20 @@ func InitWatcher(ctx context.Context) {
|
|||
databaseWatcher = w
|
||||
}
|
||||
|
||||
func CloseWatcher() error {
|
||||
if databaseWatcher == nil {
|
||||
return nil
|
||||
}
|
||||
databaseWatcher.Close()
|
||||
databaseWatcher = nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func RegisterProducer(ctx context.Context, id string) (common.Producer, error) {
|
||||
if databaseWatcher == nil {
|
||||
return nil, common.ErrWatcherNotInitialized
|
||||
}
|
||||
ctx = garmUtil.WithContext(ctx, slog.Any("producer_id", id))
|
||||
ctx = garmUtil.WithSlogContext(ctx, slog.Any("producer_id", id))
|
||||
return databaseWatcher.RegisterProducer(ctx, id)
|
||||
}
|
||||
|
||||
|
|
@ -41,7 +50,7 @@ func RegisterConsumer(ctx context.Context, id string, filters ...common.PayloadF
|
|||
if databaseWatcher == nil {
|
||||
return nil, common.ErrWatcherNotInitialized
|
||||
}
|
||||
ctx = garmUtil.WithContext(ctx, slog.Any("consumer_id", id))
|
||||
ctx = garmUtil.WithSlogContext(ctx, slog.Any("consumer_id", id))
|
||||
return databaseWatcher.RegisterConsumer(ctx, id, filters...)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -241,6 +241,112 @@ func (s *WatcherStoreTestSuite) TestInstanceWatcher() {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *WatcherStoreTestSuite) TestScaleSetInstanceWatcher() {
|
||||
consumer, err := watcher.RegisterConsumer(
|
||||
s.ctx, "instance-test",
|
||||
watcher.WithEntityTypeFilter(common.InstanceEntityType),
|
||||
watcher.WithAny(
|
||||
watcher.WithOperationTypeFilter(common.CreateOperation),
|
||||
watcher.WithOperationTypeFilter(common.UpdateOperation),
|
||||
watcher.WithOperationTypeFilter(common.DeleteOperation)),
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(consumer)
|
||||
s.T().Cleanup(func() { consumer.Close() })
|
||||
consumeEvents(consumer)
|
||||
|
||||
ep := garmTesting.CreateDefaultGithubEndpoint(s.ctx, s.store, s.T())
|
||||
creds := garmTesting.CreateTestGithubCredentials(s.ctx, "test-creds", s.store, s.T(), ep)
|
||||
s.T().Cleanup(func() { s.store.DeleteGithubCredentials(s.ctx, creds.ID) })
|
||||
|
||||
repo, err := s.store.CreateRepository(s.ctx, "test-owner", "test-repo", creds.Name, "test-secret", params.PoolBalancerTypeRoundRobin)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotEmpty(repo.ID)
|
||||
s.T().Cleanup(func() { s.store.DeleteRepository(s.ctx, repo.ID) })
|
||||
|
||||
entity, err := repo.GetEntity()
|
||||
s.Require().NoError(err)
|
||||
|
||||
createScaleSetParams := params.CreateScaleSetParams{
|
||||
ProviderName: "test-provider",
|
||||
Name: "test-scaleset",
|
||||
Image: "test-image",
|
||||
Flavor: "test-flavor",
|
||||
MinIdleRunners: 0,
|
||||
MaxRunners: 1,
|
||||
OSType: commonParams.Linux,
|
||||
OSArch: commonParams.Amd64,
|
||||
}
|
||||
|
||||
scaleSet, err := s.store.CreateEntityScaleSet(s.ctx, entity, createScaleSetParams)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotEmpty(scaleSet.ID)
|
||||
s.T().Cleanup(func() { s.store.DeleteScaleSetByID(s.ctx, scaleSet.ID) })
|
||||
|
||||
createInstanceParams := params.CreateInstanceParams{
|
||||
Name: "test-instance",
|
||||
OSType: commonParams.Linux,
|
||||
OSArch: commonParams.Amd64,
|
||||
Status: commonParams.InstanceCreating,
|
||||
}
|
||||
instance, err := s.store.CreateScaleSetInstance(s.ctx, scaleSet.ID, createInstanceParams)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotEmpty(instance.ID)
|
||||
|
||||
select {
|
||||
case event := <-consumer.Watch():
|
||||
s.Require().Equal(common.ChangePayload{
|
||||
EntityType: common.InstanceEntityType,
|
||||
Operation: common.CreateOperation,
|
||||
Payload: instance,
|
||||
}, event)
|
||||
asInstance, ok := event.Payload.(params.Instance)
|
||||
s.Require().True(ok)
|
||||
s.Require().Equal(instance.Name, "test-instance")
|
||||
s.Require().Equal(asInstance.Name, "test-instance")
|
||||
case <-time.After(1 * time.Second):
|
||||
s.T().Fatal("expected payload not received")
|
||||
}
|
||||
|
||||
updateParams := params.UpdateInstanceParams{
|
||||
RunnerStatus: params.RunnerActive,
|
||||
}
|
||||
|
||||
updatedInstance, err := s.store.UpdateInstance(s.ctx, instance.Name, updateParams)
|
||||
s.Require().NoError(err)
|
||||
|
||||
select {
|
||||
case event := <-consumer.Watch():
|
||||
s.Require().Equal(common.ChangePayload{
|
||||
EntityType: common.InstanceEntityType,
|
||||
Operation: common.UpdateOperation,
|
||||
Payload: updatedInstance,
|
||||
}, event)
|
||||
case <-time.After(1 * time.Second):
|
||||
s.T().Fatal("expected payload not received")
|
||||
}
|
||||
|
||||
err = s.store.DeleteInstanceByName(s.ctx, updatedInstance.Name)
|
||||
s.Require().NoError(err)
|
||||
|
||||
select {
|
||||
case event := <-consumer.Watch():
|
||||
s.Require().Equal(common.ChangePayload{
|
||||
EntityType: common.InstanceEntityType,
|
||||
Operation: common.DeleteOperation,
|
||||
Payload: params.Instance{
|
||||
ID: updatedInstance.ID,
|
||||
Name: updatedInstance.Name,
|
||||
ProviderID: updatedInstance.ProviderID,
|
||||
AgentID: updatedInstance.AgentID,
|
||||
ScaleSetID: updatedInstance.ScaleSetID,
|
||||
},
|
||||
}, event)
|
||||
case <-time.After(1 * time.Second):
|
||||
s.T().Fatal("expected payload not received")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *WatcherStoreTestSuite) TestPoolWatcher() {
|
||||
consumer, err := watcher.RegisterConsumer(
|
||||
s.ctx, "pool-test",
|
||||
|
|
@ -362,6 +468,134 @@ func (s *WatcherStoreTestSuite) TestPoolWatcher() {
|
|||
}
|
||||
}
|
||||
|
||||
func (s *WatcherStoreTestSuite) TestScaleSetWatcher() {
|
||||
consumer, err := watcher.RegisterConsumer(
|
||||
s.ctx, "scaleset-test",
|
||||
watcher.WithEntityTypeFilter(common.ScaleSetEntityType),
|
||||
watcher.WithAny(
|
||||
watcher.WithOperationTypeFilter(common.CreateOperation),
|
||||
watcher.WithOperationTypeFilter(common.UpdateOperation),
|
||||
watcher.WithOperationTypeFilter(common.DeleteOperation)),
|
||||
)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotNil(consumer)
|
||||
s.T().Cleanup(func() { consumer.Close() })
|
||||
consumeEvents(consumer)
|
||||
|
||||
ep := garmTesting.CreateDefaultGithubEndpoint(s.ctx, s.store, s.T())
|
||||
creds := garmTesting.CreateTestGithubCredentials(s.ctx, "test-creds", s.store, s.T(), ep)
|
||||
s.T().Cleanup(func() {
|
||||
if err := s.store.DeleteGithubCredentials(s.ctx, creds.ID); err != nil {
|
||||
s.T().Logf("failed to delete Github credentials: %v", err)
|
||||
}
|
||||
})
|
||||
|
||||
repo, err := s.store.CreateRepository(s.ctx, "test-owner", "test-repo", creds.Name, "test-secret", params.PoolBalancerTypeRoundRobin)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotEmpty(repo.ID)
|
||||
s.T().Cleanup(func() { s.store.DeleteRepository(s.ctx, repo.ID) })
|
||||
|
||||
entity, err := repo.GetEntity()
|
||||
s.Require().NoError(err)
|
||||
|
||||
createScaleSetParams := params.CreateScaleSetParams{
|
||||
ProviderName: "test-provider",
|
||||
Name: "test-scaleset",
|
||||
Image: "test-image",
|
||||
Flavor: "test-flavor",
|
||||
MinIdleRunners: 0,
|
||||
MaxRunners: 1,
|
||||
OSType: commonParams.Linux,
|
||||
OSArch: commonParams.Amd64,
|
||||
Tags: []string{"test-tag"},
|
||||
}
|
||||
scaleSet, err := s.store.CreateEntityScaleSet(s.ctx, entity, createScaleSetParams)
|
||||
s.Require().NoError(err)
|
||||
s.Require().NotEmpty(scaleSet.ID)
|
||||
|
||||
select {
|
||||
case event := <-consumer.Watch():
|
||||
s.Require().Equal(common.ChangePayload{
|
||||
EntityType: common.ScaleSetEntityType,
|
||||
Operation: common.CreateOperation,
|
||||
Payload: scaleSet,
|
||||
}, event)
|
||||
asScaleSet, ok := event.Payload.(params.ScaleSet)
|
||||
s.Require().True(ok)
|
||||
s.Require().Equal(scaleSet.Image, "test-image")
|
||||
s.Require().Equal(asScaleSet.Image, "test-image")
|
||||
case <-time.After(1 * time.Second):
|
||||
s.T().Fatal("expected payload not received")
|
||||
}
|
||||
|
||||
updateParams := params.UpdateScaleSetParams{
|
||||
Flavor: "updated-flavor",
|
||||
}
|
||||
|
||||
callbackFn := func(old, newScaleSet params.ScaleSet) error {
|
||||
s.Require().Equal(old.ID, newScaleSet.ID)
|
||||
s.Require().Equal(old.Flavor, "test-flavor")
|
||||
s.Require().Equal(newScaleSet.Flavor, "updated-flavor")
|
||||
return nil
|
||||
}
|
||||
updatedScaleSet, err := s.store.UpdateEntityScaleSet(s.ctx, entity, scaleSet.ID, updateParams, callbackFn)
|
||||
s.Require().NoError(err)
|
||||
|
||||
select {
|
||||
case event := <-consumer.Watch():
|
||||
s.Require().Equal(common.ChangePayload{
|
||||
EntityType: common.ScaleSetEntityType,
|
||||
Operation: common.UpdateOperation,
|
||||
Payload: updatedScaleSet,
|
||||
}, event)
|
||||
case <-time.After(1 * time.Second):
|
||||
s.T().Fatal("expected payload not received")
|
||||
}
|
||||
|
||||
err = s.store.SetScaleSetLastMessageID(s.ctx, updatedScaleSet.ID, 99)
|
||||
s.Require().NoError(err)
|
||||
|
||||
select {
|
||||
case event := <-consumer.Watch():
|
||||
asScaleSet, ok := event.Payload.(params.ScaleSet)
|
||||
s.Require().True(ok)
|
||||
s.Require().Equal(asScaleSet.ID, updatedScaleSet.ID)
|
||||
s.Require().Equal(asScaleSet.LastMessageID, int64(99))
|
||||
case <-time.After(1 * time.Second):
|
||||
s.T().Fatal("expected payload not received")
|
||||
}
|
||||
|
||||
err = s.store.SetScaleSetDesiredRunnerCount(s.ctx, updatedScaleSet.ID, 5)
|
||||
s.Require().NoError(err)
|
||||
|
||||
select {
|
||||
case event := <-consumer.Watch():
|
||||
asScaleSet, ok := event.Payload.(params.ScaleSet)
|
||||
s.Require().True(ok)
|
||||
s.Require().Equal(asScaleSet.ID, updatedScaleSet.ID)
|
||||
s.Require().Equal(asScaleSet.DesiredRunnerCount, 5)
|
||||
case <-time.After(1 * time.Second):
|
||||
s.T().Fatal("expected payload not received")
|
||||
}
|
||||
|
||||
err = s.store.DeleteScaleSetByID(s.ctx, scaleSet.ID)
|
||||
s.Require().NoError(err)
|
||||
|
||||
select {
|
||||
case event := <-consumer.Watch():
|
||||
// We updated last message ID and desired runner count above.
|
||||
updatedScaleSet.DesiredRunnerCount = 5
|
||||
updatedScaleSet.LastMessageID = 99
|
||||
s.Require().Equal(common.ChangePayload{
|
||||
EntityType: common.ScaleSetEntityType,
|
||||
Operation: common.DeleteOperation,
|
||||
Payload: updatedScaleSet,
|
||||
}, event)
|
||||
case <-time.After(1 * time.Second):
|
||||
s.T().Fatal("expected payload not received")
|
||||
}
|
||||
}
|
||||
|
||||
func (s *WatcherStoreTestSuite) TestControllerWatcher() {
|
||||
consumer, err := watcher.RegisterConsumer(
|
||||
s.ctx, "controller-test",
|
||||
|
|
@ -748,8 +982,11 @@ func consumeEvents(consumer common.Consumer) {
|
|||
consume:
|
||||
for {
|
||||
select {
|
||||
case <-consumer.Watch():
|
||||
case _, ok := <-consumer.Watch():
|
||||
// throw away event.
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
case <-time.After(100 * time.Millisecond):
|
||||
break consume
|
||||
}
|
||||
|
|
|
|||
21
go.mod
21
go.mod
|
|
@ -7,14 +7,14 @@ toolchain go1.23.6
|
|||
require (
|
||||
github.com/BurntSushi/toml v1.5.0
|
||||
github.com/bradleyfalzon/ghinstallation/v2 v2.15.0
|
||||
github.com/cloudbase/garm-provider-common v0.1.4
|
||||
github.com/cloudbase/garm-provider-common v0.1.5-0.20250417155201-8ef03502d06e
|
||||
github.com/felixge/httpsnoop v1.0.4
|
||||
github.com/go-openapi/errors v0.22.1
|
||||
github.com/go-openapi/runtime v0.28.0
|
||||
github.com/go-openapi/strfmt v0.23.0
|
||||
github.com/go-openapi/swag v0.23.1
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2
|
||||
github.com/google/go-github/v57 v57.0.0
|
||||
github.com/google/go-github/v71 v71.0.0
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/gorilla/handlers v1.5.2
|
||||
github.com/gorilla/mux v1.8.1
|
||||
|
|
@ -28,15 +28,15 @@ require (
|
|||
github.com/prometheus/client_golang v1.22.0
|
||||
github.com/spf13/cobra v1.9.1
|
||||
github.com/stretchr/testify v1.10.0
|
||||
golang.org/x/crypto v0.37.0
|
||||
golang.org/x/oauth2 v0.29.0
|
||||
golang.org/x/sync v0.13.0
|
||||
golang.org/x/crypto v0.38.0
|
||||
golang.org/x/oauth2 v0.30.0
|
||||
golang.org/x/sync v0.14.0
|
||||
gopkg.in/DATA-DOG/go-sqlmock.v1 v1.3.0
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||
gorm.io/datatypes v1.2.5
|
||||
gorm.io/driver/mysql v1.5.7
|
||||
gorm.io/driver/sqlite v1.5.7
|
||||
gorm.io/gorm v1.25.12
|
||||
gorm.io/gorm v1.26.0
|
||||
)
|
||||
|
||||
require (
|
||||
|
|
@ -56,7 +56,6 @@ require (
|
|||
github.com/go-openapi/validate v0.24.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.9.2 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.5.2 // indirect
|
||||
github.com/google/go-github/v71 v71.0.0 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
|
|
@ -77,7 +76,7 @@ require (
|
|||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.63.0 // indirect
|
||||
github.com/prometheus/procfs v0.16.0 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/spf13/pflag v1.0.6 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
|
|
@ -87,9 +86,9 @@ require (
|
|||
go.opentelemetry.io/otel v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.35.0 // indirect
|
||||
golang.org/x/net v0.39.0 // indirect
|
||||
golang.org/x/sys v0.32.0 // indirect
|
||||
golang.org/x/text v0.24.0 // indirect
|
||||
golang.org/x/net v0.40.0 // indirect
|
||||
golang.org/x/sys v0.33.0 // indirect
|
||||
golang.org/x/text v0.25.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
|
|
|||
38
go.sum
38
go.sum
|
|
@ -19,8 +19,8 @@ github.com/chzyer/readline v1.5.1/go.mod h1:Eh+b79XXUwfKfcPLepksvw2tcLE/Ct21YObk
|
|||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04=
|
||||
github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8=
|
||||
github.com/cloudbase/garm-provider-common v0.1.4 h1:spRjl0PV4r8vKaCTNp6xBQbRKfls/cmbBEl/i/eGWSo=
|
||||
github.com/cloudbase/garm-provider-common v0.1.4/go.mod h1:sK26i2NpjjAjhanNKiWw8iPkqt+XeohTKpFnEP7JdZ4=
|
||||
github.com/cloudbase/garm-provider-common v0.1.5-0.20250417155201-8ef03502d06e h1:giq2Prk9I/ez1dc4/r9jivf2jbhjX9apZ41TWQ5g3qE=
|
||||
github.com/cloudbase/garm-provider-common v0.1.5-0.20250417155201-8ef03502d06e/go.mod h1:sSrTBtTc0q72MZdmS9EuLLdDhkmXZAqAwRIgEK0TqUo=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
|
|
@ -66,8 +66,6 @@ github.com/golang-sql/sqlexp v0.1.0/go.mod h1:J4ad9Vo8ZCWQ2GMrC4UCQy1JpCbwU9m3EO
|
|||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/go-github/v57 v57.0.0 h1:L+Y3UPTY8ALM8x+TV0lg+IEBI+upibemtBD8Q9u7zHs=
|
||||
github.com/google/go-github/v57 v57.0.0/go.mod h1:s0omdnye0hvK/ecLvpsGfJMiRt85PimQh4oygmLIxHw=
|
||||
github.com/google/go-github/v71 v71.0.0 h1:Zi16OymGKZZMm8ZliffVVJ/Q9YZreDKONCr+WUd0Z30=
|
||||
github.com/google/go-github/v71 v71.0.0/go.mod h1:URZXObp2BLlMjwu0O8g4y6VBneUj2bCHgnI8FfgZ51M=
|
||||
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||
|
|
@ -157,8 +155,8 @@ github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNw
|
|||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
|
||||
github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18=
|
||||
github.com/prometheus/procfs v0.16.0 h1:xh6oHhKwnOJKMYiYBDWmkHqQPyiY40sny36Cmx2bbsM=
|
||||
github.com/prometheus/procfs v0.16.0/go.mod h1:8veyXUu3nGP7oaCxhX6yeaM5u4stL2FeMXnCqhDthZg=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
|
|
@ -190,21 +188,21 @@ go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucg
|
|||
go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg=
|
||||
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
||||
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
||||
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
||||
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
|
||||
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
|
||||
golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
|
||||
golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
||||
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
|
||||
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/crypto v0.38.0 h1:jt+WWG8IZlBnVbomuhg2Mdq0+BBQaHbtqHEFEigjUV8=
|
||||
golang.org/x/crypto v0.38.0/go.mod h1:MvrbAqul58NNYPKnOra203SB9vpuZW0e+RRZV+Ggqjw=
|
||||
golang.org/x/net v0.40.0 h1:79Xs7wF06Gbdcg4kdCCIQArK11Z1hr5POQ6+fIYHNuY=
|
||||
golang.org/x/net v0.40.0/go.mod h1:y0hY0exeL2Pku80/zKK7tpntoX23cqL3Oa6njdgRtds=
|
||||
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
|
||||
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
|
||||
golang.org/x/sync v0.14.0 h1:woo0S4Yywslg6hp4eUFjTVOyKt0RookbpAHG4c1HmhQ=
|
||||
golang.org/x/sync v0.14.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
||||
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
|
||||
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.25.0 h1:qVyWApTSYLk/drJRO5mDlNYskwQznZmkpV2c8q9zls4=
|
||||
golang.org/x/text v0.25.0/go.mod h1:WEdwpYrmk1qmdHvhkSTNPm3app7v4rsT8F2UD6+VHIA=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
|
|
@ -231,5 +229,5 @@ gorm.io/driver/sqlite v1.5.7/go.mod h1:U+J8craQU6Fzkcvu8oLeAQmi50TkwPEhHDEjQZXDa
|
|||
gorm.io/driver/sqlserver v1.5.4 h1:xA+Y1KDNspv79q43bPyjDMUgHoYHLhXYmdFcYPobg8g=
|
||||
gorm.io/driver/sqlserver v1.5.4/go.mod h1:+frZ/qYmuna11zHPlh5oc2O6ZA/lS88Keb0XSH1Zh/g=
|
||||
gorm.io/gorm v1.25.7/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||
gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
|
||||
gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
|
||||
gorm.io/gorm v1.26.0 h1:9lqQVPG5aNNS6AyHdRiwScAVnXHg/L/Srzx55G5fOgs=
|
||||
gorm.io/gorm v1.26.0/go.mod h1:8Z33v652h4//uMA76KjeDH8mJXPm1QNCYrMeatR0DOE=
|
||||
|
|
|
|||
|
|
@ -153,6 +153,10 @@ type NameAndIDDBEntity interface {
|
|||
GetName() string
|
||||
}
|
||||
|
||||
func Ptr[T any](v T) *T {
|
||||
return &v
|
||||
}
|
||||
|
||||
func EqualDBEntityByName[T NameAndIDDBEntity](t *testing.T, expected, actual []T) {
|
||||
require.Equal(t, len(expected), len(actual))
|
||||
|
||||
|
|
|
|||
17
locking/interface.go
Normal file
17
locking/interface.go
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
package locking
|
||||
|
||||
import "time"
|
||||
|
||||
type Locker interface {
|
||||
TryLock(key, identifier string) bool
|
||||
Lock(key, identifier string)
|
||||
LockedBy(key string) (string, bool)
|
||||
Unlock(key string, remove bool)
|
||||
Delete(key string)
|
||||
}
|
||||
|
||||
type InstanceDeleteBackoff interface {
|
||||
ShouldProcess(key string) (bool, time.Time)
|
||||
Delete(key string)
|
||||
RecordFailure(key string)
|
||||
}
|
||||
|
|
@ -1,40 +1,15 @@
|
|||
package pool
|
||||
package locking
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/cloudbase/garm/runner/common"
|
||||
)
|
||||
|
||||
const (
|
||||
maxBackoffSeconds float64 = 1200 // 20 minutes
|
||||
)
|
||||
|
||||
type keyMutex struct {
|
||||
muxes sync.Map
|
||||
}
|
||||
|
||||
func (k *keyMutex) TryLock(key string) bool {
|
||||
mux, _ := k.muxes.LoadOrStore(key, &sync.Mutex{})
|
||||
keyMux := mux.(*sync.Mutex)
|
||||
return keyMux.TryLock()
|
||||
}
|
||||
|
||||
func (k *keyMutex) Unlock(key string, remove bool) {
|
||||
mux, ok := k.muxes.Load(key)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
keyMux := mux.(*sync.Mutex)
|
||||
if remove {
|
||||
k.Delete(key)
|
||||
}
|
||||
keyMux.Unlock()
|
||||
}
|
||||
|
||||
func (k *keyMutex) Delete(key string) {
|
||||
k.muxes.Delete(key)
|
||||
func NewInstanceDeleteBackoff(_ context.Context) (InstanceDeleteBackoff, error) {
|
||||
return &instanceDeleteBackoff{}, nil
|
||||
}
|
||||
|
||||
type instanceBackOff struct {
|
||||
|
|
@ -63,7 +38,7 @@ func (i *instanceDeleteBackoff) ShouldProcess(key string) (bool, time.Time) {
|
|||
|
||||
now := time.Now().UTC()
|
||||
deadline := ib.lastRecordedFailureTime.Add(time.Duration(ib.backoffSeconds) * time.Second)
|
||||
return deadline.After(now), deadline
|
||||
return now.After(deadline), deadline
|
||||
}
|
||||
|
||||
func (i *instanceDeleteBackoff) Delete(key string) {
|
||||
75
locking/local_backoff_locker_test.go
Normal file
75
locking/local_backoff_locker_test.go
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
package locking
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type LockerBackoffTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
locker *instanceDeleteBackoff
|
||||
}
|
||||
|
||||
func (l *LockerBackoffTestSuite) SetupTest() {
|
||||
l.locker = &instanceDeleteBackoff{}
|
||||
}
|
||||
|
||||
func (l *LockerBackoffTestSuite) TearDownTest() {
|
||||
l.locker = nil
|
||||
}
|
||||
|
||||
func (l *LockerBackoffTestSuite) TestShouldProcess() {
|
||||
shouldProcess, deadline := l.locker.ShouldProcess("test")
|
||||
l.Require().True(shouldProcess)
|
||||
l.Require().Equal(time.Time{}, deadline)
|
||||
|
||||
l.locker.muxes.Store("test", &instanceBackOff{
|
||||
backoffSeconds: 0,
|
||||
lastRecordedFailureTime: time.Time{},
|
||||
})
|
||||
|
||||
shouldProcess, deadline = l.locker.ShouldProcess("test")
|
||||
l.Require().True(shouldProcess)
|
||||
l.Require().Equal(time.Time{}, deadline)
|
||||
|
||||
l.locker.muxes.Store("test", &instanceBackOff{
|
||||
backoffSeconds: 100,
|
||||
lastRecordedFailureTime: time.Now().UTC(),
|
||||
})
|
||||
|
||||
shouldProcess, deadline = l.locker.ShouldProcess("test")
|
||||
l.Require().False(shouldProcess)
|
||||
l.Require().NotEqual(time.Time{}, deadline)
|
||||
}
|
||||
|
||||
func (l *LockerBackoffTestSuite) TestRecordFailure() {
|
||||
l.locker.RecordFailure("test")
|
||||
|
||||
mux, ok := l.locker.muxes.Load("test")
|
||||
l.Require().True(ok)
|
||||
ib := mux.(*instanceBackOff)
|
||||
l.Require().NotNil(ib)
|
||||
l.Require().NotEqual(time.Time{}, ib.lastRecordedFailureTime)
|
||||
l.Require().Equal(float64(5), ib.backoffSeconds)
|
||||
|
||||
l.locker.RecordFailure("test")
|
||||
mux, ok = l.locker.muxes.Load("test")
|
||||
l.Require().True(ok)
|
||||
ib = mux.(*instanceBackOff)
|
||||
l.Require().NotNil(ib)
|
||||
l.Require().NotEqual(time.Time{}, ib.lastRecordedFailureTime)
|
||||
l.Require().Equal(7.5, ib.backoffSeconds)
|
||||
|
||||
l.locker.Delete("test")
|
||||
mux, ok = l.locker.muxes.Load("test")
|
||||
l.Require().False(ok)
|
||||
l.Require().Nil(mux)
|
||||
}
|
||||
|
||||
func TestBackoffTestSuite(t *testing.T) {
|
||||
t.Parallel()
|
||||
suite.Run(t, new(LockerBackoffTestSuite))
|
||||
}
|
||||
78
locking/local_locker.go
Normal file
78
locking/local_locker.go
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
package locking
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
dbCommon "github.com/cloudbase/garm/database/common"
|
||||
)
|
||||
|
||||
const (
|
||||
maxBackoffSeconds float64 = 1200 // 20 minutes
|
||||
)
|
||||
|
||||
func NewLocalLocker(_ context.Context, _ dbCommon.Store) (Locker, error) {
|
||||
return &keyMutex{}, nil
|
||||
}
|
||||
|
||||
type keyMutex struct {
|
||||
muxes sync.Map
|
||||
}
|
||||
|
||||
type lockWithIdent struct {
|
||||
mux sync.Mutex
|
||||
ident string
|
||||
}
|
||||
|
||||
var _ Locker = &keyMutex{}
|
||||
|
||||
func (k *keyMutex) TryLock(key, identifier string) bool {
|
||||
mux, _ := k.muxes.LoadOrStore(key, &lockWithIdent{
|
||||
mux: sync.Mutex{},
|
||||
})
|
||||
keyMux := mux.(*lockWithIdent)
|
||||
locked := keyMux.mux.TryLock()
|
||||
if locked {
|
||||
keyMux.ident = identifier
|
||||
}
|
||||
return locked
|
||||
}
|
||||
|
||||
func (k *keyMutex) Lock(key, identifier string) {
|
||||
mux, _ := k.muxes.LoadOrStore(key, &lockWithIdent{
|
||||
mux: sync.Mutex{},
|
||||
})
|
||||
keyMux := mux.(*lockWithIdent)
|
||||
keyMux.ident = identifier
|
||||
keyMux.mux.Lock()
|
||||
}
|
||||
|
||||
func (k *keyMutex) Unlock(key string, remove bool) {
|
||||
mux, ok := k.muxes.Load(key)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
keyMux := mux.(*lockWithIdent)
|
||||
if remove {
|
||||
k.Delete(key)
|
||||
}
|
||||
keyMux.ident = ""
|
||||
keyMux.mux.Unlock()
|
||||
}
|
||||
|
||||
func (k *keyMutex) Delete(key string) {
|
||||
k.muxes.Delete(key)
|
||||
}
|
||||
|
||||
func (k *keyMutex) LockedBy(key string) (string, bool) {
|
||||
mux, ok := k.muxes.Load(key)
|
||||
if !ok {
|
||||
return "", false
|
||||
}
|
||||
keyMux := mux.(*lockWithIdent)
|
||||
if keyMux.ident == "" {
|
||||
return "", false
|
||||
}
|
||||
|
||||
return keyMux.ident, true
|
||||
}
|
||||
228
locking/local_locker_test.go
Normal file
228
locking/local_locker_test.go
Normal file
|
|
@ -0,0 +1,228 @@
|
|||
package locking
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/suite"
|
||||
)
|
||||
|
||||
type LockerTestSuite struct {
|
||||
suite.Suite
|
||||
|
||||
mux *keyMutex
|
||||
}
|
||||
|
||||
func (l *LockerTestSuite) SetupTest() {
|
||||
l.mux = &keyMutex{}
|
||||
err := RegisterLocker(l.mux)
|
||||
l.Require().NoError(err, "should register the locker")
|
||||
}
|
||||
|
||||
func (l *LockerTestSuite) TearDownTest() {
|
||||
l.mux = nil
|
||||
locker = nil
|
||||
}
|
||||
|
||||
func (l *LockerTestSuite) TestLocalLockerLockUnlock() {
|
||||
l.mux.Lock("test", "test-identifier")
|
||||
mux, ok := l.mux.muxes.Load("test")
|
||||
l.Require().True(ok)
|
||||
keyMux := mux.(*lockWithIdent)
|
||||
l.Require().Equal("test-identifier", keyMux.ident)
|
||||
l.mux.Unlock("test", true)
|
||||
mux, ok = l.mux.muxes.Load("test")
|
||||
l.Require().False(ok)
|
||||
l.Require().Nil(mux)
|
||||
l.mux.Unlock("test", false)
|
||||
}
|
||||
|
||||
func (l *LockerTestSuite) TestLocalLockerTryLock() {
|
||||
locked := l.mux.TryLock("test", "test-identifier")
|
||||
l.Require().True(locked)
|
||||
mux, ok := l.mux.muxes.Load("test")
|
||||
l.Require().True(ok)
|
||||
keyMux := mux.(*lockWithIdent)
|
||||
l.Require().Equal("test-identifier", keyMux.ident)
|
||||
|
||||
locked = l.mux.TryLock("test", "another-identifier2")
|
||||
l.Require().False(locked)
|
||||
mux, ok = l.mux.muxes.Load("test")
|
||||
l.Require().True(ok)
|
||||
keyMux = mux.(*lockWithIdent)
|
||||
l.Require().Equal("test-identifier", keyMux.ident)
|
||||
|
||||
l.mux.Unlock("test", true)
|
||||
locked = l.mux.TryLock("test", "another-identifier2")
|
||||
l.Require().True(locked)
|
||||
mux, ok = l.mux.muxes.Load("test")
|
||||
l.Require().True(ok)
|
||||
keyMux = mux.(*lockWithIdent)
|
||||
l.Require().Equal("another-identifier2", keyMux.ident)
|
||||
l.mux.Unlock("test", true)
|
||||
}
|
||||
|
||||
func (l *LockerTestSuite) TestLocalLockertLockedBy() {
|
||||
l.mux.Lock("test", "test-identifier")
|
||||
identifier, ok := l.mux.LockedBy("test")
|
||||
l.Require().True(ok)
|
||||
l.Require().Equal("test-identifier", identifier)
|
||||
l.mux.Unlock("test", true)
|
||||
identifier, ok = l.mux.LockedBy("test")
|
||||
l.Require().False(ok)
|
||||
l.Require().Equal("", identifier)
|
||||
|
||||
l.mux.Lock("test", "test-identifier")
|
||||
identifier, ok = l.mux.LockedBy("test")
|
||||
l.Require().True(ok)
|
||||
l.Require().Equal("test-identifier", identifier)
|
||||
l.mux.Unlock("test", false)
|
||||
identifier, ok = l.mux.LockedBy("test")
|
||||
l.Require().False(ok)
|
||||
l.Require().Equal("", identifier)
|
||||
}
|
||||
|
||||
func (l *LockerTestSuite) TestLockerPanicsIfNotInitialized() {
|
||||
locker = nil
|
||||
l.Require().Panics(
|
||||
func() {
|
||||
Lock("test", "test-identifier")
|
||||
},
|
||||
"Lock should panic if locker is not initialized",
|
||||
)
|
||||
|
||||
l.Require().Panics(
|
||||
func() {
|
||||
TryLock("test", "test-identifier")
|
||||
},
|
||||
"TryLock should panic if locker is not initialized",
|
||||
)
|
||||
|
||||
l.Require().Panics(
|
||||
func() {
|
||||
Unlock("test", false)
|
||||
},
|
||||
"Unlock should panic if locker is not initialized",
|
||||
)
|
||||
|
||||
l.Require().Panics(
|
||||
func() {
|
||||
Delete("test")
|
||||
},
|
||||
"Delete should panic if locker is not initialized",
|
||||
)
|
||||
|
||||
l.Require().Panics(
|
||||
func() {
|
||||
LockedBy("test")
|
||||
},
|
||||
"LockedBy should panic if locker is not initialized",
|
||||
)
|
||||
}
|
||||
|
||||
func (l *LockerTestSuite) TestLockerAlreadyRegistered() {
|
||||
err := RegisterLocker(l.mux)
|
||||
l.Require().Error(err, "should not be able to register the same locker again")
|
||||
l.Require().Equal("locker already registered", err.Error())
|
||||
}
|
||||
|
||||
func (l *LockerTestSuite) TestLockerDelete() {
|
||||
Lock("test", "test-identifier")
|
||||
mux, ok := l.mux.muxes.Load("test")
|
||||
l.Require().True(ok)
|
||||
keyMux := mux.(*lockWithIdent)
|
||||
l.Require().Equal("test-identifier", keyMux.ident)
|
||||
|
||||
Delete("test")
|
||||
mux, ok = l.mux.muxes.Load("test")
|
||||
l.Require().False(ok)
|
||||
l.Require().Nil(mux)
|
||||
|
||||
identifier, ok := l.mux.LockedBy("test")
|
||||
l.Require().False(ok)
|
||||
l.Require().Equal("", identifier)
|
||||
}
|
||||
|
||||
func (l *LockerTestSuite) TestLockUnlock() {
|
||||
Lock("test", "test-identifier")
|
||||
mux, ok := l.mux.muxes.Load("test")
|
||||
l.Require().True(ok)
|
||||
keyMux := mux.(*lockWithIdent)
|
||||
l.Require().Equal("test-identifier", keyMux.ident)
|
||||
|
||||
Unlock("test", true)
|
||||
mux, ok = l.mux.muxes.Load("test")
|
||||
l.Require().False(ok)
|
||||
l.Require().Nil(mux)
|
||||
|
||||
identifier, ok := l.mux.LockedBy("test")
|
||||
l.Require().False(ok)
|
||||
l.Require().Equal("", identifier)
|
||||
}
|
||||
|
||||
func (l *LockerTestSuite) TestLockUnlockWithoutRemove() {
|
||||
Lock("test", "test-identifier")
|
||||
mux, ok := l.mux.muxes.Load("test")
|
||||
l.Require().True(ok)
|
||||
keyMux := mux.(*lockWithIdent)
|
||||
l.Require().Equal("test-identifier", keyMux.ident)
|
||||
|
||||
Unlock("test", false)
|
||||
mux, ok = l.mux.muxes.Load("test")
|
||||
l.Require().True(ok)
|
||||
keyMux = mux.(*lockWithIdent)
|
||||
l.Require().Equal("", keyMux.ident)
|
||||
|
||||
identifier, ok := l.mux.LockedBy("test")
|
||||
l.Require().False(ok)
|
||||
l.Require().Equal("", identifier)
|
||||
}
|
||||
|
||||
func (l *LockerTestSuite) TestTryLock() {
|
||||
locked := TryLock("test", "test-identifier")
|
||||
l.Require().True(locked)
|
||||
mux, ok := l.mux.muxes.Load("test")
|
||||
l.Require().True(ok)
|
||||
keyMux := mux.(*lockWithIdent)
|
||||
l.Require().Equal("test-identifier", keyMux.ident)
|
||||
|
||||
locked = TryLock("test", "another-identifier2")
|
||||
l.Require().False(locked)
|
||||
mux, ok = l.mux.muxes.Load("test")
|
||||
l.Require().True(ok)
|
||||
keyMux = mux.(*lockWithIdent)
|
||||
l.Require().Equal("test-identifier", keyMux.ident)
|
||||
|
||||
Unlock("test", true)
|
||||
locked = TryLock("test", "another-identifier2")
|
||||
l.Require().True(locked)
|
||||
mux, ok = l.mux.muxes.Load("test")
|
||||
l.Require().True(ok)
|
||||
keyMux = mux.(*lockWithIdent)
|
||||
l.Require().Equal("another-identifier2", keyMux.ident)
|
||||
Unlock("test", true)
|
||||
}
|
||||
|
||||
func (l *LockerTestSuite) TestLockedBy() {
|
||||
Lock("test", "test-identifier")
|
||||
identifier, ok := LockedBy("test")
|
||||
l.Require().True(ok)
|
||||
l.Require().Equal("test-identifier", identifier)
|
||||
Unlock("test", true)
|
||||
identifier, ok = LockedBy("test")
|
||||
l.Require().False(ok)
|
||||
l.Require().Equal("", identifier)
|
||||
|
||||
Lock("test", "test-identifier2")
|
||||
identifier, ok = LockedBy("test")
|
||||
l.Require().True(ok)
|
||||
l.Require().Equal("test-identifier2", identifier)
|
||||
Unlock("test", false)
|
||||
identifier, ok = LockedBy("test")
|
||||
l.Require().False(ok)
|
||||
l.Require().Equal("", identifier)
|
||||
}
|
||||
|
||||
func TestLockerTestSuite(t *testing.T) {
|
||||
t.Parallel()
|
||||
suite.Run(t, new(LockerTestSuite))
|
||||
}
|
||||
76
locking/locking.go
Normal file
76
locking/locking.go
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
package locking
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"runtime"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var locker Locker
|
||||
|
||||
var lockerMux = sync.Mutex{}
|
||||
|
||||
func TryLock(key, identifier string) (ok bool) {
|
||||
if locker == nil {
|
||||
panic("no locker is registered")
|
||||
}
|
||||
|
||||
_, filename, line, _ := runtime.Caller(1)
|
||||
slog.Debug("attempting to try lock", "key", key, "identifier", identifier, "caller", fmt.Sprintf("%s:%d", filename, line))
|
||||
defer slog.Debug("try lock returned", "key", key, "identifier", identifier, "locked", ok, "caller", fmt.Sprintf("%s:%d", filename, line))
|
||||
|
||||
ok = locker.TryLock(key, identifier)
|
||||
return ok
|
||||
}
|
||||
|
||||
func Lock(key, identifier string) {
|
||||
if locker == nil {
|
||||
panic("no locker is registered")
|
||||
}
|
||||
|
||||
_, filename, line, _ := runtime.Caller(1)
|
||||
slog.Debug("attempting to lock", "key", key, "identifier", identifier, "caller", fmt.Sprintf("%s:%d", filename, line))
|
||||
defer slog.Debug("lock acquired", "key", key, "identifier", identifier, "caller", fmt.Sprintf("%s:%d", filename, line))
|
||||
|
||||
locker.Lock(key, identifier)
|
||||
}
|
||||
|
||||
func Unlock(key string, remove bool) {
|
||||
if locker == nil {
|
||||
panic("no locker is registered")
|
||||
}
|
||||
|
||||
_, filename, line, _ := runtime.Caller(1)
|
||||
slog.Debug("attempting to unlock", "key", key, "remove", remove, "caller", fmt.Sprintf("%s:%d", filename, line))
|
||||
defer slog.Debug("unlock completed", "key", key, "remove", remove, "caller", fmt.Sprintf("%s:%d", filename, line))
|
||||
locker.Unlock(key, remove)
|
||||
}
|
||||
|
||||
func LockedBy(key string) (string, bool) {
|
||||
if locker == nil {
|
||||
panic("no locker is registered")
|
||||
}
|
||||
|
||||
return locker.LockedBy(key)
|
||||
}
|
||||
|
||||
func Delete(key string) {
|
||||
if locker == nil {
|
||||
panic("no locker is registered")
|
||||
}
|
||||
|
||||
locker.Delete(key)
|
||||
}
|
||||
|
||||
func RegisterLocker(lock Locker) error {
|
||||
lockerMux.Lock()
|
||||
defer lockerMux.Unlock()
|
||||
|
||||
if locker != nil {
|
||||
return fmt.Errorf("locker already registered")
|
||||
}
|
||||
|
||||
locker = lock
|
||||
return nil
|
||||
}
|
||||
352
params/github.go
352
params/github.go
|
|
@ -14,7 +14,16 @@
|
|||
|
||||
package params
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"encoding/base64"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"time"
|
||||
|
||||
jwt "github.com/golang-jwt/jwt/v5"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type Event string
|
||||
|
||||
|
|
@ -208,3 +217,344 @@ type WorkflowJob struct {
|
|||
SiteAdmin bool `json:"site_admin"`
|
||||
} `json:"sender"`
|
||||
}
|
||||
|
||||
type RunnerSetting struct {
|
||||
Ephemeral bool `json:"ephemeral,omitempty"`
|
||||
IsElastic bool `json:"isElastic,omitempty"`
|
||||
DisableUpdate bool `json:"disableUpdate,omitempty"`
|
||||
}
|
||||
|
||||
type Label struct {
|
||||
Type string `json:"type"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type RunnerScaleSetStatistic struct {
|
||||
TotalAvailableJobs int `json:"totalAvailableJobs"`
|
||||
TotalAcquiredJobs int `json:"totalAcquiredJobs"`
|
||||
TotalAssignedJobs int `json:"totalAssignedJobs"`
|
||||
TotalRunningJobs int `json:"totalRunningJobs"`
|
||||
TotalRegisteredRunners int `json:"totalRegisteredRunners"`
|
||||
TotalBusyRunners int `json:"totalBusyRunners"`
|
||||
TotalIdleRunners int `json:"totalIdleRunners"`
|
||||
}
|
||||
|
||||
type RunnerScaleSet struct {
|
||||
ID int `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
RunnerGroupID int64 `json:"runnerGroupId,omitempty"`
|
||||
RunnerGroupName string `json:"runnerGroupName,omitempty"`
|
||||
Labels []Label `json:"labels,omitempty"`
|
||||
RunnerSetting RunnerSetting `json:"RunnerSetting,omitempty"`
|
||||
CreatedOn time.Time `json:"createdOn,omitempty"`
|
||||
RunnerJitConfigURL string `json:"runnerJitConfigUrl,omitempty"`
|
||||
GetAcquirableJobsURL string `json:"getAcquirableJobsUrl,omitempty"`
|
||||
AcquireJobsURL string `json:"acquireJobsUrl,omitempty"`
|
||||
Statistics *RunnerScaleSetStatistic `json:"statistics,omitempty"`
|
||||
Status interface{} `json:"status,omitempty"`
|
||||
Enabled *bool `json:"enabled,omitempty"`
|
||||
}
|
||||
|
||||
type RunnerScaleSetsResponse struct {
|
||||
Count int `json:"count"`
|
||||
RunnerScaleSets []RunnerScaleSet `json:"value"`
|
||||
}
|
||||
|
||||
type ActionsServiceAdminInfoResponse struct {
|
||||
URL string `json:"url,omitempty"`
|
||||
Token string `json:"token,omitempty"`
|
||||
}
|
||||
|
||||
func (a ActionsServiceAdminInfoResponse) GetURL() (*url.URL, error) {
|
||||
if a.URL == "" {
|
||||
return nil, fmt.Errorf("no url specified")
|
||||
}
|
||||
u, err := url.ParseRequestURI(a.URL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse URL: %w", err)
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func (a ActionsServiceAdminInfoResponse) getJWT() (*jwt.Token, error) {
|
||||
// We're parsing a token we got from the GitHub API. We can't verify its signature.
|
||||
// We do need the expiration date however, or other info.
|
||||
token, _, err := jwt.NewParser().ParseUnverified(a.Token, &jwt.RegisteredClaims{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse jwt token: %w", err)
|
||||
}
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func (a ActionsServiceAdminInfoResponse) ExiresAt() (time.Time, error) {
|
||||
jwt, err := a.getJWT()
|
||||
if err != nil {
|
||||
return time.Time{}, fmt.Errorf("failed to decode jwt token: %w", err)
|
||||
}
|
||||
expiration, err := jwt.Claims.GetExpirationTime()
|
||||
if err != nil {
|
||||
return time.Time{}, fmt.Errorf("failed to get expiration time: %w", err)
|
||||
}
|
||||
|
||||
return expiration.Time, nil
|
||||
}
|
||||
|
||||
func (a ActionsServiceAdminInfoResponse) IsExpired() bool {
|
||||
if exp, err := a.ExiresAt(); err == nil {
|
||||
return time.Now().UTC().After(exp)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (a ActionsServiceAdminInfoResponse) TimeRemaining() (time.Duration, error) {
|
||||
exp, err := a.ExiresAt()
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to get expiration: %w", err)
|
||||
}
|
||||
now := time.Now().UTC()
|
||||
return exp.Sub(now), nil
|
||||
}
|
||||
|
||||
func (a ActionsServiceAdminInfoResponse) ExpiresIn(t time.Duration) bool {
|
||||
remaining, err := a.TimeRemaining()
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
return remaining <= t
|
||||
}
|
||||
|
||||
type ActionsServiceAdminInfoRequest struct {
|
||||
URL string `json:"url,omitempty"`
|
||||
RunnerEvent string `json:"runner_event,omitempty"`
|
||||
}
|
||||
|
||||
type RunnerScaleSetSession struct {
|
||||
SessionID *uuid.UUID `json:"sessionId,omitempty"`
|
||||
OwnerName string `json:"ownerName,omitempty"`
|
||||
RunnerScaleSet *RunnerScaleSet `json:"runnerScaleSet,omitempty"`
|
||||
MessageQueueURL string `json:"messageQueueUrl,omitempty"`
|
||||
MessageQueueAccessToken string `json:"messageQueueAccessToken,omitempty"`
|
||||
Statistics *RunnerScaleSetStatistic `json:"statistics,omitempty"`
|
||||
}
|
||||
|
||||
func (a RunnerScaleSetSession) GetURL() (*url.URL, error) {
|
||||
if a.MessageQueueURL == "" {
|
||||
return nil, fmt.Errorf("no url specified")
|
||||
}
|
||||
u, err := url.ParseRequestURI(a.MessageQueueURL)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse URL: %w", err)
|
||||
}
|
||||
return u, nil
|
||||
}
|
||||
|
||||
func (a RunnerScaleSetSession) getJWT() (*jwt.Token, error) {
|
||||
// We're parsing a token we got from the GitHub API. We can't verify its signature.
|
||||
// We do need the expiration date however, or other info.
|
||||
token, _, err := jwt.NewParser().ParseUnverified(a.MessageQueueAccessToken, &jwt.RegisteredClaims{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to parse jwt token: %w", err)
|
||||
}
|
||||
return token, nil
|
||||
}
|
||||
|
||||
func (a RunnerScaleSetSession) ExiresAt() (time.Time, error) {
|
||||
jwt, err := a.getJWT()
|
||||
if err != nil {
|
||||
return time.Time{}, fmt.Errorf("failed to decode jwt token: %w", err)
|
||||
}
|
||||
expiration, err := jwt.Claims.GetExpirationTime()
|
||||
if err != nil {
|
||||
return time.Time{}, fmt.Errorf("failed to get expiration time: %w", err)
|
||||
}
|
||||
|
||||
return expiration.Time, nil
|
||||
}
|
||||
|
||||
func (a RunnerScaleSetSession) IsExpired() bool {
|
||||
if exp, err := a.ExiresAt(); err == nil {
|
||||
return time.Now().UTC().After(exp)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (a RunnerScaleSetSession) TimeRemaining() (time.Duration, error) {
|
||||
exp, err := a.ExiresAt()
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to get expiration: %w", err)
|
||||
}
|
||||
now := time.Now().UTC()
|
||||
return exp.Sub(now), nil
|
||||
}
|
||||
|
||||
func (a RunnerScaleSetSession) ExpiresIn(t time.Duration) bool {
|
||||
remaining, err := a.TimeRemaining()
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
return remaining <= t
|
||||
}
|
||||
|
||||
type RunnerScaleSetMessage struct {
|
||||
MessageID int64 `json:"messageId"`
|
||||
MessageType string `json:"messageType"`
|
||||
Body string `json:"body"`
|
||||
Statistics *RunnerScaleSetStatistic `json:"statistics"`
|
||||
}
|
||||
|
||||
func (r RunnerScaleSetMessage) IsNil() bool {
|
||||
return r.MessageID == 0 && r.MessageType == "" && r.Body == "" && r.Statistics == nil
|
||||
}
|
||||
|
||||
func (r RunnerScaleSetMessage) GetJobsFromBody() ([]ScaleSetJobMessage, error) {
|
||||
var body []ScaleSetJobMessage
|
||||
if r.Body == "" {
|
||||
return nil, fmt.Errorf("no body specified")
|
||||
}
|
||||
|
||||
if err := json.Unmarshal([]byte(r.Body), &body); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal body: %w", err)
|
||||
}
|
||||
return body, nil
|
||||
}
|
||||
|
||||
type RunnerReference struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
OS string `json:"os"`
|
||||
RunnerScaleSetID int `json:"runnerScaleSetId"`
|
||||
CreatedOn interface{} `json:"createdOn"`
|
||||
RunnerGroupID uint64 `json:"runnerGroupId"`
|
||||
RunnerGroupName string `json:"runnerGroupName"`
|
||||
Version string `json:"version"`
|
||||
Enabled bool `json:"enabled"`
|
||||
Ephemeral bool `json:"ephemeral"`
|
||||
Status interface{} `json:"status"`
|
||||
DisableUpdate bool `json:"disableUpdate"`
|
||||
ProvisioningState string `json:"provisioningState"`
|
||||
Busy bool `json:"busy"`
|
||||
Labels []Label `json:"labels,omitempty"`
|
||||
}
|
||||
|
||||
func (r RunnerReference) GetStatus() RunnerStatus {
|
||||
status, ok := r.Status.(string)
|
||||
if !ok {
|
||||
return RunnerUnknown
|
||||
}
|
||||
runnerStatus := RunnerStatus(status)
|
||||
if !runnerStatus.IsValid() {
|
||||
return RunnerUnknown
|
||||
}
|
||||
|
||||
if runnerStatus == RunnerOnline {
|
||||
if r.Busy {
|
||||
return RunnerActive
|
||||
}
|
||||
return RunnerIdle
|
||||
}
|
||||
return runnerStatus
|
||||
}
|
||||
|
||||
type RunnerScaleSetJitRunnerConfig struct {
|
||||
Runner *RunnerReference `json:"runner"`
|
||||
EncodedJITConfig string `json:"encodedJITConfig"`
|
||||
}
|
||||
|
||||
func (r RunnerScaleSetJitRunnerConfig) DecodedJITConfig() (map[string]string, error) {
|
||||
if r.EncodedJITConfig == "" {
|
||||
return nil, fmt.Errorf("no encoded JIT config specified")
|
||||
}
|
||||
decoded, err := base64.StdEncoding.DecodeString(r.EncodedJITConfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to decode JIT config: %w", err)
|
||||
}
|
||||
jitConfig := make(map[string]string)
|
||||
if err := json.Unmarshal(decoded, &jitConfig); err != nil {
|
||||
return nil, fmt.Errorf("failed to unmarshal JIT config: %w", err)
|
||||
}
|
||||
return jitConfig, nil
|
||||
}
|
||||
|
||||
type RunnerReferenceList struct {
|
||||
Count int `json:"count"`
|
||||
RunnerReferences []RunnerReference `json:"value"`
|
||||
}
|
||||
|
||||
type AcquirableJobList struct {
|
||||
Count int `json:"count"`
|
||||
Jobs []AcquirableJob `json:"value"`
|
||||
}
|
||||
|
||||
type AcquirableJob struct {
|
||||
AcquireJobURL string `json:"acquireJobUrl"`
|
||||
MessageType string `json:"messageType"`
|
||||
RunnerRequestID int64 `json:"run0ne00rRequestId"`
|
||||
RepositoryName string `json:"repositoryName"`
|
||||
OwnerName string `json:"ownerName"`
|
||||
JobWorkflowRef string `json:"jobWorkflowRef"`
|
||||
EventName string `json:"eventName"`
|
||||
RequestLabels []string `json:"requestLabels"`
|
||||
}
|
||||
|
||||
type RunnerGroup struct {
|
||||
ID int64 `json:"id"`
|
||||
Name string `json:"name"`
|
||||
Size int64 `json:"size"`
|
||||
IsDefault bool `json:"isDefaultGroup"`
|
||||
}
|
||||
|
||||
type RunnerGroupList struct {
|
||||
Count int `json:"count"`
|
||||
RunnerGroups []RunnerGroup `json:"value"`
|
||||
}
|
||||
|
||||
type ScaleSetJobMessage struct {
|
||||
MessageType string `json:"messageType,omitempty"`
|
||||
RunnerRequestID int64 `json:"runnerRequestId,omitempty"`
|
||||
RepositoryName string `json:"repositoryName,omitempty"`
|
||||
OwnerName string `json:"ownerName,omitempty"`
|
||||
JobWorkflowRef string `json:"jobWorkflowRef,omitempty"`
|
||||
JobDisplayName string `json:"jobDisplayName,omitempty"`
|
||||
WorkflowRunID int64 `json:"workflowRunId,omitempty"`
|
||||
EventName string `json:"eventName,omitempty"`
|
||||
RequestLabels []string `json:"requestLabels,omitempty"`
|
||||
QueueTime time.Time `json:"queueTime,omitempty"`
|
||||
ScaleSetAssignTime time.Time `json:"scaleSetAssignTime,omitempty"`
|
||||
RunnerAssignTime time.Time `json:"runnerAssignTime,omitempty"`
|
||||
FinishTime time.Time `json:"finishTime,omitempty"`
|
||||
Result string `json:"result,omitempty"`
|
||||
RunnerID int64 `json:"runnerId,omitempty"`
|
||||
RunnerName string `json:"runnerName,omitempty"`
|
||||
AcquireJobURL string `json:"acquireJobUrl,omitempty"`
|
||||
}
|
||||
|
||||
func (s ScaleSetJobMessage) MessageTypeToStatus() JobStatus {
|
||||
switch s.MessageType {
|
||||
case MessageTypeJobAssigned:
|
||||
return JobStatusQueued
|
||||
case MessageTypeJobStarted:
|
||||
return JobStatusInProgress
|
||||
case MessageTypeJobCompleted:
|
||||
return JobStatusCompleted
|
||||
default:
|
||||
return JobStatusQueued
|
||||
}
|
||||
}
|
||||
|
||||
func (s ScaleSetJobMessage) ToJob() Job {
|
||||
return Job{
|
||||
ID: s.RunnerRequestID,
|
||||
Action: s.EventName,
|
||||
RunID: s.WorkflowRunID,
|
||||
Status: string(s.MessageTypeToStatus()),
|
||||
Conclusion: s.Result,
|
||||
CompletedAt: s.FinishTime,
|
||||
StartedAt: s.RunnerAssignTime,
|
||||
Name: s.JobDisplayName,
|
||||
GithubRunnerID: s.RunnerID,
|
||||
RunnerName: s.RunnerName,
|
||||
RepositoryName: s.RepositoryName,
|
||||
RepositoryOwner: s.OwnerName,
|
||||
Labels: s.RequestLabels,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
7
params/interfaces.go
Normal file
7
params/interfaces.go
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
package params
|
||||
|
||||
// EntityGetter is implemented by all github entities (repositories, organizations and enterprises).
|
||||
// It defines the GetEntity() function which returns a github entity.
|
||||
type EntityGetter interface {
|
||||
GetEntity() (GithubEntity, error)
|
||||
}
|
||||
188
params/params.go
188
params/params.go
|
|
@ -22,11 +22,12 @@ import (
|
|||
"encoding/json"
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"math"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/bradleyfalzon/ghinstallation/v2"
|
||||
"github.com/google/go-github/v57/github"
|
||||
"github.com/google/go-github/v71/github"
|
||||
"github.com/google/uuid"
|
||||
"golang.org/x/oauth2"
|
||||
|
||||
|
|
@ -44,8 +45,22 @@ type (
|
|||
WebhookEndpointType string
|
||||
GithubAuthType string
|
||||
PoolBalancerType string
|
||||
ScaleSetState string
|
||||
ScaleSetMessageType string
|
||||
)
|
||||
|
||||
func (s RunnerStatus) IsValid() bool {
|
||||
switch s {
|
||||
case RunnerIdle, RunnerPending, RunnerTerminated,
|
||||
RunnerInstalling, RunnerFailed,
|
||||
RunnerActive, RunnerOffline,
|
||||
RunnerUnknown, RunnerOnline:
|
||||
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
const (
|
||||
// PoolBalancerTypeRoundRobin will try to cycle through the pools of an entity
|
||||
// in a round robin fashion. For example, if a repository has multiple pools that
|
||||
|
|
@ -114,6 +129,9 @@ const (
|
|||
RunnerInstalling RunnerStatus = "installing"
|
||||
RunnerFailed RunnerStatus = "failed"
|
||||
RunnerActive RunnerStatus = "active"
|
||||
RunnerOffline RunnerStatus = "offline"
|
||||
RunnerOnline RunnerStatus = "online"
|
||||
RunnerUnknown RunnerStatus = "unknown"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -127,6 +145,25 @@ func (e GithubEntityType) String() string {
|
|||
return string(e)
|
||||
}
|
||||
|
||||
const (
|
||||
ScaleSetPendingCreate ScaleSetState = "pending_create"
|
||||
ScaleSetCreated ScaleSetState = "created"
|
||||
ScaleSetError ScaleSetState = "error"
|
||||
ScaleSetPendingDelete ScaleSetState = "pending_delete"
|
||||
ScaleSetPendingForceDelete ScaleSetState = "pending_force_delete"
|
||||
)
|
||||
|
||||
const (
|
||||
MessageTypeRunnerScaleSetJobMessages ScaleSetMessageType = "RunnerScaleSetJobMessages"
|
||||
)
|
||||
|
||||
const (
|
||||
MessageTypeJobAssigned = "JobAssigned"
|
||||
MessageTypeJobCompleted = "JobCompleted"
|
||||
MessageTypeJobStarted = "JobStarted"
|
||||
MessageTypeJobAvailable = "JobAvailable"
|
||||
)
|
||||
|
||||
type StatusMessage struct {
|
||||
CreatedAt time.Time `json:"created_at,omitempty"`
|
||||
Message string `json:"message,omitempty"`
|
||||
|
|
@ -143,6 +180,10 @@ type Instance struct {
|
|||
// instance in the provider.
|
||||
ProviderID string `json:"provider_id,omitempty"`
|
||||
|
||||
// ProviderName is the name of the IaaS where the instance was
|
||||
// created.
|
||||
ProviderName string `json:"provider_name"`
|
||||
|
||||
// AgentID is the github runner agent ID.
|
||||
AgentID int64 `json:"agent_id,omitempty"`
|
||||
|
||||
|
|
@ -178,6 +219,9 @@ type Instance struct {
|
|||
// PoolID is the ID of the garm pool to which a runner belongs.
|
||||
PoolID string `json:"pool_id,omitempty"`
|
||||
|
||||
// ScaleSetID is the ID of the scale set to which a runner belongs.
|
||||
ScaleSetID uint `json:"scale_set_id,omitempty"`
|
||||
|
||||
// ProviderFault holds any error messages captured from the IaaS provider that is
|
||||
// responsible for managing the lifecycle of the runner.
|
||||
ProviderFault []byte `json:"provider_fault,omitempty"`
|
||||
|
|
@ -326,7 +370,22 @@ type Pool struct {
|
|||
Priority uint `json:"priority,omitempty"`
|
||||
}
|
||||
|
||||
func (p Pool) GithubEntity() (GithubEntity, error) {
|
||||
func (p Pool) MinIdleRunnersAsInt() int {
|
||||
if p.MinIdleRunners > math.MaxInt {
|
||||
return math.MaxInt
|
||||
}
|
||||
|
||||
return int(p.MinIdleRunners)
|
||||
}
|
||||
|
||||
func (p Pool) MaxRunnersAsInt() int {
|
||||
if p.MaxRunners > math.MaxInt {
|
||||
return math.MaxInt
|
||||
}
|
||||
return int(p.MaxRunners)
|
||||
}
|
||||
|
||||
func (p Pool) GetEntity() (GithubEntity, error) {
|
||||
switch p.PoolType() {
|
||||
case GithubEntityTypeRepository:
|
||||
return GithubEntity{
|
||||
|
|
@ -387,6 +446,100 @@ func (p *Pool) HasRequiredLabels(set []string) bool {
|
|||
// used by swagger client generated code
|
||||
type Pools []Pool
|
||||
|
||||
type ScaleSet struct {
|
||||
RunnerPrefix
|
||||
|
||||
ID uint `json:"id,omitempty"`
|
||||
ScaleSetID int `json:"scale_set_id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
DisableUpdate bool `json:"disable_update"`
|
||||
|
||||
State ScaleSetState `json:"state"`
|
||||
ExtendedState string `json:"extended_state,omitempty"`
|
||||
|
||||
ProviderName string `json:"provider_name,omitempty"`
|
||||
MaxRunners uint `json:"max_runners,omitempty"`
|
||||
MinIdleRunners uint `json:"min_idle_runners,omitempty"`
|
||||
Image string `json:"image,omitempty"`
|
||||
Flavor string `json:"flavor,omitempty"`
|
||||
OSType commonParams.OSType `json:"os_type,omitempty"`
|
||||
OSArch commonParams.OSArch `json:"os_arch,omitempty"`
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
Instances []Instance `json:"instances,omitempty"`
|
||||
DesiredRunnerCount int `json:"desired_runner_count,omitempty"`
|
||||
|
||||
RunnerBootstrapTimeout uint `json:"runner_bootstrap_timeout,omitempty"`
|
||||
// ExtraSpecs is an opaque raw json that gets sent to the provider
|
||||
// as part of the bootstrap params for instances. It can contain
|
||||
// any kind of data needed by providers. The contents of this field means
|
||||
// nothing to garm itself. We don't act on the information in this field at
|
||||
// all. We only validate that it's a proper json.
|
||||
ExtraSpecs json.RawMessage `json:"extra_specs,omitempty"`
|
||||
// GithubRunnerGroup is the github runner group in which the runners will be added.
|
||||
// The runner group must be created by someone with access to the enterprise.
|
||||
GitHubRunnerGroup string `json:"github-runner-group,omitempty"`
|
||||
|
||||
StatusMessages []StatusMessage `json:"status_messages"`
|
||||
|
||||
RepoID string `json:"repo_id,omitempty"`
|
||||
RepoName string `json:"repo_name,omitempty"`
|
||||
|
||||
OrgID string `json:"org_id,omitempty"`
|
||||
OrgName string `json:"org_name,omitempty"`
|
||||
|
||||
EnterpriseID string `json:"enterprise_id,omitempty"`
|
||||
EnterpriseName string `json:"enterprise_name,omitempty"`
|
||||
|
||||
LastMessageID int64 `json:"-"`
|
||||
}
|
||||
|
||||
func (p ScaleSet) GetEntity() (GithubEntity, error) {
|
||||
switch p.ScaleSetType() {
|
||||
case GithubEntityTypeRepository:
|
||||
return GithubEntity{
|
||||
ID: p.RepoID,
|
||||
EntityType: GithubEntityTypeRepository,
|
||||
}, nil
|
||||
case GithubEntityTypeOrganization:
|
||||
return GithubEntity{
|
||||
ID: p.OrgID,
|
||||
EntityType: GithubEntityTypeOrganization,
|
||||
}, nil
|
||||
case GithubEntityTypeEnterprise:
|
||||
return GithubEntity{
|
||||
ID: p.EnterpriseID,
|
||||
EntityType: GithubEntityTypeEnterprise,
|
||||
}, nil
|
||||
}
|
||||
return GithubEntity{}, fmt.Errorf("pool has no associated entity")
|
||||
}
|
||||
|
||||
func (p *ScaleSet) ScaleSetType() GithubEntityType {
|
||||
switch {
|
||||
case p.RepoID != "":
|
||||
return GithubEntityTypeRepository
|
||||
case p.OrgID != "":
|
||||
return GithubEntityTypeOrganization
|
||||
case p.EnterpriseID != "":
|
||||
return GithubEntityTypeEnterprise
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (p ScaleSet) GetID() uint {
|
||||
return p.ID
|
||||
}
|
||||
|
||||
func (p *ScaleSet) RunnerTimeout() uint {
|
||||
if p.RunnerBootstrapTimeout == 0 {
|
||||
return appdefaults.DefaultRunnerBootstrapTimeout
|
||||
}
|
||||
return p.RunnerBootstrapTimeout
|
||||
}
|
||||
|
||||
// used by swagger client generated code
|
||||
type ScaleSets []ScaleSet
|
||||
|
||||
type Repository struct {
|
||||
ID string `json:"id,omitempty"`
|
||||
Owner string `json:"owner,omitempty"`
|
||||
|
|
@ -611,6 +764,14 @@ type ControllerInfo struct {
|
|||
Version string `json:"version,omitempty"`
|
||||
}
|
||||
|
||||
func (c *ControllerInfo) JobBackoff() time.Duration {
|
||||
if math.MaxInt64 > c.MinimumJobAgeBackoff {
|
||||
return time.Duration(math.MaxInt64)
|
||||
}
|
||||
|
||||
return time.Duration(int64(c.MinimumJobAgeBackoff))
|
||||
}
|
||||
|
||||
type GithubCredentials struct {
|
||||
ID uint `json:"id,omitempty"`
|
||||
Name string `json:"name,omitempty"`
|
||||
|
|
@ -837,6 +998,18 @@ type GithubEntity struct {
|
|||
WebhookSecret string `json:"-"`
|
||||
}
|
||||
|
||||
func (g *GithubEntity) GithubURL() string {
|
||||
switch g.EntityType {
|
||||
case GithubEntityTypeRepository:
|
||||
return fmt.Sprintf("%s/%s/%s", g.Credentials.BaseURL, g.Owner, g.Name)
|
||||
case GithubEntityTypeOrganization:
|
||||
return fmt.Sprintf("%s/%s", g.Credentials.BaseURL, g.Owner)
|
||||
case GithubEntityTypeEnterprise:
|
||||
return fmt.Sprintf("%s/enterprises/%s", g.Credentials.BaseURL, g.Owner)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (g GithubEntity) GetPoolBalancerType() PoolBalancerType {
|
||||
if g.PoolBalancerType == "" {
|
||||
return PoolBalancerTypeRoundRobin
|
||||
|
|
@ -866,6 +1039,17 @@ func (g GithubEntity) String() string {
|
|||
return ""
|
||||
}
|
||||
|
||||
func (g GithubEntity) GetIDAsUUID() (uuid.UUID, error) {
|
||||
if g.ID == "" {
|
||||
return uuid.Nil, nil
|
||||
}
|
||||
id, err := uuid.Parse(g.ID)
|
||||
if err != nil {
|
||||
return uuid.Nil, fmt.Errorf("failed to parse entity ID: %w", err)
|
||||
}
|
||||
return id, nil
|
||||
}
|
||||
|
||||
// used by swagger client generated code
|
||||
type GithubEndpoints []GithubEndpoint
|
||||
|
||||
|
|
|
|||
|
|
@ -533,3 +533,76 @@ func (u UpdateControllerParams) Validate() error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
type CreateScaleSetParams struct {
|
||||
RunnerPrefix
|
||||
|
||||
Name string `json:"name"`
|
||||
DisableUpdate bool `json:"disable_update"`
|
||||
ScaleSetID int `json:"scale_set_id"`
|
||||
|
||||
ProviderName string `json:"provider_name,omitempty"`
|
||||
MaxRunners uint `json:"max_runners,omitempty"`
|
||||
MinIdleRunners uint `json:"min_idle_runners,omitempty"`
|
||||
Image string `json:"image,omitempty"`
|
||||
Flavor string `json:"flavor,omitempty"`
|
||||
OSType commonParams.OSType `json:"os_type,omitempty"`
|
||||
OSArch commonParams.OSArch `json:"os_arch,omitempty"`
|
||||
Tags []string `json:"tags,omitempty"`
|
||||
Enabled bool `json:"enabled,omitempty"`
|
||||
RunnerBootstrapTimeout uint `json:"runner_bootstrap_timeout,omitempty"`
|
||||
ExtraSpecs json.RawMessage `json:"extra_specs,omitempty"`
|
||||
// GithubRunnerGroup is the github runner group in which the runners of this
|
||||
// pool will be added to.
|
||||
// The runner group must be created by someone with access to the enterprise.
|
||||
GitHubRunnerGroup string `json:"github-runner-group,omitempty"`
|
||||
}
|
||||
|
||||
func (s *CreateScaleSetParams) Validate() error {
|
||||
if s.ProviderName == "" {
|
||||
return fmt.Errorf("missing provider")
|
||||
}
|
||||
|
||||
if s.MinIdleRunners > s.MaxRunners {
|
||||
return fmt.Errorf("min_idle_runners cannot be larger than max_runners")
|
||||
}
|
||||
|
||||
if s.MaxRunners == 0 {
|
||||
return fmt.Errorf("max_runners cannot be 0")
|
||||
}
|
||||
|
||||
if s.Flavor == "" {
|
||||
return fmt.Errorf("missing flavor")
|
||||
}
|
||||
|
||||
if s.Image == "" {
|
||||
return fmt.Errorf("missing image")
|
||||
}
|
||||
|
||||
if s.Name == "" {
|
||||
return fmt.Errorf("missing scale set name")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type UpdateScaleSetParams struct {
|
||||
RunnerPrefix
|
||||
|
||||
Name string `json:"name,omitempty"`
|
||||
Enabled *bool `json:"enabled,omitempty"`
|
||||
MaxRunners *uint `json:"max_runners,omitempty"`
|
||||
MinIdleRunners *uint `json:"min_idle_runners,omitempty"`
|
||||
RunnerBootstrapTimeout *uint `json:"runner_bootstrap_timeout,omitempty"`
|
||||
Image string `json:"image,omitempty"`
|
||||
Flavor string `json:"flavor,omitempty"`
|
||||
OSType commonParams.OSType `json:"os_type,omitempty"`
|
||||
OSArch commonParams.OSArch `json:"os_arch,omitempty"`
|
||||
ExtraSpecs json.RawMessage `json:"extra_specs,omitempty"`
|
||||
// GithubRunnerGroup is the github runner group in which the runners of this
|
||||
// pool will be added to.
|
||||
// The runner group must be created by someone with access to the enterprise.
|
||||
GitHubRunnerGroup *string `json:"runner_group,omitempty"`
|
||||
State *ScaleSetState `json:"state"`
|
||||
ExtendedState *string `json:"extended_state"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,14 +1,16 @@
|
|||
// Code generated by mockery v2.42.0. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.3. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
github "github.com/google/go-github/v57/github"
|
||||
github "github.com/google/go-github/v71/github"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
params "github.com/cloudbase/garm/params"
|
||||
|
||||
url "net/url"
|
||||
)
|
||||
|
||||
// GithubClient is an autogenerated mock type for the GithubClient type
|
||||
|
|
@ -115,6 +117,24 @@ func (_m *GithubClient) DeleteEntityHook(ctx context.Context, id int64) (*github
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// GetEntity provides a mock function with no fields
|
||||
func (_m *GithubClient) GetEntity() params.GithubEntity {
|
||||
ret := _m.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetEntity")
|
||||
}
|
||||
|
||||
var r0 params.GithubEntity
|
||||
if rf, ok := ret.Get(0).(func() params.GithubEntity); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(params.GithubEntity)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// GetEntityHook provides a mock function with given fields: ctx, id
|
||||
func (_m *GithubClient) GetEntityHook(ctx context.Context, id int64) (*github.Hook, error) {
|
||||
ret := _m.Called(ctx, id)
|
||||
|
|
@ -223,6 +243,26 @@ func (_m *GithubClient) GetWorkflowJobByID(ctx context.Context, owner string, re
|
|||
return r0, r1, r2
|
||||
}
|
||||
|
||||
// GithubBaseURL provides a mock function with no fields
|
||||
func (_m *GithubClient) GithubBaseURL() *url.URL {
|
||||
ret := _m.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GithubBaseURL")
|
||||
}
|
||||
|
||||
var r0 *url.URL
|
||||
if rf, ok := ret.Get(0).(func() *url.URL); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*url.URL)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// ListEntityHooks provides a mock function with given fields: ctx, opts
|
||||
func (_m *GithubClient) ListEntityHooks(ctx context.Context, opts *github.ListOptions) ([]*github.Hook, *github.Response, error) {
|
||||
ret := _m.Called(ctx, opts)
|
||||
|
|
@ -371,33 +411,21 @@ func (_m *GithubClient) PingEntityHook(ctx context.Context, id int64) (*github.R
|
|||
}
|
||||
|
||||
// RemoveEntityRunner provides a mock function with given fields: ctx, runnerID
|
||||
func (_m *GithubClient) RemoveEntityRunner(ctx context.Context, runnerID int64) (*github.Response, error) {
|
||||
func (_m *GithubClient) RemoveEntityRunner(ctx context.Context, runnerID int64) error {
|
||||
ret := _m.Called(ctx, runnerID)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RemoveEntityRunner")
|
||||
}
|
||||
|
||||
var r0 *github.Response
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64) (*github.Response, error)); ok {
|
||||
return rf(ctx, runnerID)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64) *github.Response); ok {
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok {
|
||||
r0 = rf(ctx, runnerID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*github.Response)
|
||||
}
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok {
|
||||
r1 = rf(ctx, runnerID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
return r0
|
||||
}
|
||||
|
||||
// NewGithubClient creates a new instance of GithubClient. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ package mocks
|
|||
import (
|
||||
context "context"
|
||||
|
||||
github "github.com/google/go-github/v57/github"
|
||||
github "github.com/google/go-github/v71/github"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,16 @@
|
|||
// Code generated by mockery v2.42.0. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.3. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
github "github.com/google/go-github/v57/github"
|
||||
github "github.com/google/go-github/v71/github"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
params "github.com/cloudbase/garm/params"
|
||||
|
||||
url "net/url"
|
||||
)
|
||||
|
||||
// GithubEntityOperations is an autogenerated mock type for the GithubEntityOperations type
|
||||
|
|
@ -115,6 +117,24 @@ func (_m *GithubEntityOperations) DeleteEntityHook(ctx context.Context, id int64
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// GetEntity provides a mock function with no fields
|
||||
func (_m *GithubEntityOperations) GetEntity() params.GithubEntity {
|
||||
ret := _m.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetEntity")
|
||||
}
|
||||
|
||||
var r0 params.GithubEntity
|
||||
if rf, ok := ret.Get(0).(func() params.GithubEntity); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
r0 = ret.Get(0).(params.GithubEntity)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// GetEntityHook provides a mock function with given fields: ctx, id
|
||||
func (_m *GithubEntityOperations) GetEntityHook(ctx context.Context, id int64) (*github.Hook, error) {
|
||||
ret := _m.Called(ctx, id)
|
||||
|
|
@ -184,6 +204,26 @@ func (_m *GithubEntityOperations) GetEntityJITConfig(ctx context.Context, instan
|
|||
return r0, r1, r2
|
||||
}
|
||||
|
||||
// GithubBaseURL provides a mock function with no fields
|
||||
func (_m *GithubEntityOperations) GithubBaseURL() *url.URL {
|
||||
ret := _m.Called()
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GithubBaseURL")
|
||||
}
|
||||
|
||||
var r0 *url.URL
|
||||
if rf, ok := ret.Get(0).(func() *url.URL); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*url.URL)
|
||||
}
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// ListEntityHooks provides a mock function with given fields: ctx, opts
|
||||
func (_m *GithubEntityOperations) ListEntityHooks(ctx context.Context, opts *github.ListOptions) ([]*github.Hook, *github.Response, error) {
|
||||
ret := _m.Called(ctx, opts)
|
||||
|
|
@ -332,33 +372,21 @@ func (_m *GithubEntityOperations) PingEntityHook(ctx context.Context, id int64)
|
|||
}
|
||||
|
||||
// RemoveEntityRunner provides a mock function with given fields: ctx, runnerID
|
||||
func (_m *GithubEntityOperations) RemoveEntityRunner(ctx context.Context, runnerID int64) (*github.Response, error) {
|
||||
func (_m *GithubEntityOperations) RemoveEntityRunner(ctx context.Context, runnerID int64) error {
|
||||
ret := _m.Called(ctx, runnerID)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RemoveEntityRunner")
|
||||
}
|
||||
|
||||
var r0 *github.Response
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64) (*github.Response, error)); ok {
|
||||
return rf(ctx, runnerID)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64) *github.Response); ok {
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, int64) error); ok {
|
||||
r0 = rf(ctx, runnerID)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*github.Response)
|
||||
}
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, int64) error); ok {
|
||||
r1 = rf(ctx, runnerID)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
return r0
|
||||
}
|
||||
|
||||
// NewGithubEntityOperations creates a new instance of GithubEntityOperations. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations.
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ package mocks
|
|||
import (
|
||||
context "context"
|
||||
|
||||
github "github.com/google/go-github/v57/github"
|
||||
github "github.com/google/go-github/v71/github"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Code generated by mockery v2.42.0. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.3. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
|
|
@ -14,24 +14,6 @@ type PoolManager struct {
|
|||
mock.Mock
|
||||
}
|
||||
|
||||
// DeleteRunner provides a mock function with given fields: runner, forceRemove, bypassGHUnauthorizedError
|
||||
func (_m *PoolManager) DeleteRunner(runner params.Instance, forceRemove bool, bypassGHUnauthorizedError bool) error {
|
||||
ret := _m.Called(runner, forceRemove, bypassGHUnauthorizedError)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for DeleteRunner")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(params.Instance, bool, bool) error); ok {
|
||||
r0 = rf(runner, forceRemove, bypassGHUnauthorizedError)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
||||
return r0
|
||||
}
|
||||
|
||||
// GetWebhookInfo provides a mock function with given fields: ctx
|
||||
func (_m *PoolManager) GetWebhookInfo(ctx context.Context) (params.HookInfo, error) {
|
||||
ret := _m.Called(ctx)
|
||||
|
|
@ -60,7 +42,7 @@ func (_m *PoolManager) GetWebhookInfo(ctx context.Context) (params.HookInfo, err
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// GithubRunnerRegistrationToken provides a mock function with given fields:
|
||||
// GithubRunnerRegistrationToken provides a mock function with no fields
|
||||
func (_m *PoolManager) GithubRunnerRegistrationToken() (string, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
|
|
@ -106,7 +88,7 @@ func (_m *PoolManager) HandleWorkflowJob(job params.WorkflowJob) error {
|
|||
return r0
|
||||
}
|
||||
|
||||
// ID provides a mock function with given fields:
|
||||
// ID provides a mock function with no fields
|
||||
func (_m *PoolManager) ID() string {
|
||||
ret := _m.Called()
|
||||
|
||||
|
|
@ -152,7 +134,7 @@ func (_m *PoolManager) InstallWebhook(ctx context.Context, param params.InstallW
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// RootCABundle provides a mock function with given fields:
|
||||
// RootCABundle provides a mock function with no fields
|
||||
func (_m *PoolManager) RootCABundle() (params.CertificateBundle, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
|
|
@ -180,7 +162,12 @@ func (_m *PoolManager) RootCABundle() (params.CertificateBundle, error) {
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// Start provides a mock function with given fields:
|
||||
// SetPoolRunningState provides a mock function with given fields: isRunning, failureReason
|
||||
func (_m *PoolManager) SetPoolRunningState(isRunning bool, failureReason string) {
|
||||
_m.Called(isRunning, failureReason)
|
||||
}
|
||||
|
||||
// Start provides a mock function with no fields
|
||||
func (_m *PoolManager) Start() error {
|
||||
ret := _m.Called()
|
||||
|
||||
|
|
@ -198,7 +185,7 @@ func (_m *PoolManager) Start() error {
|
|||
return r0
|
||||
}
|
||||
|
||||
// Status provides a mock function with given fields:
|
||||
// Status provides a mock function with no fields
|
||||
func (_m *PoolManager) Status() params.PoolManagerStatus {
|
||||
ret := _m.Called()
|
||||
|
||||
|
|
@ -216,7 +203,7 @@ func (_m *PoolManager) Status() params.PoolManagerStatus {
|
|||
return r0
|
||||
}
|
||||
|
||||
// Stop provides a mock function with given fields:
|
||||
// Stop provides a mock function with no fields
|
||||
func (_m *PoolManager) Stop() error {
|
||||
ret := _m.Called()
|
||||
|
||||
|
|
@ -252,7 +239,7 @@ func (_m *PoolManager) UninstallWebhook(ctx context.Context) error {
|
|||
return r0
|
||||
}
|
||||
|
||||
// Wait provides a mock function with given fields:
|
||||
// Wait provides a mock function with no fields
|
||||
func (_m *PoolManager) Wait() error {
|
||||
ret := _m.Called()
|
||||
|
||||
|
|
@ -270,7 +257,7 @@ func (_m *PoolManager) Wait() error {
|
|||
return r0
|
||||
}
|
||||
|
||||
// WebhookSecret provides a mock function with given fields:
|
||||
// WebhookSecret provides a mock function with no fields
|
||||
func (_m *PoolManager) WebhookSecret() string {
|
||||
ret := _m.Called()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,15 +1,17 @@
|
|||
// Code generated by mockery v2.42.0. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.3. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
common "github.com/cloudbase/garm/runner/common"
|
||||
|
||||
garm_provider_commonparams "github.com/cloudbase/garm-provider-common/params"
|
||||
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
|
||||
params "github.com/cloudbase/garm/params"
|
||||
"github.com/cloudbase/garm/runner/common"
|
||||
)
|
||||
|
||||
// Provider is an autogenerated mock type for the Provider type
|
||||
|
|
@ -17,7 +19,7 @@ type Provider struct {
|
|||
mock.Mock
|
||||
}
|
||||
|
||||
// AsParams provides a mock function with given fields:
|
||||
// AsParams provides a mock function with no fields
|
||||
func (_m *Provider) AsParams() params.Provider {
|
||||
ret := _m.Called()
|
||||
|
||||
|
|
@ -35,9 +37,9 @@ func (_m *Provider) AsParams() params.Provider {
|
|||
return r0
|
||||
}
|
||||
|
||||
// CreateInstance provides a mock function with given fields: ctx, bootstrapParams
|
||||
// CreateInstance provides a mock function with given fields: ctx, bootstrapParams, createInstanceParams
|
||||
func (_m *Provider) CreateInstance(ctx context.Context, bootstrapParams garm_provider_commonparams.BootstrapInstance, createInstanceParams common.CreateInstanceParams) (garm_provider_commonparams.ProviderInstance, error) {
|
||||
ret := _m.Called(ctx, bootstrapParams)
|
||||
ret := _m.Called(ctx, bootstrapParams, createInstanceParams)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for CreateInstance")
|
||||
|
|
@ -45,17 +47,17 @@ func (_m *Provider) CreateInstance(ctx context.Context, bootstrapParams garm_pro
|
|||
|
||||
var r0 garm_provider_commonparams.ProviderInstance
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, garm_provider_commonparams.BootstrapInstance) (garm_provider_commonparams.ProviderInstance, error)); ok {
|
||||
return rf(ctx, bootstrapParams)
|
||||
if rf, ok := ret.Get(0).(func(context.Context, garm_provider_commonparams.BootstrapInstance, common.CreateInstanceParams) (garm_provider_commonparams.ProviderInstance, error)); ok {
|
||||
return rf(ctx, bootstrapParams, createInstanceParams)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, garm_provider_commonparams.BootstrapInstance) garm_provider_commonparams.ProviderInstance); ok {
|
||||
r0 = rf(ctx, bootstrapParams)
|
||||
if rf, ok := ret.Get(0).(func(context.Context, garm_provider_commonparams.BootstrapInstance, common.CreateInstanceParams) garm_provider_commonparams.ProviderInstance); ok {
|
||||
r0 = rf(ctx, bootstrapParams, createInstanceParams)
|
||||
} else {
|
||||
r0 = ret.Get(0).(garm_provider_commonparams.ProviderInstance)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, garm_provider_commonparams.BootstrapInstance) error); ok {
|
||||
r1 = rf(ctx, bootstrapParams)
|
||||
if rf, ok := ret.Get(1).(func(context.Context, garm_provider_commonparams.BootstrapInstance, common.CreateInstanceParams) error); ok {
|
||||
r1 = rf(ctx, bootstrapParams, createInstanceParams)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
|
@ -63,17 +65,17 @@ func (_m *Provider) CreateInstance(ctx context.Context, bootstrapParams garm_pro
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// DeleteInstance provides a mock function with given fields: ctx, instance
|
||||
// DeleteInstance provides a mock function with given fields: ctx, instance, deleteInstanceParams
|
||||
func (_m *Provider) DeleteInstance(ctx context.Context, instance string, deleteInstanceParams common.DeleteInstanceParams) error {
|
||||
ret := _m.Called(ctx, instance)
|
||||
ret := _m.Called(ctx, instance, deleteInstanceParams)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for DeleteInstance")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) error); ok {
|
||||
r0 = rf(ctx, instance)
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, common.DeleteInstanceParams) error); ok {
|
||||
r0 = rf(ctx, instance, deleteInstanceParams)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
|
@ -81,7 +83,7 @@ func (_m *Provider) DeleteInstance(ctx context.Context, instance string, deleteI
|
|||
return r0
|
||||
}
|
||||
|
||||
// DisableJITConfig provides a mock function with given fields:
|
||||
// DisableJITConfig provides a mock function with no fields
|
||||
func (_m *Provider) DisableJITConfig() bool {
|
||||
ret := _m.Called()
|
||||
|
||||
|
|
@ -99,9 +101,9 @@ func (_m *Provider) DisableJITConfig() bool {
|
|||
return r0
|
||||
}
|
||||
|
||||
// GetInstance provides a mock function with given fields: ctx, instance
|
||||
// GetInstance provides a mock function with given fields: ctx, instance, getInstanceParams
|
||||
func (_m *Provider) GetInstance(ctx context.Context, instance string, getInstanceParams common.GetInstanceParams) (garm_provider_commonparams.ProviderInstance, error) {
|
||||
ret := _m.Called(ctx, instance)
|
||||
ret := _m.Called(ctx, instance, getInstanceParams)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for GetInstance")
|
||||
|
|
@ -109,17 +111,17 @@ func (_m *Provider) GetInstance(ctx context.Context, instance string, getInstanc
|
|||
|
||||
var r0 garm_provider_commonparams.ProviderInstance
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) (garm_provider_commonparams.ProviderInstance, error)); ok {
|
||||
return rf(ctx, instance)
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, common.GetInstanceParams) (garm_provider_commonparams.ProviderInstance, error)); ok {
|
||||
return rf(ctx, instance, getInstanceParams)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) garm_provider_commonparams.ProviderInstance); ok {
|
||||
r0 = rf(ctx, instance)
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, common.GetInstanceParams) garm_provider_commonparams.ProviderInstance); ok {
|
||||
r0 = rf(ctx, instance, getInstanceParams)
|
||||
} else {
|
||||
r0 = ret.Get(0).(garm_provider_commonparams.ProviderInstance)
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, instance)
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, common.GetInstanceParams) error); ok {
|
||||
r1 = rf(ctx, instance, getInstanceParams)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
|
@ -127,9 +129,9 @@ func (_m *Provider) GetInstance(ctx context.Context, instance string, getInstanc
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// ListInstances provides a mock function with given fields: ctx, poolID
|
||||
// ListInstances provides a mock function with given fields: ctx, poolID, listInstancesParams
|
||||
func (_m *Provider) ListInstances(ctx context.Context, poolID string, listInstancesParams common.ListInstancesParams) ([]garm_provider_commonparams.ProviderInstance, error) {
|
||||
ret := _m.Called(ctx, poolID)
|
||||
ret := _m.Called(ctx, poolID, listInstancesParams)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for ListInstances")
|
||||
|
|
@ -137,19 +139,19 @@ func (_m *Provider) ListInstances(ctx context.Context, poolID string, listInstan
|
|||
|
||||
var r0 []garm_provider_commonparams.ProviderInstance
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) ([]garm_provider_commonparams.ProviderInstance, error)); ok {
|
||||
return rf(ctx, poolID)
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, common.ListInstancesParams) ([]garm_provider_commonparams.ProviderInstance, error)); ok {
|
||||
return rf(ctx, poolID, listInstancesParams)
|
||||
}
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) []garm_provider_commonparams.ProviderInstance); ok {
|
||||
r0 = rf(ctx, poolID)
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, common.ListInstancesParams) []garm_provider_commonparams.ProviderInstance); ok {
|
||||
r0 = rf(ctx, poolID, listInstancesParams)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]garm_provider_commonparams.ProviderInstance)
|
||||
}
|
||||
}
|
||||
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string) error); ok {
|
||||
r1 = rf(ctx, poolID)
|
||||
if rf, ok := ret.Get(1).(func(context.Context, string, common.ListInstancesParams) error); ok {
|
||||
r1 = rf(ctx, poolID, listInstancesParams)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
|
@ -157,17 +159,17 @@ func (_m *Provider) ListInstances(ctx context.Context, poolID string, listInstan
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// RemoveAllInstances provides a mock function with given fields: ctx
|
||||
func (_m *Provider) RemoveAllInstances(ctx context.Context, removeAllInstances common.RemoveAllInstancesParams) error {
|
||||
ret := _m.Called(ctx)
|
||||
// RemoveAllInstances provides a mock function with given fields: ctx, removeAllInstancesParams
|
||||
func (_m *Provider) RemoveAllInstances(ctx context.Context, removeAllInstancesParams common.RemoveAllInstancesParams) error {
|
||||
ret := _m.Called(ctx, removeAllInstancesParams)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for RemoveAllInstances")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context) error); ok {
|
||||
r0 = rf(ctx)
|
||||
if rf, ok := ret.Get(0).(func(context.Context, common.RemoveAllInstancesParams) error); ok {
|
||||
r0 = rf(ctx, removeAllInstancesParams)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
|
@ -175,17 +177,17 @@ func (_m *Provider) RemoveAllInstances(ctx context.Context, removeAllInstances c
|
|||
return r0
|
||||
}
|
||||
|
||||
// Start provides a mock function with given fields: ctx, instance
|
||||
// Start provides a mock function with given fields: ctx, instance, startParams
|
||||
func (_m *Provider) Start(ctx context.Context, instance string, startParams common.StartParams) error {
|
||||
ret := _m.Called(ctx, instance)
|
||||
ret := _m.Called(ctx, instance, startParams)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Start")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) error); ok {
|
||||
r0 = rf(ctx, instance)
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, common.StartParams) error); ok {
|
||||
r0 = rf(ctx, instance, startParams)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
|
@ -193,17 +195,17 @@ func (_m *Provider) Start(ctx context.Context, instance string, startParams comm
|
|||
return r0
|
||||
}
|
||||
|
||||
// Stop provides a mock function with given fields: ctx, instance
|
||||
// Stop provides a mock function with given fields: ctx, instance, stopParams
|
||||
func (_m *Provider) Stop(ctx context.Context, instance string, stopParams common.StopParams) error {
|
||||
ret := _m.Called(ctx, instance)
|
||||
ret := _m.Called(ctx, instance, stopParams)
|
||||
|
||||
if len(ret) == 0 {
|
||||
panic("no return value specified for Stop")
|
||||
}
|
||||
|
||||
var r0 error
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string) error); ok {
|
||||
r0 = rf(ctx, instance)
|
||||
if rf, ok := ret.Get(0).(func(context.Context, string, common.StopParams) error); ok {
|
||||
r0 = rf(ctx, instance, stopParams)
|
||||
} else {
|
||||
r0 = ret.Error(0)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ package mocks
|
|||
import (
|
||||
context "context"
|
||||
|
||||
github "github.com/google/go-github/v57/github"
|
||||
github "github.com/google/go-github/v71/github"
|
||||
mock "github.com/stretchr/testify/mock"
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -54,13 +54,6 @@ type PoolManager interface {
|
|||
// for it and call this function with the WorkflowJob as a parameter.
|
||||
HandleWorkflowJob(job params.WorkflowJob) error
|
||||
|
||||
// DeleteRunner will attempt to remove a runner from the pool. If forceRemove is true, any error
|
||||
// received from the provider will be ignored and we will proceed to remove the runner from the database.
|
||||
// An error received while attempting to remove from GitHub (other than 404) will still stop the deletion
|
||||
// process. This can happen if the runner is already processing a job. At which point, you can simply cancel
|
||||
// the job in github. Doing so will prompt GARM to reap the runner automatically.
|
||||
DeleteRunner(runner params.Instance, forceRemove, bypassGHUnauthorizedError bool) error
|
||||
|
||||
// InstallWebhook will create a webhook in github for the entity associated with this pool manager.
|
||||
InstallWebhook(ctx context.Context, param params.InstallWebhookParams) (params.HookInfo, error)
|
||||
// GetWebhookInfo will return information about the webhook installed in github for the entity associated
|
||||
|
|
@ -74,6 +67,8 @@ type PoolManager interface {
|
|||
// may use internal or self signed certificates.
|
||||
RootCABundle() (params.CertificateBundle, error)
|
||||
|
||||
SetPoolRunningState(isRunning bool, failureReason string)
|
||||
|
||||
// Start will start the pool manager and all associated workers.
|
||||
Start() error
|
||||
// Stop will stop the pool manager and all associated workers.
|
||||
|
|
|
|||
|
|
@ -2,8 +2,9 @@ package common
|
|||
|
||||
import (
|
||||
"context"
|
||||
"net/url"
|
||||
|
||||
"github.com/google/go-github/v57/github"
|
||||
"github.com/google/go-github/v71/github"
|
||||
|
||||
"github.com/cloudbase/garm/params"
|
||||
)
|
||||
|
|
@ -14,11 +15,21 @@ type GithubEntityOperations interface {
|
|||
CreateEntityHook(ctx context.Context, hook *github.Hook) (ret *github.Hook, err error)
|
||||
DeleteEntityHook(ctx context.Context, id int64) (ret *github.Response, err error)
|
||||
PingEntityHook(ctx context.Context, id int64) (ret *github.Response, err error)
|
||||
ListEntityRunners(ctx context.Context, opts *github.ListOptions) (*github.Runners, *github.Response, error)
|
||||
ListEntityRunners(ctx context.Context, opts *github.ListRunnersOptions) (*github.Runners, *github.Response, error)
|
||||
ListEntityRunnerApplicationDownloads(ctx context.Context) ([]*github.RunnerApplicationDownload, *github.Response, error)
|
||||
RemoveEntityRunner(ctx context.Context, runnerID int64) (*github.Response, error)
|
||||
RemoveEntityRunner(ctx context.Context, runnerID int64) error
|
||||
RateLimit(ctx context.Context) (*github.RateLimits, error)
|
||||
CreateEntityRegistrationToken(ctx context.Context) (*github.RegistrationToken, *github.Response, error)
|
||||
GetEntityJITConfig(ctx context.Context, instance string, pool params.Pool, labels []string) (jitConfigMap map[string]string, runner *github.Runner, err error)
|
||||
|
||||
// GetEntity returns the GitHub entity for which the github client was instanciated.
|
||||
GetEntity() params.GithubEntity
|
||||
// GithubBaseURL returns the base URL for the github or GHES API.
|
||||
GithubBaseURL() *url.URL
|
||||
}
|
||||
|
||||
type RateLimitClient interface {
|
||||
RateLimit(ctx context.Context) (*github.RateLimits, error)
|
||||
}
|
||||
|
||||
// GithubClient that describes the minimum list of functions we need to interact with github.
|
||||
|
|
|
|||
|
|
@ -145,6 +145,15 @@ func (r *Runner) DeleteEnterprise(ctx context.Context, enterpriseID string) erro
|
|||
return runnerErrors.NewBadRequestError("enterprise has pools defined (%s)", strings.Join(poolIDs, ", "))
|
||||
}
|
||||
|
||||
scaleSets, err := r.store.ListEntityScaleSets(ctx, entity)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching enterprise scale sets")
|
||||
}
|
||||
|
||||
if len(scaleSets) > 0 {
|
||||
return runnerErrors.NewBadRequestError("enterprise has scale sets defined; delete them first")
|
||||
}
|
||||
|
||||
if err := r.poolManagerCtrl.DeleteEnterprisePoolManager(enterprise); err != nil {
|
||||
return errors.Wrap(err, "deleting enterprise pool manager")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ import (
|
|||
"fmt"
|
||||
"html/template"
|
||||
"log/slog"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
|
|
@ -57,24 +56,52 @@ func (r *Runner) GetRunnerServiceName(ctx context.Context) (string, error) {
|
|||
ctx, "failed to get instance params")
|
||||
return "", runnerErrors.ErrUnauthorized
|
||||
}
|
||||
var entity params.GithubEntity
|
||||
|
||||
pool, err := r.store.GetPoolByID(r.ctx, instance.PoolID)
|
||||
if err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(
|
||||
ctx, "failed to get pool",
|
||||
"pool_id", instance.PoolID)
|
||||
return "", errors.Wrap(err, "fetching pool")
|
||||
switch {
|
||||
case instance.PoolID != "":
|
||||
pool, err := r.store.GetPoolByID(r.ctx, instance.PoolID)
|
||||
if err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(
|
||||
ctx, "failed to get pool",
|
||||
"pool_id", instance.PoolID)
|
||||
return "", errors.Wrap(err, "fetching pool")
|
||||
}
|
||||
entity, err = pool.GetEntity()
|
||||
if err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(
|
||||
ctx, "failed to get pool entity",
|
||||
"pool_id", instance.PoolID)
|
||||
return "", errors.Wrap(err, "fetching pool entity")
|
||||
}
|
||||
case instance.ScaleSetID != 0:
|
||||
scaleSet, err := r.store.GetScaleSetByID(r.ctx, instance.ScaleSetID)
|
||||
if err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(
|
||||
ctx, "failed to get scale set",
|
||||
"scale_set_id", instance.ScaleSetID)
|
||||
return "", errors.Wrap(err, "fetching scale set")
|
||||
}
|
||||
entity, err = scaleSet.GetEntity()
|
||||
if err != nil {
|
||||
slog.With(slog.Any("error", err)).ErrorContext(
|
||||
ctx, "failed to get scale set entity",
|
||||
"scale_set_id", instance.ScaleSetID)
|
||||
return "", errors.Wrap(err, "fetching scale set entity")
|
||||
}
|
||||
default:
|
||||
return "", errors.New("instance not associated with a pool or scale set")
|
||||
}
|
||||
|
||||
tpl := "actions.runner.%s.%s"
|
||||
var serviceName string
|
||||
switch pool.PoolType() {
|
||||
switch entity.EntityType {
|
||||
case params.GithubEntityTypeEnterprise:
|
||||
serviceName = fmt.Sprintf(tpl, pool.EnterpriseName, instance.Name)
|
||||
serviceName = fmt.Sprintf(tpl, entity.Owner, instance.Name)
|
||||
case params.GithubEntityTypeOrganization:
|
||||
serviceName = fmt.Sprintf(tpl, pool.OrgName, instance.Name)
|
||||
serviceName = fmt.Sprintf(tpl, entity.Owner, instance.Name)
|
||||
case params.GithubEntityTypeRepository:
|
||||
serviceName = fmt.Sprintf(tpl, strings.ReplaceAll(pool.RepoName, "/", "-"), instance.Name)
|
||||
serviceName = fmt.Sprintf(tpl, fmt.Sprintf("%s-%s", entity.Owner, entity.Name), instance.Name)
|
||||
}
|
||||
return serviceName, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
// Code generated by mockery v2.42.0. DO NOT EDIT.
|
||||
// Code generated by mockery v2.53.3. DO NOT EDIT.
|
||||
|
||||
package mocks
|
||||
|
||||
|
|
@ -193,7 +193,7 @@ func (_m *PoolManagerController) GetEnterprisePoolManager(enterprise params.Ente
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// GetEnterprisePoolManagers provides a mock function with given fields:
|
||||
// GetEnterprisePoolManagers provides a mock function with no fields
|
||||
func (_m *PoolManagerController) GetEnterprisePoolManagers() (map[string]common.PoolManager, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
|
|
@ -253,7 +253,7 @@ func (_m *PoolManagerController) GetOrgPoolManager(org params.Organization) (com
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// GetOrgPoolManagers provides a mock function with given fields:
|
||||
// GetOrgPoolManagers provides a mock function with no fields
|
||||
func (_m *PoolManagerController) GetOrgPoolManagers() (map[string]common.PoolManager, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
|
|
@ -313,7 +313,7 @@ func (_m *PoolManagerController) GetRepoPoolManager(repo params.Repository) (com
|
|||
return r0, r1
|
||||
}
|
||||
|
||||
// GetRepoPoolManagers provides a mock function with given fields:
|
||||
// GetRepoPoolManagers provides a mock function with no fields
|
||||
func (_m *PoolManagerController) GetRepoPoolManagers() (map[string]common.PoolManager, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
|
|
|
|||
|
|
@ -159,6 +159,15 @@ func (r *Runner) DeleteOrganization(ctx context.Context, orgID string, keepWebho
|
|||
return runnerErrors.NewBadRequestError("org has pools defined (%s)", strings.Join(poolIDs, ", "))
|
||||
}
|
||||
|
||||
scaleSets, err := r.store.ListEntityScaleSets(ctx, entity)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "fetching organization scale sets")
|
||||
}
|
||||
|
||||
if len(scaleSets) > 0 {
|
||||
return runnerErrors.NewBadRequestError("organization has scale sets defined; delete them first")
|
||||
}
|
||||
|
||||
if !keepWebhook && r.config.Default.EnableWebhookManagement {
|
||||
poolMgr, err := r.poolManagerCtrl.GetOrgPoolManager(org)
|
||||
if err != nil {
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue