Add Gitea endpoints and credentials

Signed-off-by: Gabriel Adrian Samfira <gsamfira@cloudbasesolutions.com>
This commit is contained in:
Gabriel Adrian Samfira 2025-05-14 00:34:54 +00:00
parent 40e6581a75
commit 823a9e4b82
100 changed files with 7439 additions and 660 deletions

View file

@ -344,26 +344,30 @@ type Tag struct {
type Pool struct {
RunnerPrefix
ID string `json:"id,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"`
Tags []Tag `json:"tags,omitempty"`
Enabled bool `json:"enabled,omitempty"`
Instances []Instance `json:"instances,omitempty"`
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"`
RunnerBootstrapTimeout uint `json:"runner_bootstrap_timeout,omitempty"`
CreatedAt time.Time `json:"created_at,omitempty"`
UpdatedAt time.Time `json:"updated_at,omitempty"`
ID string `json:"id,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"`
Tags []Tag `json:"tags,omitempty"`
Enabled bool `json:"enabled,omitempty"`
Instances []Instance `json:"instances,omitempty"`
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"`
RunnerBootstrapTimeout uint `json:"runner_bootstrap_timeout,omitempty"`
CreatedAt time.Time `json:"created_at,omitempty"`
UpdatedAt time.Time `json:"updated_at,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
@ -586,9 +590,11 @@ type Repository struct {
// CredentialName is the name of the credentials associated with the enterprise.
// This field is now deprecated. Use CredentialsID instead. This field will be
// removed in v0.2.0.
CredentialsName string `json:"credentials_name,omitempty"`
CredentialsID uint `json:"credentials_id,omitempty"`
Credentials GithubCredentials `json:"credentials,omitempty"`
CredentialsName string `json:"credentials_name,omitempty"`
CredentialsID uint `json:"credentials_id,omitempty"`
Credentials ForgeCredentials `json:"credentials,omitempty"`
PoolManagerStatus PoolManagerStatus `json:"pool_manager_status,omitempty"`
PoolBalancerType PoolBalancerType `json:"pool_balancing_type,omitempty"`
Endpoint ForgeEndpoint `json:"endpoint,omitempty"`
@ -598,6 +604,13 @@ type Repository struct {
WebhookSecret string `json:"-"`
}
func (r Repository) GetCredentialsName() string {
if r.CredentialsName != "" {
return r.CredentialsName
}
return r.Credentials.Name
}
func (r Repository) CreationDateGetter() time.Time {
return r.CreatedAt
}
@ -612,13 +625,10 @@ func (r Repository) GetEntity() (ForgeEntity, error) {
Owner: r.Owner,
Name: r.Name,
PoolBalancerType: r.PoolBalancerType,
Credentials: ForgeCredentials{
ForgeType: GithubEndpointType,
GithubCredentials: r.Credentials,
},
WebhookSecret: r.WebhookSecret,
CreatedAt: r.CreatedAt,
UpdatedAt: r.UpdatedAt,
Credentials: r.Credentials,
WebhookSecret: r.WebhookSecret,
CreatedAt: r.CreatedAt,
UpdatedAt: r.UpdatedAt,
}, nil
}
@ -652,7 +662,7 @@ type Organization struct {
// This field is now deprecated. Use CredentialsID instead. This field will be
// removed in v0.2.0.
CredentialsName string `json:"credentials_name,omitempty"`
Credentials GithubCredentials `json:"credentials,omitempty"`
Credentials ForgeCredentials `json:"credentials,omitempty"`
CredentialsID uint `json:"credentials_id,omitempty"`
PoolManagerStatus PoolManagerStatus `json:"pool_manager_status,omitempty"`
PoolBalancerType PoolBalancerType `json:"pool_balancing_type,omitempty"`
@ -677,12 +687,9 @@ func (o Organization) GetEntity() (ForgeEntity, error) {
Owner: o.Name,
WebhookSecret: o.WebhookSecret,
PoolBalancerType: o.PoolBalancerType,
Credentials: ForgeCredentials{
ForgeType: GithubEndpointType,
GithubCredentials: o.Credentials,
},
CreatedAt: o.CreatedAt,
UpdatedAt: o.UpdatedAt,
Credentials: o.Credentials,
CreatedAt: o.CreatedAt,
UpdatedAt: o.UpdatedAt,
}, nil
}
@ -712,7 +719,7 @@ type Enterprise struct {
// This field is now deprecated. Use CredentialsID instead. This field will be
// removed in v0.2.0.
CredentialsName string `json:"credentials_name,omitempty"`
Credentials GithubCredentials `json:"credentials,omitempty"`
Credentials ForgeCredentials `json:"credentials,omitempty"`
CredentialsID uint `json:"credentials_id,omitempty"`
PoolManagerStatus PoolManagerStatus `json:"pool_manager_status,omitempty"`
PoolBalancerType PoolBalancerType `json:"pool_balancing_type,omitempty"`
@ -737,12 +744,9 @@ func (e Enterprise) GetEntity() (ForgeEntity, error) {
Owner: e.Name,
WebhookSecret: e.WebhookSecret,
PoolBalancerType: e.PoolBalancerType,
Credentials: ForgeCredentials{
ForgeType: GithubEndpointType,
GithubCredentials: e.Credentials,
},
CreatedAt: e.CreatedAt,
UpdatedAt: e.UpdatedAt,
Credentials: e.Credentials,
CreatedAt: e.CreatedAt,
UpdatedAt: e.UpdatedAt,
}, nil
}
@ -856,99 +860,6 @@ func (g GithubRateLimit) ResetAt() time.Time {
}
type ForgeCredentials struct {
ForgeType EndpointType `json:"type,omitempty"`
GithubCredentials GithubCredentials `json:"github,omitempty"`
}
func (f ForgeCredentials) CABundle() []byte {
switch f.ForgeType {
case GithubEndpointType:
return f.GithubCredentials.CABundle
case GiteaEndpointType:
return nil
default:
return nil
}
}
func (f ForgeCredentials) Endpoint() ForgeEndpoint {
switch f.ForgeType {
case GithubEndpointType:
return f.GithubCredentials.Endpoint
case GiteaEndpointType:
return ForgeEndpoint{}
default:
return ForgeEndpoint{}
}
}
func (f ForgeCredentials) APIBaseURL() string {
switch f.ForgeType {
case GithubEndpointType:
return f.GithubCredentials.APIBaseURL
case GiteaEndpointType:
return ""
default:
return ""
}
}
func (f ForgeCredentials) UploadBaseURL() string {
switch f.ForgeType {
case GithubEndpointType:
return f.GithubCredentials.UploadBaseURL
case GiteaEndpointType:
return ""
default:
return ""
}
}
func (f ForgeCredentials) BaseURL() string {
switch f.ForgeType {
case GithubEndpointType:
return f.GithubCredentials.BaseURL
case GiteaEndpointType:
return ""
default:
return ""
}
}
func (f ForgeCredentials) GetHTTPClient(ctx context.Context) (*http.Client, error) {
switch f.ForgeType {
case GithubEndpointType:
return f.GithubCredentials.GetHTTPClient(ctx)
case GiteaEndpointType:
return nil, fmt.Errorf("gitea credentials not supported")
default:
return nil, fmt.Errorf("unknown credentials type")
}
}
func (f ForgeCredentials) GetID() uint {
switch f.ForgeType {
case GithubEndpointType:
return f.GithubCredentials.ID
case GiteaEndpointType:
return 0
default:
return 0
}
}
func (f ForgeCredentials) RootCertificateBundle() (CertificateBundle, error) {
switch f.ForgeType {
case GithubEndpointType:
return f.GithubCredentials.RootCertificateBundle()
case GiteaEndpointType:
return CertificateBundle{}, fmt.Errorf("gitea credentials not supported")
default:
return CertificateBundle{}, fmt.Errorf("unknown credentials type")
}
}
type GithubCredentials struct {
ID uint `json:"id,omitempty"`
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
@ -958,30 +869,25 @@ type GithubCredentials struct {
CABundle []byte `json:"ca_bundle,omitempty"`
AuthType ForgeAuthType `json:"auth-type,omitempty"`
Repositories []Repository `json:"repositories,omitempty"`
Organizations []Organization `json:"organizations,omitempty"`
Enterprises []Enterprise `json:"enterprises,omitempty"`
Endpoint ForgeEndpoint `json:"endpoint,omitempty"`
CreatedAt time.Time `json:"created_at,omitempty"`
UpdatedAt time.Time `json:"updated_at,omitempty"`
RateLimit GithubRateLimit `json:"rate_limit,omitempty"`
ForgeType EndpointType `json:"forge_type,omitempty"`
Repositories []Repository `json:"repositories,omitempty"`
Organizations []Organization `json:"organizations,omitempty"`
Enterprises []Enterprise `json:"enterprises,omitempty"`
Endpoint ForgeEndpoint `json:"endpoint,omitempty"`
CreatedAt time.Time `json:"created_at,omitempty"`
UpdatedAt time.Time `json:"updated_at,omitempty"`
RateLimit *GithubRateLimit `json:"rate_limit,omitempty"`
// Do not serialize sensitive info.
CredentialsPayload []byte `json:"-"`
}
func (g GithubCredentials) GetID() uint {
func (g ForgeCredentials) GetID() uint {
return g.ID
}
func (g GithubCredentials) GetForgeCredentials() ForgeCredentials {
return ForgeCredentials{
ForgeType: GithubEndpointType,
GithubCredentials: g,
}
}
func (g GithubCredentials) GetHTTPClient(ctx context.Context) (*http.Client, error) {
func (g ForgeCredentials) GetHTTPClient(ctx context.Context) (*http.Client, error) {
var roots *x509.CertPool
if g.CABundle != nil {
roots = x509.NewCertPool()
@ -1036,7 +942,7 @@ func (g GithubCredentials) GetHTTPClient(ctx context.Context) (*http.Client, err
return tc, nil
}
func (g GithubCredentials) RootCertificateBundle() (CertificateBundle, error) {
func (g ForgeCredentials) RootCertificateBundle() (CertificateBundle, error) {
if len(g.CABundle) == 0 {
return CertificateBundle{}, nil
}
@ -1067,7 +973,7 @@ func (g GithubCredentials) RootCertificateBundle() (CertificateBundle, error) {
}
// used by swagger client generated code
type Credentials []GithubCredentials
type Credentials []ForgeCredentials
type Provider struct {
Name string `json:"name,omitempty"`
@ -1195,11 +1101,11 @@ func (g ForgeEntity) GetCreatedAt() time.Time {
func (g ForgeEntity) ForgeURL() string {
switch g.EntityType {
case ForgeEntityTypeRepository:
return fmt.Sprintf("%s/%s/%s", g.Credentials.BaseURL(), g.Owner, g.Name)
return fmt.Sprintf("%s/%s/%s", g.Credentials.BaseURL, g.Owner, g.Name)
case ForgeEntityTypeOrganization:
return fmt.Sprintf("%s/%s", g.Credentials.BaseURL(), g.Owner)
return fmt.Sprintf("%s/%s", g.Credentials.BaseURL, g.Owner)
case ForgeEntityTypeEnterprise:
return fmt.Sprintf("%s/enterprises/%s", g.Credentials.BaseURL(), g.Owner)
return fmt.Sprintf("%s/enterprises/%s", g.Credentials.BaseURL, g.Owner)
}
return ""
}

View file

@ -45,6 +45,16 @@ type CreateRepoParams struct {
CredentialsName string `json:"credentials_name,omitempty"`
WebhookSecret string `json:"webhook_secret,omitempty"`
PoolBalancerType PoolBalancerType `json:"pool_balancer_type,omitempty"`
ForgeType EndpointType `json:"forge_type,omitempty"`
}
func (c CreateRepoParams) GetForgeType() EndpointType {
switch c.ForgeType {
case GithubEndpointType, GiteaEndpointType:
return c.ForgeType
default:
return GithubEndpointType
}
}
func (c *CreateRepoParams) Validate() error {
@ -77,6 +87,16 @@ type CreateOrgParams struct {
CredentialsName string `json:"credentials_name,omitempty"`
WebhookSecret string `json:"webhook_secret,omitempty"`
PoolBalancerType PoolBalancerType `json:"pool_balancer_type,omitempty"`
ForgeType EndpointType `json:"forge_type,omitempty"`
}
func (c CreateOrgParams) GetForgeType() EndpointType {
switch c.ForgeType {
case GithubEndpointType, GiteaEndpointType:
return c.ForgeType
default:
return GithubEndpointType
}
}
func (c *CreateOrgParams) Validate() error {
@ -281,7 +301,6 @@ type CreateGithubEndpointParams struct {
APIBaseURL string `json:"api_base_url,omitempty"`
UploadBaseURL string `json:"upload_base_url,omitempty"`
BaseURL string `json:"base_url,omitempty"`
EndpointType string `json:"endpoint_type,omitempty"`
CACertBundle []byte `json:"ca_cert_bundle,omitempty"`
}
@ -290,14 +309,6 @@ func (c CreateGithubEndpointParams) Validate() error {
return runnerErrors.NewBadRequestError("missing api_base_url")
}
if c.EndpointType != "" {
switch c.EndpointType {
case string(GithubEndpointType), string(GiteaEndpointType):
default:
return runnerErrors.NewBadRequestError("invalid endpoint_type: %s", c.EndpointType)
}
}
url, err := url.Parse(c.APIBaseURL)
if err != nil || url.Scheme == "" || url.Host == "" {
return runnerErrors.NewBadRequestError("invalid api_base_url")
@ -308,21 +319,19 @@ func (c CreateGithubEndpointParams) Validate() error {
return runnerErrors.NewBadRequestError("invalid api_base_url")
}
if c.EndpointType == string(GithubEndpointType) {
if c.UploadBaseURL == "" {
return runnerErrors.NewBadRequestError("missing upload_base_url")
}
if c.UploadBaseURL == "" {
return runnerErrors.NewBadRequestError("missing upload_base_url")
}
url, err = url.Parse(c.UploadBaseURL)
if err != nil || url.Scheme == "" || url.Host == "" {
return runnerErrors.NewBadRequestError("invalid upload_base_url")
}
url, err = url.Parse(c.UploadBaseURL)
if err != nil || url.Scheme == "" || url.Host == "" {
return runnerErrors.NewBadRequestError("invalid upload_base_url")
}
switch url.Scheme {
case httpsScheme, httpScheme:
default:
return runnerErrors.NewBadRequestError("invalid api_base_url")
}
switch url.Scheme {
case httpsScheme, httpScheme:
default:
return runnerErrors.NewBadRequestError("invalid api_base_url")
}
if c.BaseURL == "" {
@ -617,3 +626,154 @@ type UpdateScaleSetParams struct {
State *ScaleSetState `json:"state"`
ExtendedState *string `json:"extended_state"`
}
type CreateGiteaEndpointParams struct {
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
APIBaseURL string `json:"api_base_url,omitempty"`
BaseURL string `json:"base_url,omitempty"`
CACertBundle []byte `json:"ca_cert_bundle,omitempty"`
}
func (c CreateGiteaEndpointParams) Validate() error {
if c.APIBaseURL == "" {
return runnerErrors.NewBadRequestError("missing api_base_url")
}
url, err := url.Parse(c.APIBaseURL)
if err != nil || url.Scheme == "" || url.Host == "" {
return runnerErrors.NewBadRequestError("invalid api_base_url")
}
switch url.Scheme {
case httpsScheme, httpScheme:
default:
return runnerErrors.NewBadRequestError("invalid api_base_url")
}
switch url.Scheme {
case httpsScheme, httpScheme:
default:
return runnerErrors.NewBadRequestError("invalid api_base_url")
}
if c.BaseURL == "" {
return runnerErrors.NewBadRequestError("missing base_url")
}
url, err = url.Parse(c.BaseURL)
if err != nil || url.Scheme == "" || url.Host == "" {
return runnerErrors.NewBadRequestError("invalid base_url")
}
switch url.Scheme {
case httpsScheme, httpScheme:
default:
return runnerErrors.NewBadRequestError("invalid api_base_url")
}
if c.CACertBundle != nil {
block, _ := pem.Decode(c.CACertBundle)
if block == nil {
return runnerErrors.NewBadRequestError("invalid ca_cert_bundle")
}
if _, err := x509.ParseCertificates(block.Bytes); err != nil {
return runnerErrors.NewBadRequestError("invalid ca_cert_bundle")
}
}
return nil
}
type UpdateGiteaEndpointParams struct {
Description *string `json:"description,omitempty"`
APIBaseURL *string `json:"api_base_url,omitempty"`
BaseURL *string `json:"base_url,omitempty"`
CACertBundle []byte `json:"ca_cert_bundle,omitempty"`
}
func (u UpdateGiteaEndpointParams) Validate() error {
if u.APIBaseURL != nil {
url, err := url.Parse(*u.APIBaseURL)
if err != nil || url.Scheme == "" || url.Host == "" {
return runnerErrors.NewBadRequestError("invalid api_base_url")
}
switch url.Scheme {
case httpsScheme, httpScheme:
default:
return runnerErrors.NewBadRequestError("invalid api_base_url")
}
}
if u.BaseURL != nil {
url, err := url.Parse(*u.BaseURL)
if err != nil || url.Scheme == "" || url.Host == "" {
return runnerErrors.NewBadRequestError("invalid base_url")
}
switch url.Scheme {
case httpsScheme, httpScheme:
default:
return runnerErrors.NewBadRequestError("invalid api_base_url")
}
}
if u.CACertBundle != nil {
block, _ := pem.Decode(u.CACertBundle)
if block == nil {
return runnerErrors.NewBadRequestError("invalid ca_cert_bundle")
}
if _, err := x509.ParseCertificates(block.Bytes); err != nil {
return runnerErrors.NewBadRequestError("invalid ca_cert_bundle")
}
}
return nil
}
type CreateGiteaCredentialsParams struct {
Name string `json:"name,omitempty"`
Description string `json:"description,omitempty"`
Endpoint string `json:"endpoint,omitempty"`
AuthType ForgeAuthType `json:"auth_type,omitempty"`
PAT GithubPAT `json:"pat,omitempty"`
App GithubApp `json:"app,omitempty"`
}
func (c CreateGiteaCredentialsParams) Validate() error {
if c.Name == "" {
return runnerErrors.NewBadRequestError("missing name")
}
if c.Endpoint == "" {
return runnerErrors.NewBadRequestError("missing endpoint")
}
switch c.AuthType {
case ForgeAuthTypePAT:
default:
return runnerErrors.NewBadRequestError("invalid auth_type: %s", c.AuthType)
}
if c.AuthType == ForgeAuthTypePAT {
if c.PAT.OAuth2Token == "" {
return runnerErrors.NewBadRequestError("missing oauth2_token")
}
}
return nil
}
type UpdateGiteaCredentialsParams struct {
Name *string `json:"name,omitempty"`
Description *string `json:"description,omitempty"`
PAT *GithubPAT `json:"pat,omitempty"`
}
func (u UpdateGiteaCredentialsParams) Validate() error {
if u.PAT != nil {
if u.PAT.OAuth2Token == "" {
return runnerErrors.NewBadRequestError("missing oauth2_token")
}
}
return nil
}