drone/app/store/database/infra_provider_resource.go

245 lines
8.5 KiB
Go

// Copyright 2023 Harness, Inc.
//
// 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 database
import (
"context"
"encoding/json"
"github.com/harness/gitness/app/store"
"github.com/harness/gitness/store/database"
"github.com/harness/gitness/store/database/dbtx"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
"github.com/guregu/null"
"github.com/jmoiron/sqlx"
"github.com/pkg/errors"
)
const (
infraProviderResourceIDColumn = `ipreso_id`
infraProviderResourceInsertColumns = `
ipreso_uid,
ipreso_display_name,
ipreso_infra_provider_config_id,
ipreso_type,
ipreso_space_id,
ipreso_created,
ipreso_updated,
ipreso_cpu,
ipreso_memory,
ipreso_disk,
ipreso_network,
ipreso_region,
ipreso_opentofu_params,
ipreso_gateway_host,
ipreso_gateway_port,
ipreso_infra_provider_template_id
`
infraProviderResourceSelectColumns = "ipreso_id," + infraProviderResourceInsertColumns
infraProviderResourceTable = `infra_provider_resources`
)
type infraProviderResource struct {
ID int64 `db:"ipreso_id"`
Identifier string `db:"ipreso_uid"`
Name string `db:"ipreso_display_name"`
InfraProviderConfigID int64 `db:"ipreso_infra_provider_config_id"`
InfraProviderType enum.InfraProviderType `db:"ipreso_type"`
SpaceID int64 `db:"ipreso_space_id"`
CPU null.String `db:"ipreso_cpu"`
Memory null.String `db:"ipreso_memory"`
Disk null.String `db:"ipreso_disk"`
Network null.String `db:"ipreso_network"`
Region string `db:"ipreso_region"` // need list maybe
OpenTofuParams []byte `db:"ipreso_opentofu_params"`
GatewayHost null.String `db:"ipreso_gateway_host"`
GatewayPort null.String `db:"ipreso_gateway_port"`
TemplateID null.Int `db:"ipreso_infra_provider_template_id"`
Created int64 `db:"ipreso_created"`
Updated int64 `db:"ipreso_updated"`
}
var _ store.InfraProviderResourceStore = (*infraProviderResourceStore)(nil)
// NewGitspaceConfigStore returns a new GitspaceConfigStore.
func NewInfraProviderResourceStore(db *sqlx.DB) store.InfraProviderResourceStore {
return &infraProviderResourceStore{
db: db,
}
}
type infraProviderResourceStore struct {
db *sqlx.DB
}
func (s infraProviderResourceStore) List(ctx context.Context, infraProviderConfigID int64,
_ types.ListQueryFilter) ([]*types.InfraProviderResource, error) {
stmt := database.Builder.
Select(infraProviderResourceSelectColumns).
From(infraProviderResourceTable).
Where("ipreso_infra_provider_config_id = $1", infraProviderConfigID)
sql, args, err := stmt.ToSql()
if err != nil {
return nil, errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
db := dbtx.GetAccessor(ctx, s.db)
dst := new([]infraProviderResource)
if err := db.SelectContext(ctx, dst, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "Failed executing custom list query")
}
return s.mapToInfraProviderResources(ctx, *dst)
}
func (s infraProviderResourceStore) mapToInfraProviderResource(_ context.Context,
in *infraProviderResource) (*types.InfraProviderResource, error) {
openTofuParamsMap := make(map[string]string)
marshalErr := json.Unmarshal(in.OpenTofuParams, &openTofuParamsMap)
if marshalErr != nil {
return nil, marshalErr
}
return &types.InfraProviderResource{
Identifier: in.Identifier,
InfraProviderConfigID: in.InfraProviderConfigID,
ID: in.ID,
InfraProviderType: in.InfraProviderType,
Name: in.Name,
SpaceID: in.SpaceID,
CPU: in.CPU.Ptr(),
Memory: in.Memory.Ptr(),
Disk: in.Disk.Ptr(),
Network: in.Network.Ptr(),
Region: in.Region,
Metadata: openTofuParamsMap,
GatewayHost: in.GatewayHost.Ptr(),
GatewayPort: in.GatewayPort.Ptr(),
TemplateID: in.TemplateID.Ptr(),
Created: in.Created,
Updated: in.Updated,
}, nil
}
func (s infraProviderResourceStore) Find(ctx context.Context, id int64) (*types.InfraProviderResource, error) {
stmt := database.Builder.
Select(infraProviderResourceSelectColumns).
From(infraProviderResourceTable).
Where(infraProviderResourceIDColumn+" = $1", id)
sql, args, err := stmt.ToSql()
if err != nil {
return nil, errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
dst := new(infraProviderResource)
db := dbtx.GetAccessor(ctx, s.db)
if err := db.GetContext(ctx, dst, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to find infraProviderResource")
}
return s.mapToInfraProviderResource(ctx, dst)
}
func (s infraProviderResourceStore) FindByIdentifier(
ctx context.Context,
spaceID int64,
identifier string,
) (*types.InfraProviderResource, error) {
stmt := database.Builder.
Select(infraProviderResourceSelectColumns).
From(infraProviderResourceTable).
Where("ipreso_uid = $1", identifier).
Where("ipreso_space_id = $2", spaceID)
sql, args, err := stmt.ToSql()
if err != nil {
return nil, errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
dst := new(infraProviderResource)
db := dbtx.GetAccessor(ctx, s.db)
if err := db.GetContext(ctx, dst, sql, args...); err != nil {
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to find infraProviderResource")
}
return s.mapToInfraProviderResource(ctx, dst)
}
func (s infraProviderResourceStore) Create(
ctx context.Context,
infraProviderResource *types.InfraProviderResource,
) error {
jsonBytes, marshalErr := json.Marshal(infraProviderResource.Metadata)
if marshalErr != nil {
return marshalErr
}
stmt := database.Builder.
Insert(infraProviderResourceTable).
Columns(infraProviderResourceInsertColumns).
Values(
infraProviderResource.Identifier,
infraProviderResource.Name,
infraProviderResource.InfraProviderConfigID,
infraProviderResource.InfraProviderType,
infraProviderResource.SpaceID,
infraProviderResource.Created,
infraProviderResource.Updated,
infraProviderResource.CPU,
infraProviderResource.Memory,
infraProviderResource.Disk,
infraProviderResource.Network,
infraProviderResource.Region,
jsonBytes,
infraProviderResource.GatewayHost,
infraProviderResource.GatewayPort,
infraProviderResource.TemplateID,
).
Suffix(ReturningClause + infraProviderResourceIDColumn)
sql, args, err := stmt.ToSql()
if err != nil {
return errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
db := dbtx.GetAccessor(ctx, s.db)
if err = db.QueryRowContext(ctx, sql, args...).Scan(&infraProviderResource.ID); err != nil {
return database.ProcessSQLErrorf(ctx, err, "infra provider resource query failed")
}
return nil
}
func (s infraProviderResourceStore) DeleteByIdentifier(ctx context.Context, spaceID int64, identifier string) error {
stmt := database.Builder.
Delete(infraProviderResourceTable).
Where("ipreso_uid = $1", identifier).
Where("ipreso_space_id = $2", spaceID)
sql, args, err := stmt.ToSql()
if err != nil {
return errors.Wrap(err, "Failed to convert squirrel builder to sql")
}
db := dbtx.GetAccessor(ctx, s.db)
if _, err := db.ExecContext(ctx, sql, args...); err != nil {
return database.ProcessSQLErrorf(ctx, err, "Failed to delete infra provider resource")
}
return nil
}
func (s infraProviderResourceStore) mapToInfraProviderResources(ctx context.Context,
resources []infraProviderResource) ([]*types.InfraProviderResource, error) {
var err error
res := make([]*types.InfraProviderResource, len(resources))
for i := range resources {
res[i], err = s.mapToInfraProviderResource(ctx, &resources[i])
if err != nil {
return nil, err
}
}
return res, nil
}