mirror of https://github.com/harness/drone.git
feat: [CDE-637]: Changes to support hybrid's infra resources. (#3453)
* Linting * Refactoring db query in infra resource store for pq support. * Using a default value of infra config identifier if not present in the create gitspace request. * feat: [CDE-637]: Decoupling infra resource mgmt from config. Adding soft delete support to infra resource table. * Making infra provider resource unique to config and space.jobatzil/login/xforwardedfor
parent
8732b64aa8
commit
31d15dc8eb
|
@ -13,4 +13,7 @@ GITNESS_SSH_HOST=localhost
|
|||
GITNESS_SSH_PORT=2222
|
||||
|
||||
GITNESS_REGISTRY_STORAGE_TYPE=filesystem
|
||||
GITNESS_REGISTRY_FILESYSTEM_ROOT_DIRECTORY=/tmp
|
||||
GITNESS_REGISTRY_FILESYSTEM_ROOT_DIRECTORY=/tmp
|
||||
|
||||
#GITNESS_DATABASE_DRIVER=postgres
|
||||
#GITNESS_DATABASE_DATASOURCE=postgres://postgres:postgres@localhost:5432/gitness?sslmode=disable
|
|
@ -45,19 +45,20 @@ var (
|
|||
|
||||
// CreateInput is the input used for create operations.
|
||||
type CreateInput struct {
|
||||
Identifier string `json:"identifier"`
|
||||
Name string `json:"name"`
|
||||
SpaceRef string `json:"space_ref"` // Ref of the parent space
|
||||
IDE enum.IDEType `json:"ide"`
|
||||
ResourceIdentifier string `json:"resource_identifier"`
|
||||
ResourceSpaceRef string `json:"resource_space_ref"`
|
||||
CodeRepoURL string `json:"code_repo_url"`
|
||||
CodeRepoType enum.GitspaceCodeRepoType `json:"code_repo_type"`
|
||||
CodeRepoRef *string `json:"code_repo_ref"`
|
||||
Branch string `json:"branch"`
|
||||
DevcontainerPath *string `json:"devcontainer_path"`
|
||||
Metadata map[string]string `json:"metadata"`
|
||||
SSHTokenIdentifier string `json:"ssh_token_identifier"`
|
||||
Identifier string `json:"identifier"`
|
||||
Name string `json:"name"`
|
||||
SpaceRef string `json:"space_ref"` // Ref of the parent space
|
||||
IDE enum.IDEType `json:"ide"`
|
||||
InfraProviderConfigIdentifier string `json:"infra_provider_config_identifier"`
|
||||
ResourceIdentifier string `json:"resource_identifier"`
|
||||
ResourceSpaceRef string `json:"resource_space_ref"`
|
||||
CodeRepoURL string `json:"code_repo_url"`
|
||||
CodeRepoType enum.GitspaceCodeRepoType `json:"code_repo_type"`
|
||||
CodeRepoRef *string `json:"code_repo_ref"`
|
||||
Branch string `json:"branch"`
|
||||
DevcontainerPath *string `json:"devcontainer_path"`
|
||||
Metadata map[string]string `json:"metadata"`
|
||||
SSHTokenIdentifier string `json:"ssh_token_identifier"`
|
||||
}
|
||||
|
||||
// Create creates a new gitspace.
|
||||
|
@ -132,7 +133,15 @@ func (c *Controller) Create(
|
|||
enum.PermissionInfraProviderAccess); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
infraProviderResource, err := c.createOrFindInfraProviderResource(ctx, resourceSpace, resourceIdentifier, now)
|
||||
|
||||
// TODO: Temp fix to ensure the gitspace creation doesnt fail. Once the FE starts sending this field in the
|
||||
// request, remove this.
|
||||
if in.InfraProviderConfigIdentifier == "" {
|
||||
in.InfraProviderConfigIdentifier = defaultResourceIdentifier
|
||||
}
|
||||
|
||||
infraProviderResource, err := c.createOrFindInfraProviderResource(ctx, resourceSpace, resourceIdentifier,
|
||||
in.InfraProviderConfigIdentifier, now)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -183,13 +192,16 @@ func (c *Controller) createOrFindInfraProviderResource(
|
|||
ctx context.Context,
|
||||
resourceSpace *types.SpaceCore,
|
||||
resourceIdentifier string,
|
||||
infraProviderConfigIdentifier string,
|
||||
now int64,
|
||||
) (*types.InfraProviderResource, error) {
|
||||
var resource *types.InfraProviderResource
|
||||
var err error
|
||||
|
||||
resource, err = c.infraProviderSvc.FindResourceByIdentifier(ctx, resourceSpace.ID, resourceIdentifier)
|
||||
if err != nil && errors.Is(err, store.ErrResourceNotFound) && resourceIdentifier == defaultResourceIdentifier {
|
||||
resource, err = c.infraProviderSvc.FindResourceByConfigAndIdentifier(ctx, resourceSpace.ID,
|
||||
infraProviderConfigIdentifier, resourceIdentifier)
|
||||
if ((err != nil && errors.Is(err, store.ErrResourceNotFound)) || resource == nil) &&
|
||||
resourceIdentifier == defaultResourceIdentifier {
|
||||
resource, err = c.autoCreateDefaultResource(ctx, resourceSpace, now)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -237,12 +249,13 @@ func (c *Controller) autoCreateDefaultResource(
|
|||
}
|
||||
defaultDockerConfig.Resources = []types.InfraProviderResource{defaultResource}
|
||||
|
||||
err = c.infraProviderSvc.CreateInfraProvider(ctx, defaultDockerConfig)
|
||||
err = c.infraProviderSvc.CreateConfigAndResources(ctx, defaultDockerConfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not auto-create the infra provider: %w", err)
|
||||
}
|
||||
|
||||
resource, err := c.infraProviderSvc.FindResourceByIdentifier(ctx, rootSpace.ID, defaultResourceIdentifier)
|
||||
resource, err := c.infraProviderSvc.FindResourceByConfigAndIdentifier(ctx, rootSpace.ID,
|
||||
defaultDockerConfig.Identifier, defaultResourceIdentifier)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("could not find infra provider resource : %q %w", defaultResourceIdentifier, err)
|
||||
}
|
||||
|
|
|
@ -18,8 +18,44 @@ import (
|
|||
"github.com/harness/gitness/app/auth/authz"
|
||||
"github.com/harness/gitness/app/services/infraprovider"
|
||||
"github.com/harness/gitness/app/services/refcache"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
const NoResourceIdentifier = ""
|
||||
|
||||
type ConfigInput struct {
|
||||
Identifier string `json:"identifier" yaml:"identifier"`
|
||||
SpaceRef string `json:"space_ref" yaml:"space_ref"`
|
||||
Name string `json:"name" yaml:"name"`
|
||||
Type enum.InfraProviderType `json:"type" yaml:"type"`
|
||||
Metadata map[string]any `json:"metadata" yaml:"metadata"`
|
||||
}
|
||||
|
||||
type ResourceInput struct {
|
||||
Identifier string `json:"identifier" yaml:"identifier"`
|
||||
Name string `json:"name" yaml:"name"`
|
||||
InfraProviderType enum.InfraProviderType `json:"infra_provider_type" yaml:"infra_provider_type"`
|
||||
CPU *string `json:"cpu" yaml:"cpu"`
|
||||
Memory *string `json:"memory" yaml:"memory"`
|
||||
Disk *string `json:"disk" yaml:"disk"`
|
||||
Network *string `json:"network" yaml:"network"`
|
||||
Region []string `json:"region" yaml:"region"`
|
||||
Metadata map[string]string `json:"metadata" yaml:"metadata"`
|
||||
GatewayHost *string `json:"gateway_host" yaml:"gateway_host"`
|
||||
GatewayPort *string `json:"gateway_port" yaml:"gateway_port"`
|
||||
}
|
||||
|
||||
type AutoCreateInput struct {
|
||||
Config ConfigInput `json:"config" yaml:"config"`
|
||||
Resources []ResourceInput `json:"resources" yaml:"resources"`
|
||||
}
|
||||
|
||||
type TemplateInput struct {
|
||||
Identifier string `json:"identifier" yaml:"identifier"`
|
||||
Description string `json:"description" yaml:"description"`
|
||||
Data string `json:"data" yaml:"data"`
|
||||
}
|
||||
|
||||
type Controller struct {
|
||||
authorizer authz.Authorizer
|
||||
spaceFinder refcache.SpaceFinder
|
||||
|
|
|
@ -1,115 +0,0 @@
|
|||
// 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 infraprovider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
apiauth "github.com/harness/gitness/app/api/auth"
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/check"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
const NoResourceIdentifier = ""
|
||||
|
||||
type CreateInput struct {
|
||||
Identifier string `json:"identifier" yaml:"identifier"`
|
||||
SpaceRef string `json:"space_ref" yaml:"space_ref"` // Ref of the parent space
|
||||
Name string `json:"name" yaml:"name"`
|
||||
Type enum.InfraProviderType `json:"type" yaml:"type"`
|
||||
Metadata map[string]any `json:"metadata" yaml:"metadata"`
|
||||
Resources []ResourceInput `json:"resources" yaml:"resources"`
|
||||
}
|
||||
|
||||
type ResourceInput struct {
|
||||
Identifier string `json:"identifier" yaml:"identifier"`
|
||||
Name string `json:"name" yaml:"name"`
|
||||
InfraProviderType enum.InfraProviderType `json:"infra_provider_type" yaml:"infra_provider_type"`
|
||||
CPU *string `json:"cpu" yaml:"cpu"`
|
||||
Memory *string `json:"memory" yaml:"memory"`
|
||||
Disk *string `json:"disk" yaml:"disk"`
|
||||
Network *string `json:"network" yaml:"network"`
|
||||
Region []string `json:"region" yaml:"region"`
|
||||
Metadata map[string]string `json:"metadata" yaml:"metadata"`
|
||||
GatewayHost *string `json:"gateway_host" yaml:"gateway_host"`
|
||||
GatewayPort *string `json:"gateway_port" yaml:"gateway_port"`
|
||||
}
|
||||
|
||||
type TemplateInput struct {
|
||||
Identifier string `json:"identifier" yaml:"identifier"`
|
||||
Description string `json:"description" yaml:"description"`
|
||||
Data string `json:"data" yaml:"data"`
|
||||
}
|
||||
|
||||
// Create creates a new infra provider.
|
||||
func (c *Controller) Create(
|
||||
ctx context.Context,
|
||||
session auth.Session,
|
||||
in CreateInput,
|
||||
) (*types.InfraProviderConfig, error) {
|
||||
if err := c.sanitizeCreateInput(in); err != nil {
|
||||
return nil, fmt.Errorf("invalid input: %w", err)
|
||||
}
|
||||
parentSpace, err := c.spaceFinder.FindByRef(ctx, in.SpaceRef)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find parent by ref %q : %w", in.SpaceRef, err)
|
||||
}
|
||||
if err = apiauth.CheckInfraProvider(
|
||||
ctx,
|
||||
c.authorizer,
|
||||
&session,
|
||||
parentSpace.Path,
|
||||
NoResourceIdentifier,
|
||||
enum.PermissionInfraProviderEdit); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
now := time.Now().UnixMilli()
|
||||
infraProviderConfig := c.MapToInfraProviderConfig(in, parentSpace, now)
|
||||
err = c.infraproviderSvc.CreateInfraProvider(ctx, infraProviderConfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create the infraprovider: %q %w", infraProviderConfig.Identifier, err)
|
||||
}
|
||||
return infraProviderConfig, nil
|
||||
}
|
||||
|
||||
func (c *Controller) MapToInfraProviderConfig(
|
||||
in CreateInput,
|
||||
parentSpace *types.SpaceCore,
|
||||
now int64,
|
||||
) *types.InfraProviderConfig {
|
||||
infraProviderConfig := &types.InfraProviderConfig{
|
||||
Identifier: in.Identifier,
|
||||
Name: in.Name,
|
||||
SpaceID: parentSpace.ID,
|
||||
SpacePath: parentSpace.Path,
|
||||
Type: in.Type,
|
||||
Created: now,
|
||||
Updated: now,
|
||||
Metadata: in.Metadata,
|
||||
}
|
||||
infraProviderConfig.Resources = mapToResourceEntity(in.Resources, parentSpace, now)
|
||||
return infraProviderConfig
|
||||
}
|
||||
|
||||
func (c *Controller) sanitizeCreateInput(in CreateInput) error {
|
||||
if err := check.Identifier(in.Identifier); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
// 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 infraprovider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
apiauth "github.com/harness/gitness/app/api/auth"
|
||||
"github.com/harness/gitness/app/auth"
|
||||
"github.com/harness/gitness/types"
|
||||
"github.com/harness/gitness/types/check"
|
||||
"github.com/harness/gitness/types/enum"
|
||||
)
|
||||
|
||||
// CreateConfig creates a new infra provider config.
|
||||
func (c *Controller) CreateConfig(
|
||||
ctx context.Context,
|
||||
session auth.Session,
|
||||
in ConfigInput,
|
||||
) (*types.InfraProviderConfig, error) {
|
||||
if err := c.sanitizeCreateInput(in); err != nil {
|
||||
return nil, fmt.Errorf("invalid input: %w", err)
|
||||
}
|
||||
parentSpace, err := c.spaceFinder.FindByRef(ctx, in.SpaceRef)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find parent by ref %q : %w", in.SpaceRef, err)
|
||||
}
|
||||
if err = apiauth.CheckInfraProvider(
|
||||
ctx,
|
||||
c.authorizer,
|
||||
&session,
|
||||
parentSpace.Path,
|
||||
NoResourceIdentifier,
|
||||
enum.PermissionInfraProviderEdit); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
now := time.Now().UnixMilli()
|
||||
infraProviderConfig := c.MapToInfraProviderConfig(in, parentSpace, now)
|
||||
err = c.infraproviderSvc.CreateConfig(ctx, infraProviderConfig)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create the infraprovider: %q %w", infraProviderConfig.Identifier, err)
|
||||
}
|
||||
return infraProviderConfig, nil
|
||||
}
|
||||
|
||||
func (c *Controller) MapToInfraProviderConfig(
|
||||
in ConfigInput,
|
||||
space *types.SpaceCore,
|
||||
now int64,
|
||||
) *types.InfraProviderConfig {
|
||||
return &types.InfraProviderConfig{
|
||||
Identifier: in.Identifier,
|
||||
Name: in.Name,
|
||||
SpaceID: space.ID,
|
||||
SpacePath: space.Path,
|
||||
Type: in.Type,
|
||||
Created: now,
|
||||
Updated: now,
|
||||
Metadata: in.Metadata,
|
||||
}
|
||||
}
|
||||
|
||||
func (c *Controller) sanitizeCreateInput(in ConfigInput) error {
|
||||
if err := check.Identifier(in.Identifier); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -83,7 +83,7 @@ func (c *Controller) CreateResources(
|
|||
return nil, fmt.Errorf("invalid input: %w", err)
|
||||
}
|
||||
now := time.Now().UnixMilli()
|
||||
parentSpace, err := c.spaceFinder.FindByRef(ctx, spaceRef)
|
||||
space, err := c.spaceFinder.FindByRef(ctx, spaceRef)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find parent by ref: %w", err)
|
||||
}
|
||||
|
@ -91,31 +91,35 @@ func (c *Controller) CreateResources(
|
|||
ctx,
|
||||
c.authorizer,
|
||||
&session,
|
||||
parentSpace.Path,
|
||||
space.Path,
|
||||
NoResourceIdentifier,
|
||||
enum.PermissionInfraProviderEdit); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
infraProviderConfig, err := c.infraproviderSvc.Find(ctx, parentSpace, configIdentifier)
|
||||
infraProviderConfig, err := c.infraproviderSvc.Find(ctx, space, configIdentifier)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find infraprovider config by ref: %q %w", infraProviderConfig.Identifier, err)
|
||||
return nil, fmt.Errorf("failed to find infraprovider config by ref: %q %w", configIdentifier, err)
|
||||
}
|
||||
resources := mapToResourceEntity(in, parentSpace, now)
|
||||
err = c.infraproviderSvc.CreateResources(ctx, resources, infraProviderConfig.ID, infraProviderConfig.Identifier)
|
||||
resources := c.MapToResourceEntity(in, space, now)
|
||||
err = c.infraproviderSvc.CreateResources(ctx, space.ID, resources, infraProviderConfig.ID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return resources, nil
|
||||
}
|
||||
|
||||
func mapToResourceEntity(in []ResourceInput, parentSpace *types.SpaceCore, now int64) []types.InfraProviderResource {
|
||||
func (c *Controller) MapToResourceEntity(
|
||||
in []ResourceInput,
|
||||
space *types.SpaceCore,
|
||||
now int64,
|
||||
) []types.InfraProviderResource {
|
||||
var resources []types.InfraProviderResource
|
||||
for _, res := range in {
|
||||
infraProviderResource := types.InfraProviderResource{
|
||||
UID: res.Identifier,
|
||||
InfraProviderType: res.InfraProviderType,
|
||||
Name: res.Name,
|
||||
SpaceID: parentSpace.ID,
|
||||
SpaceID: space.ID,
|
||||
CPU: res.CPU,
|
||||
Memory: res.Memory,
|
||||
Disk: res.Disk,
|
||||
|
@ -124,7 +128,7 @@ func mapToResourceEntity(in []ResourceInput, parentSpace *types.SpaceCore, now i
|
|||
Metadata: res.Metadata,
|
||||
Created: now,
|
||||
Updated: now,
|
||||
SpacePath: parentSpace.Path,
|
||||
SpacePath: space.Path,
|
||||
}
|
||||
resources = append(resources, infraProviderResource)
|
||||
}
|
||||
|
|
|
@ -29,14 +29,14 @@ func HandleCreateConfig(infraProviderCtrl *infraprovider.Controller) http.Handle
|
|||
ctx := r.Context()
|
||||
session, _ := request.AuthSessionFrom(ctx)
|
||||
|
||||
in := new(infraprovider.CreateInput)
|
||||
in := new(infraprovider.ConfigInput)
|
||||
err := json.NewDecoder(r.Body).Decode(in)
|
||||
if err != nil {
|
||||
render.BadRequestf(ctx, w, "Invalid Request Body: %s.", err)
|
||||
return
|
||||
}
|
||||
|
||||
infraProviderConfig, err := infraProviderCtrl.Create(ctx, *session, *in)
|
||||
infraProviderConfig, err := infraProviderCtrl.CreateConfig(ctx, *session, *in)
|
||||
if err != nil {
|
||||
render.TranslatedUserError(ctx, w, err)
|
||||
return
|
||||
|
|
|
@ -25,7 +25,7 @@ import (
|
|||
)
|
||||
|
||||
type createInfraProviderConfigRequest struct {
|
||||
infraprovider.CreateInput
|
||||
infraprovider.ConfigInput
|
||||
}
|
||||
|
||||
type getInfraProviderRequest struct {
|
||||
|
|
|
@ -1,215 +0,0 @@
|
|||
// 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 infraprovider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/app/api/usererror"
|
||||
"github.com/harness/gitness/infraprovider"
|
||||
"github.com/harness/gitness/types"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func (c *Service) CreateTemplate(
|
||||
ctx context.Context,
|
||||
template *types.InfraProviderTemplate,
|
||||
) error {
|
||||
return c.infraProviderTemplateStore.Create(ctx, template)
|
||||
}
|
||||
|
||||
func (c *Service) CreateInfraProvider(
|
||||
ctx context.Context,
|
||||
infraProviderConfig *types.InfraProviderConfig,
|
||||
) error {
|
||||
err := c.tx.WithTx(ctx, func(ctx context.Context) error {
|
||||
err := c.areNewConfigsAllowed(ctx, infraProviderConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
configID, err := c.createConfig(ctx, infraProviderConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create the config: %q %w", infraProviderConfig.Identifier, err)
|
||||
}
|
||||
err = c.createResources(ctx, infraProviderConfig.Resources, configID, infraProviderConfig.Identifier)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create the resources: %v %w", infraProviderConfig.Resources, err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to complete txn for the infraprovider %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Service) validateConfigAndResources(infraProviderConfig *types.InfraProviderConfig) error {
|
||||
infraProvider, err := c.infraProviderFactory.GetInfraProvider(infraProviderConfig.Type)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch infra provider for type %s: %w", infraProviderConfig.Type, err)
|
||||
}
|
||||
|
||||
err = infraProvider.ValidateConfigAndResources(infraProviderConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Service) areNewConfigsAllowed(ctx context.Context, infraProviderConfig *types.InfraProviderConfig) error {
|
||||
existingConfigs, err := c.fetchExistingConfigs(ctx, infraProviderConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(existingConfigs) > 0 {
|
||||
return usererror.NewWithPayload(http.StatusForbidden, fmt.Sprintf(
|
||||
"%d infra configs for provider %s exist for this account. Only 1 is allowed",
|
||||
len(existingConfigs), infraProviderConfig.Type))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Service) fetchExistingConfigs(
|
||||
ctx context.Context,
|
||||
infraProviderConfig *types.InfraProviderConfig,
|
||||
) ([]*types.InfraProviderConfig, error) {
|
||||
existingConfigs, err := c.infraProviderConfigStore.FindByType(ctx, infraProviderConfig.SpaceID,
|
||||
infraProviderConfig.Type)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find existing infraprovider config for type %s & space %d: %w",
|
||||
infraProviderConfig.Type, infraProviderConfig.SpaceID, err)
|
||||
}
|
||||
return existingConfigs, nil
|
||||
}
|
||||
|
||||
func (c *Service) createConfig(ctx context.Context, infraProviderConfig *types.InfraProviderConfig) (int64, error) {
|
||||
err := c.validateConfigAndResources(infraProviderConfig)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
err = c.infraProviderConfigStore.Create(ctx, infraProviderConfig)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to create infraprovider config for %s: %w", infraProviderConfig.Identifier, err)
|
||||
}
|
||||
|
||||
newInfraProviderConfig, err := c.infraProviderConfigStore.FindByIdentifier(ctx, infraProviderConfig.SpaceID,
|
||||
infraProviderConfig.Identifier)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to find newly created infraprovider config %s in space %d: %w",
|
||||
infraProviderConfig.Identifier, infraProviderConfig.SpaceID, err)
|
||||
}
|
||||
return newInfraProviderConfig.ID, nil
|
||||
}
|
||||
|
||||
func (c *Service) CreateResources(
|
||||
ctx context.Context,
|
||||
resources []types.InfraProviderResource,
|
||||
configID int64,
|
||||
infraProviderConfigIdentifier string,
|
||||
) error {
|
||||
err := c.tx.WithTx(ctx, func(ctx context.Context) error {
|
||||
return c.createResources(ctx, resources, configID, infraProviderConfigIdentifier)
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to complete create txn for the infraprovider resource %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Service) createResources(
|
||||
ctx context.Context,
|
||||
resources []types.InfraProviderResource,
|
||||
configID int64,
|
||||
infraProviderConfigIdentifier string,
|
||||
) error {
|
||||
for idx := range resources {
|
||||
resource := &resources[idx]
|
||||
resource.InfraProviderConfigID = configID
|
||||
resource.InfraProviderConfigIdentifier = infraProviderConfigIdentifier
|
||||
|
||||
err := c.validate(ctx, resource)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = c.infraProviderResourceStore.Create(ctx, resource)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to create infraprovider resource for : %q %w", resource.UID, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Service) validate(ctx context.Context, resource *types.InfraProviderResource) error {
|
||||
infraProvider, err := c.infraProviderFactory.GetInfraProvider(resource.InfraProviderType)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch infra impl for type : %q %w", resource.InfraProviderType, err)
|
||||
}
|
||||
|
||||
if len(infraProvider.TemplateParams()) > 0 {
|
||||
err = c.validateTemplates(ctx, infraProvider, *resource)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = c.validateResourceParams(infraProvider, *resource)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Service) validateTemplates(
|
||||
ctx context.Context,
|
||||
infraProvider infraprovider.InfraProvider,
|
||||
res types.InfraProviderResource,
|
||||
) error {
|
||||
templateParams := infraProvider.TemplateParams()
|
||||
for _, param := range templateParams {
|
||||
key := param.Name
|
||||
if res.Metadata[key] != "" {
|
||||
templateIdentifier := res.Metadata[key]
|
||||
_, err := c.infraProviderTemplateStore.FindByIdentifier(
|
||||
ctx, res.SpaceID, templateIdentifier)
|
||||
if err != nil {
|
||||
log.Warn().Msgf("unable to get template params for ID : %s",
|
||||
res.Metadata[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Service) validateResourceParams(
|
||||
infraProvider infraprovider.InfraProvider,
|
||||
res types.InfraProviderResource,
|
||||
) error {
|
||||
infraResourceParams := make([]types.InfraProviderParameter, 0)
|
||||
for key, value := range res.Metadata {
|
||||
infraResourceParams = append(infraResourceParams, types.InfraProviderParameter{
|
||||
Name: key,
|
||||
Value: value,
|
||||
})
|
||||
}
|
||||
return infraProvider.ValidateParams(infraResourceParams)
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
// 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 infraprovider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/app/api/usererror"
|
||||
"github.com/harness/gitness/types"
|
||||
)
|
||||
|
||||
func (c *Service) CreateConfig(
|
||||
ctx context.Context,
|
||||
infraProviderConfig *types.InfraProviderConfig,
|
||||
) error {
|
||||
err := c.tx.WithTx(ctx, func(ctx context.Context) error {
|
||||
err := c.areNewConfigsAllowed(ctx, infraProviderConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = c.createConfig(ctx, infraProviderConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create the config: %q %w", infraProviderConfig.Identifier, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to complete txn for the infraprovider %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Service) areNewConfigsAllowed(ctx context.Context, infraProviderConfig *types.InfraProviderConfig) error {
|
||||
existingConfigs, err := c.fetchExistingConfigs(ctx, infraProviderConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(existingConfigs) > 0 {
|
||||
return usererror.NewWithPayload(http.StatusForbidden, fmt.Sprintf(
|
||||
"%d infra configs for provider %s exist for this account. Only 1 is allowed",
|
||||
len(existingConfigs), infraProviderConfig.Type))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Service) fetchExistingConfigs(
|
||||
ctx context.Context,
|
||||
infraProviderConfig *types.InfraProviderConfig,
|
||||
) ([]*types.InfraProviderConfig, error) {
|
||||
existingConfigs, err := c.infraProviderConfigStore.FindByType(ctx, infraProviderConfig.SpaceID,
|
||||
infraProviderConfig.Type)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find existing infraprovider config for type %s & space %d: %w",
|
||||
infraProviderConfig.Type, infraProviderConfig.SpaceID, err)
|
||||
}
|
||||
return existingConfigs, nil
|
||||
}
|
||||
|
||||
func (c *Service) createConfig(ctx context.Context, infraProviderConfig *types.InfraProviderConfig) (int64, error) {
|
||||
err := c.validateConfig(infraProviderConfig)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
err = c.infraProviderConfigStore.Create(ctx, infraProviderConfig)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to create infraprovider config for %s: %w", infraProviderConfig.Identifier, err)
|
||||
}
|
||||
|
||||
newInfraProviderConfig, err := c.infraProviderConfigStore.FindByIdentifier(ctx, infraProviderConfig.SpaceID,
|
||||
infraProviderConfig.Identifier)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("failed to find newly created infraprovider config %s in space %d: %w",
|
||||
infraProviderConfig.Identifier, infraProviderConfig.SpaceID, err)
|
||||
}
|
||||
return newInfraProviderConfig.ID, nil
|
||||
}
|
||||
|
||||
func (c *Service) validateConfig(infraProviderConfig *types.InfraProviderConfig) error {
|
||||
infraProvider, err := c.infraProviderFactory.GetInfraProvider(infraProviderConfig.Type)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch infra provider for type %s: %w", infraProviderConfig.Type, err)
|
||||
}
|
||||
|
||||
err = infraProvider.ValidateConfig(infraProviderConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
// 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 infraprovider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/types"
|
||||
)
|
||||
|
||||
func (c *Service) CreateConfigAndResources(
|
||||
ctx context.Context,
|
||||
infraProviderConfig *types.InfraProviderConfig,
|
||||
) error {
|
||||
err := c.tx.WithTx(ctx, func(ctx context.Context) error {
|
||||
err := c.areNewConfigsAllowed(ctx, infraProviderConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
configID, err := c.createConfig(ctx, infraProviderConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create the config: %q %w", infraProviderConfig.Identifier, err)
|
||||
}
|
||||
err = c.createMissingResources(ctx, infraProviderConfig.Resources, configID, infraProviderConfig.SpaceID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not create the resources: %v %w", infraProviderConfig.Resources, err)
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to complete txn for the infraprovider %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,102 @@
|
|||
// 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 infraprovider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/harness/gitness/infraprovider"
|
||||
"github.com/harness/gitness/store"
|
||||
"github.com/harness/gitness/types"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func (c *Service) CreateResources(
|
||||
ctx context.Context,
|
||||
spaceID int64,
|
||||
resources []types.InfraProviderResource,
|
||||
configID int64,
|
||||
) error {
|
||||
err := c.tx.WithTx(ctx, func(ctx context.Context) error {
|
||||
return c.createMissingResources(ctx, resources, configID, spaceID)
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to complete create txn for the infraprovider resource %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Service) createMissingResources(
|
||||
ctx context.Context,
|
||||
resources []types.InfraProviderResource,
|
||||
configID int64,
|
||||
spaceID int64,
|
||||
) error {
|
||||
for idx := range resources {
|
||||
resource := &resources[idx]
|
||||
resource.InfraProviderConfigID = configID
|
||||
resource.SpaceID = spaceID
|
||||
if err := c.validateResource(ctx, resource); err != nil {
|
||||
return err
|
||||
}
|
||||
existingResource, err := c.infraProviderResourceStore.FindByConfigAndIdentifier(ctx, resource.SpaceID,
|
||||
configID, resource.UID)
|
||||
if (err != nil && errors.Is(err, store.ErrResourceNotFound)) || existingResource == nil {
|
||||
if err = c.infraProviderResourceStore.Create(ctx, resource); err != nil {
|
||||
return fmt.Errorf("failed to create infraprovider resource for %s: %w", resource.UID, err)
|
||||
}
|
||||
log.Info().Msgf("created new resource %s/%s", resource.InfraProviderConfigIdentifier, resource.UID)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Service) validateResource(ctx context.Context, resource *types.InfraProviderResource) error {
|
||||
infraProvider, err := c.infraProviderFactory.GetInfraProvider(resource.InfraProviderType)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch infra impl for type : %q %w", resource.InfraProviderType, err)
|
||||
}
|
||||
|
||||
if len(infraProvider.TemplateParams()) > 0 {
|
||||
err = c.validateTemplates(ctx, infraProvider, *resource)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
err = c.validateResourceParams(infraProvider, *resource)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (c *Service) validateResourceParams(
|
||||
infraProvider infraprovider.InfraProvider,
|
||||
res types.InfraProviderResource,
|
||||
) error {
|
||||
infraResourceParams := make([]types.InfraProviderParameter, 0)
|
||||
for key, value := range res.Metadata {
|
||||
infraResourceParams = append(infraResourceParams, types.InfraProviderParameter{
|
||||
Name: key,
|
||||
Value: value,
|
||||
})
|
||||
}
|
||||
return infraProvider.ValidateParams(infraResourceParams)
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
// 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 infraprovider
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/harness/gitness/infraprovider"
|
||||
"github.com/harness/gitness/types"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func (c *Service) CreateTemplate(
|
||||
ctx context.Context,
|
||||
template *types.InfraProviderTemplate,
|
||||
) error {
|
||||
return c.infraProviderTemplateStore.Create(ctx, template)
|
||||
}
|
||||
|
||||
func (c *Service) validateTemplates(
|
||||
ctx context.Context,
|
||||
infraProvider infraprovider.InfraProvider,
|
||||
res types.InfraProviderResource,
|
||||
) error {
|
||||
templateParams := infraProvider.TemplateParams()
|
||||
for _, param := range templateParams {
|
||||
key := param.Name
|
||||
if res.Metadata[key] != "" {
|
||||
templateIdentifier := res.Metadata[key]
|
||||
_, err := c.infraProviderTemplateStore.FindByIdentifier(
|
||||
ctx, res.SpaceID, templateIdentifier)
|
||||
if err != nil {
|
||||
log.Warn().Msgf("unable to get template params for ID : %s",
|
||||
res.Metadata[key])
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
// 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 infraprovider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"github.com/harness/gitness/app/api/usererror"
|
||||
)
|
||||
|
||||
func (c *Service) DeleteResource(
|
||||
ctx context.Context,
|
||||
spaceID int64,
|
||||
infraProviderConfigIdentifier string,
|
||||
identifier string,
|
||||
) error {
|
||||
err := c.tx.WithTx(ctx, func(ctx context.Context) error {
|
||||
infraProviderConfig, err := c.infraProviderConfigStore.FindByIdentifier(ctx, spaceID,
|
||||
infraProviderConfigIdentifier)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to find infra config %s for deleting resource: %w",
|
||||
infraProviderConfigIdentifier, err)
|
||||
}
|
||||
|
||||
infraProviderResource, err := c.infraProviderResourceStore.FindByConfigAndIdentifier(ctx, spaceID,
|
||||
infraProviderConfig.ID, identifier)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to find infra resource %s with config %s for deleting resource: %w",
|
||||
identifier, infraProviderConfigIdentifier, err)
|
||||
}
|
||||
|
||||
activeGitspaces, err := c.gitspaceConfigStore.ListActiveConfigsForInfraProviderResource(ctx,
|
||||
infraProviderResource.ID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to list active configs for infra resource %s for deleting resource: %w",
|
||||
identifier, err)
|
||||
}
|
||||
|
||||
if len(activeGitspaces) > 0 {
|
||||
return usererror.NewWithPayload(http.StatusForbidden, fmt.Sprintf("There are %d active configs for "+
|
||||
"infra resource %s, expected 0", len(activeGitspaces), identifier))
|
||||
}
|
||||
|
||||
return c.infraProviderResourceStore.Delete(ctx, infraProviderResource.ID)
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to complete txn for deleting the infra resource %s: %w", identifier, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
// 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 infraprovider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"slices"
|
||||
|
||||
"github.com/harness/gitness/types"
|
||||
)
|
||||
|
||||
func (c *Service) Find(
|
||||
ctx context.Context,
|
||||
space *types.SpaceCore,
|
||||
identifier string,
|
||||
) (*types.InfraProviderConfig, error) {
|
||||
infraProviderConfig, err := c.infraProviderConfigStore.FindByIdentifier(ctx, space.ID, identifier)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find infraprovider config: %q %w", identifier, err)
|
||||
}
|
||||
resources, err := c.infraProviderResourceStore.List(ctx, infraProviderConfig.ID, types.ListQueryFilter{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find infraprovider resources for config: %q %w",
|
||||
infraProviderConfig.Identifier, err)
|
||||
}
|
||||
infraProviderConfig.SpacePath = space.Path
|
||||
if len(resources) > 0 {
|
||||
providerResources := make([]types.InfraProviderResource, len(resources))
|
||||
for i, resource := range resources {
|
||||
if resource != nil {
|
||||
providerResources[i] = *resource
|
||||
providerResources[i].SpacePath = space.Path
|
||||
}
|
||||
}
|
||||
slices.SortFunc(providerResources, types.CompareInfraProviderResource)
|
||||
infraProviderConfig.Resources = providerResources
|
||||
}
|
||||
return infraProviderConfig, nil
|
||||
}
|
||||
|
||||
func (c *Service) FindTemplate(
|
||||
ctx context.Context,
|
||||
space *types.SpaceCore,
|
||||
identifier string,
|
||||
) (*types.InfraProviderTemplate, error) {
|
||||
infraProviderTemplate, err := c.infraProviderTemplateStore.FindByIdentifier(ctx, space.ID, identifier)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find infraprovider template: %q %w", identifier, err)
|
||||
}
|
||||
return infraProviderTemplate, nil
|
||||
}
|
||||
|
||||
func (c *Service) FindResourceByConfigAndIdentifier(
|
||||
ctx context.Context,
|
||||
spaceID int64,
|
||||
infraProviderConfigIdentifier string,
|
||||
identifier string,
|
||||
) (*types.InfraProviderResource, error) {
|
||||
infraProviderConfig, err := c.infraProviderConfigStore.FindByIdentifier(ctx, spaceID, infraProviderConfigIdentifier)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find infraprovider config %s: %w", infraProviderConfigIdentifier, err)
|
||||
}
|
||||
return c.infraProviderResourceStore.FindByConfigAndIdentifier(ctx, spaceID, infraProviderConfig.ID, identifier)
|
||||
}
|
||||
|
||||
func (c *Service) FindResource(ctx context.Context, id int64) (*types.InfraProviderResource, error) {
|
||||
return c.infraProviderResourceStore.Find(ctx, id)
|
||||
}
|
|
@ -15,19 +15,15 @@
|
|||
package infraprovider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"slices"
|
||||
|
||||
"github.com/harness/gitness/app/services/refcache"
|
||||
"github.com/harness/gitness/app/store"
|
||||
"github.com/harness/gitness/infraprovider"
|
||||
"github.com/harness/gitness/store/database/dbtx"
|
||||
"github.com/harness/gitness/types"
|
||||
)
|
||||
|
||||
func NewService(
|
||||
tx dbtx.Transactor,
|
||||
gitspaceConfigStore store.GitspaceConfigStore,
|
||||
resourceStore store.InfraProviderResourceStore,
|
||||
configStore store.InfraProviderConfigStore,
|
||||
templateStore store.InfraProviderTemplateStore,
|
||||
|
@ -41,66 +37,16 @@ func NewService(
|
|||
infraProviderTemplateStore: templateStore,
|
||||
infraProviderFactory: factory,
|
||||
spaceFinder: spaceFinder,
|
||||
gitspaceConfigStore: gitspaceConfigStore,
|
||||
}
|
||||
}
|
||||
|
||||
type Service struct {
|
||||
tx dbtx.Transactor
|
||||
gitspaceConfigStore store.GitspaceConfigStore
|
||||
infraProviderResourceStore store.InfraProviderResourceStore
|
||||
infraProviderConfigStore store.InfraProviderConfigStore
|
||||
infraProviderTemplateStore store.InfraProviderTemplateStore
|
||||
infraProviderFactory infraprovider.Factory
|
||||
spaceFinder refcache.SpaceFinder
|
||||
}
|
||||
|
||||
func (c *Service) Find(
|
||||
ctx context.Context,
|
||||
space *types.SpaceCore,
|
||||
identifier string,
|
||||
) (*types.InfraProviderConfig, error) {
|
||||
infraProviderConfig, err := c.infraProviderConfigStore.FindByIdentifier(ctx, space.ID, identifier)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find infraprovider config: %q %w", identifier, err)
|
||||
}
|
||||
resources, err := c.infraProviderResourceStore.List(ctx, infraProviderConfig.ID, types.ListQueryFilter{})
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find infraprovider resources for config: %q %w",
|
||||
infraProviderConfig.Identifier, err)
|
||||
}
|
||||
infraProviderConfig.SpacePath = space.Path
|
||||
if len(resources) > 0 {
|
||||
providerResources := make([]types.InfraProviderResource, len(resources))
|
||||
for i, resource := range resources {
|
||||
if resource != nil {
|
||||
providerResources[i] = *resource
|
||||
providerResources[i].SpacePath = space.Path
|
||||
}
|
||||
}
|
||||
slices.SortFunc(providerResources, types.CompareInfraProviderResource)
|
||||
infraProviderConfig.Resources = providerResources
|
||||
}
|
||||
return infraProviderConfig, nil
|
||||
}
|
||||
|
||||
func (c *Service) FindTemplate(
|
||||
ctx context.Context,
|
||||
space *types.SpaceCore,
|
||||
identifier string,
|
||||
) (*types.InfraProviderTemplate, error) {
|
||||
infraProviderTemplate, err := c.infraProviderTemplateStore.FindByIdentifier(ctx, space.ID, identifier)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to find infraprovider template: %q %w", identifier, err)
|
||||
}
|
||||
return infraProviderTemplate, nil
|
||||
}
|
||||
|
||||
func (c *Service) FindResourceByIdentifier(
|
||||
ctx context.Context,
|
||||
spaceID int64,
|
||||
identifier string) (*types.InfraProviderResource, error) {
|
||||
return c.infraProviderResourceStore.FindByIdentifier(ctx, spaceID, identifier)
|
||||
}
|
||||
|
||||
func (c *Service) FindResource(ctx context.Context, id int64) (*types.InfraProviderResource, error) {
|
||||
return c.infraProviderResourceStore.Find(ctx, id)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
// 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 infraprovider
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/harness/gitness/types"
|
||||
)
|
||||
|
||||
func (c *Service) UpdateConfig(ctx context.Context, infraProviderConfig *types.InfraProviderConfig) error {
|
||||
err := c.validateConfig(infraProviderConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
infraProviderConfig.Updated = time.Now().UnixMilli()
|
||||
err = c.infraProviderConfigStore.Update(ctx, infraProviderConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update infraprovider config for %s: %w", infraProviderConfig.Identifier, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
|
@ -17,49 +17,10 @@ package infraprovider
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/harness/gitness/types"
|
||||
)
|
||||
|
||||
func (c *Service) updateConfig(ctx context.Context, infraProviderConfig *types.InfraProviderConfig) error {
|
||||
err := c.validateConfigAndResources(infraProviderConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
infraProviderConfig.Updated = time.Now().UnixMilli()
|
||||
err = c.infraProviderConfigStore.Update(ctx, infraProviderConfig)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to update infraprovider config for %s: %w", infraProviderConfig.Identifier, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Service) UpdateResource(ctx context.Context, resource types.InfraProviderResource) error {
|
||||
err := c.tx.WithTx(ctx, func(ctx context.Context) error {
|
||||
space, err := c.spaceFinder.FindByRef(ctx, resource.SpacePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
infraProviderResource, err := c.FindResourceByIdentifier(ctx, space.ID, resource.UID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
resource.ID = infraProviderResource.ID
|
||||
resource.Updated = time.Now().UnixMilli()
|
||||
if err = c.infraProviderResourceStore.Update(ctx, &resource); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to complete update txn for the infraprovider resource %w", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Service) UpdateTemplate(ctx context.Context, template types.InfraProviderTemplate) error {
|
||||
err := c.tx.WithTx(ctx, func(ctx context.Context) error {
|
||||
space, err := c.spaceFinder.FindByRef(ctx, template.SpacePath)
|
|
@ -25,9 +25,10 @@ import (
|
|||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
func (c *Service) UpsertInfraProvider(
|
||||
func (c *Service) UpsertConfigAndResources(
|
||||
ctx context.Context,
|
||||
infraProviderConfig *types.InfraProviderConfig,
|
||||
infraProviderResources []types.InfraProviderResource,
|
||||
) error {
|
||||
space, err := c.spaceFinder.FindByRef(ctx, infraProviderConfig.SpacePath)
|
||||
if err != nil {
|
||||
|
@ -35,7 +36,7 @@ func (c *Service) UpsertInfraProvider(
|
|||
}
|
||||
|
||||
err = c.tx.WithTx(ctx, func(ctx context.Context) error {
|
||||
return c.upsertConfig(ctx, space, infraProviderConfig)
|
||||
return c.upsertConfigAndResources(ctx, space, infraProviderConfig, infraProviderResources)
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to complete txn for the infraprovider: %w", err)
|
||||
|
@ -43,59 +44,35 @@ func (c *Service) UpsertInfraProvider(
|
|||
return nil
|
||||
}
|
||||
|
||||
func (c *Service) upsertConfig(
|
||||
func (c *Service) upsertConfigAndResources(
|
||||
ctx context.Context,
|
||||
space *types.SpaceCore,
|
||||
infraProviderConfig *types.InfraProviderConfig,
|
||||
infraProviderResources []types.InfraProviderResource,
|
||||
) error {
|
||||
providerConfigInDB, err := c.Find(ctx, space, infraProviderConfig.Identifier)
|
||||
var infraProviderConfigID int64
|
||||
if errors.Is(err, store.ErrResourceNotFound) {
|
||||
if infraProviderConfigID, err = c.createConfig(ctx, infraProviderConfig); err != nil {
|
||||
if errors.Is(err, store.ErrResourceNotFound) { // nolint:gocritic
|
||||
configID, createErr := c.createConfig(ctx, infraProviderConfig)
|
||||
if createErr != nil {
|
||||
return fmt.Errorf("could not create the config: %q %w", infraProviderConfig.Identifier, err)
|
||||
}
|
||||
infraProviderConfigID = configID
|
||||
log.Info().Msgf("created new infraconfig %s", infraProviderConfig.Identifier)
|
||||
} else if err != nil { // todo: should this not be err == nil?
|
||||
infraProviderConfig.ID = providerConfigInDB.ID
|
||||
if err = c.updateConfig(ctx, infraProviderConfig); err != nil {
|
||||
return fmt.Errorf("could not update the config %s: %w", infraProviderConfig.Identifier, err)
|
||||
}
|
||||
log.Info().Msgf("updated infraconfig %s", infraProviderConfig.Identifier)
|
||||
}
|
||||
if err != nil {
|
||||
} else if err != nil {
|
||||
return err
|
||||
} else {
|
||||
infraProviderConfigID = providerConfigInDB.ID
|
||||
}
|
||||
if err = c.UpsertResources(ctx, infraProviderConfig.Resources, infraProviderConfigID, space.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *Service) UpsertResources(
|
||||
ctx context.Context,
|
||||
resources []types.InfraProviderResource,
|
||||
configID int64,
|
||||
spaceID int64,
|
||||
) error {
|
||||
for idx := range resources {
|
||||
resource := &resources[idx]
|
||||
resource.InfraProviderConfigID = configID
|
||||
resource.SpaceID = spaceID
|
||||
if err := c.validate(ctx, resource); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err := c.infraProviderResourceStore.FindByIdentifier(ctx, resource.SpaceID, resource.UID)
|
||||
if errors.Is(err, store.ErrResourceNotFound) {
|
||||
if err = c.infraProviderResourceStore.Create(ctx, resource); err != nil {
|
||||
return fmt.Errorf("failed to create infraprovider resource for %s: %w", resource.UID, err)
|
||||
}
|
||||
log.Info().Msgf("created new resource %s/%s", resource.InfraProviderConfigIdentifier, resource.UID)
|
||||
} else {
|
||||
if err = c.UpdateResource(ctx, *resource); err != nil {
|
||||
log.Info().Msgf("updated resource %s/%s", resource.InfraProviderConfigIdentifier, resource.UID)
|
||||
return fmt.Errorf("could not update the resources %s: %w", resource.UID, err)
|
||||
}
|
||||
}
|
||||
infraProviderConfig.ID = infraProviderConfigID
|
||||
if err = c.UpdateConfig(ctx, infraProviderConfig); err != nil {
|
||||
return fmt.Errorf("could not update the config %s: %w", infraProviderConfig.Identifier, err)
|
||||
}
|
||||
|
||||
log.Info().Msgf("updated infraconfig %s", infraProviderConfig.Identifier)
|
||||
if err = c.createMissingResources(ctx, infraProviderResources, infraProviderConfigID, space.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -29,11 +29,13 @@ var WireSet = wire.NewSet(
|
|||
|
||||
func ProvideInfraProvider(
|
||||
tx dbtx.Transactor,
|
||||
gitspaceConfigStore store.GitspaceConfigStore,
|
||||
resourceStore store.InfraProviderResourceStore,
|
||||
configStore store.InfraProviderConfigStore,
|
||||
templateStore store.InfraProviderTemplateStore,
|
||||
infraProviderFactory infraprovider.Factory,
|
||||
spaceFinder refcache.SpaceFinder,
|
||||
) *Service {
|
||||
return NewService(tx, resourceStore, configStore, templateStore, infraProviderFactory, spaceFinder)
|
||||
return NewService(tx, gitspaceConfigStore, resourceStore, configStore, templateStore, infraProviderFactory,
|
||||
spaceFinder)
|
||||
}
|
||||
|
|
|
@ -705,6 +705,12 @@ type (
|
|||
|
||||
// Count the number of gitspace configs in a space matching the given filter.
|
||||
Count(ctx context.Context, filter *types.GitspaceFilter) (int64, error)
|
||||
|
||||
// ListActiveConfigsForInfraProviderResource returns all active configs for the given infra resource.
|
||||
ListActiveConfigsForInfraProviderResource(
|
||||
ctx context.Context,
|
||||
infraProviderResourceID int64,
|
||||
) ([]*types.GitspaceConfig, error)
|
||||
}
|
||||
|
||||
GitspaceInstanceStore interface {
|
||||
|
@ -768,15 +774,18 @@ type (
|
|||
// Find returns a Infra provider resource given a ID from the datastore.
|
||||
Find(ctx context.Context, id int64) (*types.InfraProviderResource, error)
|
||||
|
||||
// FindByIdentifier returns a infra provider resource with a given UID in a space
|
||||
FindByIdentifier(ctx context.Context, spaceID int64, identifier string) (*types.InfraProviderResource, error)
|
||||
// FindByConfigAndIdentifier returns the most recent infra provider resource with a given identifier in
|
||||
// a space for the given infra provider config.
|
||||
FindByConfigAndIdentifier(
|
||||
ctx context.Context,
|
||||
spaceID int64,
|
||||
infraProviderConfigID int64,
|
||||
identifier string,
|
||||
) (*types.InfraProviderResource, error)
|
||||
|
||||
// Create creates a new infra provider resource in the datastore.
|
||||
Create(ctx context.Context, infraProviderResource *types.InfraProviderResource) error
|
||||
|
||||
// Update tries to update the infra provider resource in the datastore.
|
||||
Update(ctx context.Context, infraProviderResource *types.InfraProviderResource) error
|
||||
|
||||
// List lists the infra provider resource present for the gitspace config in a parent space ID in the datastore.
|
||||
List(
|
||||
ctx context.Context,
|
||||
|
@ -784,8 +793,8 @@ type (
|
|||
filter types.ListQueryFilter,
|
||||
) ([]*types.InfraProviderResource, error)
|
||||
|
||||
// DeleteByIdentifier deletes the Infra provider resource with the given identifier for the given space.
|
||||
DeleteByIdentifier(ctx context.Context, spaceID int64, identifier string) error
|
||||
// Delete soft deletes the Infra provider resource with the given id.
|
||||
Delete(ctx context.Context, id int64) error
|
||||
}
|
||||
|
||||
PipelineStore interface {
|
||||
|
|
|
@ -398,6 +398,30 @@ func (s gitspaceConfigStore) FindAll(ctx context.Context, ids []int64) ([]*types
|
|||
return s.mapToGitspaceConfigs(ctx, dst)
|
||||
}
|
||||
|
||||
func (s gitspaceConfigStore) ListActiveConfigsForInfraProviderResource(
|
||||
ctx context.Context,
|
||||
infraProviderResourceID int64,
|
||||
) ([]*types.GitspaceConfig, error) {
|
||||
stmt := database.Builder.
|
||||
Select(gitspaceConfigSelectColumns).
|
||||
From(gitspaceConfigsTable).
|
||||
Where("gconf_infra_provider_resource_id = ?", infraProviderResourceID).
|
||||
Where("gconf_is_deleted = false").
|
||||
Where("gconf_is_marked_for_deletion = false")
|
||||
|
||||
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)
|
||||
var dst []*gitspaceConfigWithLatestInstance
|
||||
if err = db.SelectContext(ctx, &dst, sql, args...); err != nil {
|
||||
return nil, database.ProcessSQLErrorf(ctx, err, "Failed executing list gitspace config query")
|
||||
}
|
||||
return s.ToGitspaceConfigs(ctx, dst)
|
||||
}
|
||||
|
||||
func (s gitspaceConfigStore) mapDBToGitspaceConfig(
|
||||
ctx context.Context,
|
||||
in *gitspaceConfig,
|
||||
|
|
|
@ -124,7 +124,8 @@ func (i infraProviderConfigStore) FindByType(
|
|||
db := dbtx.GetAccessor(ctx, i.db)
|
||||
dst := new([]*infraProviderConfig)
|
||||
if err := db.SelectContext(ctx, dst, sql, args...); err != nil {
|
||||
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to list infraprovider resources")
|
||||
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to list infraprovider configs of type %s for"+
|
||||
" space %d", infraProviderType, spaceID)
|
||||
}
|
||||
return i.mapToInfraProviderConfigs(*dst)
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ package database
|
|||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/harness/gitness/app/store"
|
||||
"github.com/harness/gitness/store/database"
|
||||
|
@ -46,7 +46,9 @@ const (
|
|||
ipreso_disk,
|
||||
ipreso_network,
|
||||
ipreso_region,
|
||||
ipreso_opentofu_params
|
||||
ipreso_metadata,
|
||||
ipreso_is_deleted,
|
||||
ipreso_deleted
|
||||
`
|
||||
infraProviderResourceSelectColumns = "ipreso_id," + infraProviderResourceInsertColumns
|
||||
infraProviderResourceTable = `infra_provider_resources`
|
||||
|
@ -64,14 +66,16 @@ type infraProviderResource struct {
|
|||
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"`
|
||||
Metadata []byte `db:"ipreso_metadata"`
|
||||
Created int64 `db:"ipreso_created"`
|
||||
Updated int64 `db:"ipreso_updated"`
|
||||
IsDeleted bool `db:"ipreso_is_deleted"`
|
||||
Deleted null.Int `db:"ipreso_deleted"`
|
||||
}
|
||||
|
||||
var _ store.InfraProviderResourceStore = (*infraProviderResourceStore)(nil)
|
||||
|
||||
// NewGitspaceConfigStore returns a new GitspaceConfigStore.
|
||||
// NewInfraProviderResourceStore returns a new InfraProviderResourceStore.
|
||||
func NewInfraProviderResourceStore(db *sqlx.DB) store.InfraProviderResourceStore {
|
||||
return &infraProviderResourceStore{
|
||||
db: db,
|
||||
|
@ -82,12 +86,23 @@ 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).
|
||||
func (s infraProviderResourceStore) List(
|
||||
ctx context.Context,
|
||||
infraProviderConfigID int64,
|
||||
_ types.ListQueryFilter,
|
||||
) ([]*types.InfraProviderResource, error) {
|
||||
subQuery := squirrel.Select("MAX(ipreso_created)").
|
||||
From(infraProviderResourceTable).
|
||||
Where("ipreso_infra_provider_config_id = $1", infraProviderConfigID)
|
||||
Where("ipreso_infra_provider_config_id = $1", infraProviderConfigID).
|
||||
Where("ipreso_is_deleted = false").
|
||||
GroupBy("ipreso_uid")
|
||||
|
||||
stmt := squirrel.Select(infraProviderResourceSelectColumns).
|
||||
From(infraProviderResourceTable).
|
||||
Where("ipreso_infra_provider_config_id = $2", infraProviderConfigID).
|
||||
Where("ipreso_is_deleted = false").
|
||||
Where(squirrel.Expr("ipreso_created IN (?)", subQuery)).
|
||||
OrderBy("ipreso_uid", "ipreso_created DESC")
|
||||
|
||||
sql, args, err := stmt.ToSql()
|
||||
if err != nil {
|
||||
|
@ -96,7 +111,8 @@ func (s infraProviderResourceStore) List(ctx context.Context, infraProviderConfi
|
|||
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 to list infraprovider resources")
|
||||
return nil, database.ProcessSQLErrorf(ctx, err, "Failed to list infraprovider resources for config %d",
|
||||
infraProviderConfigID)
|
||||
}
|
||||
return mapToInfraProviderResources(*dst)
|
||||
}
|
||||
|
@ -105,7 +121,8 @@ func (s infraProviderResourceStore) Find(ctx context.Context, id int64) (*types.
|
|||
stmt := database.Builder.
|
||||
Select(infraProviderResourceSelectColumns).
|
||||
From(infraProviderResourceTable).
|
||||
Where(infraProviderResourceIDColumn+" = $1", id)
|
||||
Where(infraProviderResourceIDColumn+" = $1", id).
|
||||
Where("ipreso_is_deleted = false")
|
||||
|
||||
sql, args, err := stmt.ToSql()
|
||||
if err != nil {
|
||||
|
@ -119,16 +136,23 @@ func (s infraProviderResourceStore) Find(ctx context.Context, id int64) (*types.
|
|||
return mapToInfraProviderResource(dst)
|
||||
}
|
||||
|
||||
func (s infraProviderResourceStore) FindByIdentifier(
|
||||
func (s infraProviderResourceStore) FindByConfigAndIdentifier(
|
||||
ctx context.Context,
|
||||
spaceID int64,
|
||||
infraProviderConfigID int64,
|
||||
identifier string,
|
||||
) (*types.InfraProviderResource, error) {
|
||||
stmt := database.Builder.
|
||||
Select(infraProviderResourceSelectColumns).
|
||||
From(infraProviderResourceTable).
|
||||
Where("ipreso_uid = $1", identifier).
|
||||
Where("ipreso_space_id = $2", spaceID)
|
||||
stmt :=
|
||||
database.Builder.
|
||||
Select(infraProviderResourceSelectColumns).
|
||||
From(infraProviderResourceTable).
|
||||
OrderBy("ipreso_created DESC").
|
||||
Limit(1).
|
||||
Where("ipreso_uid = ?", identifier).
|
||||
Where("ipreso_space_id = ?", spaceID).
|
||||
Where("ipreso_infra_provider_config_id = ?", infraProviderConfigID).
|
||||
Where("ipreso_is_deleted = false")
|
||||
|
||||
sql, args, err := stmt.ToSql()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "Failed to convert squirrel builder to sql")
|
||||
|
@ -145,7 +169,7 @@ func (s infraProviderResourceStore) Create(
|
|||
ctx context.Context,
|
||||
infraProviderResource *types.InfraProviderResource,
|
||||
) error {
|
||||
jsonBytes, marshalErr := json.Marshal(infraProviderResource.Metadata)
|
||||
metadata, marshalErr := json.Marshal(infraProviderResource.Metadata)
|
||||
if marshalErr != nil {
|
||||
return marshalErr
|
||||
}
|
||||
|
@ -165,7 +189,9 @@ func (s infraProviderResourceStore) Create(
|
|||
infraProviderResource.Disk,
|
||||
infraProviderResource.Network,
|
||||
infraProviderResource.Region,
|
||||
jsonBytes,
|
||||
metadata,
|
||||
infraProviderResource.IsDeleted,
|
||||
infraProviderResource.Deleted,
|
||||
).
|
||||
Suffix(ReturningClause + infraProviderResourceIDColumn)
|
||||
sql, args, err := stmt.ToSql()
|
||||
|
@ -180,57 +206,9 @@ func (s infraProviderResourceStore) Create(
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s infraProviderResourceStore) Update(
|
||||
ctx context.Context,
|
||||
infraProviderResource *types.InfraProviderResource,
|
||||
) error {
|
||||
dbinfraProviderResource, err := s.mapToInternalInfraProviderResource(infraProviderResource)
|
||||
if err != nil {
|
||||
return fmt.Errorf(
|
||||
"failed to map to DB Obj for infraprovider resource %s", infraProviderResource.UID)
|
||||
}
|
||||
stmt := database.Builder.
|
||||
Update(infraProviderResourceTable).
|
||||
Set("ipreso_display_name", dbinfraProviderResource.Name).
|
||||
Set("ipreso_memory", dbinfraProviderResource.Memory).
|
||||
Set("ipreso_disk", dbinfraProviderResource.Disk).
|
||||
Set("ipreso_network", dbinfraProviderResource.Network).
|
||||
Set("ipreso_region", dbinfraProviderResource.Region).
|
||||
Set("ipreso_opentofu_params", dbinfraProviderResource.OpenTofuParams).
|
||||
Set("ipreso_updated", dbinfraProviderResource.Updated).
|
||||
Where("ipreso_id = ?", infraProviderResource.ID)
|
||||
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 update infraprovider resource %s", infraProviderResource.UID)
|
||||
}
|
||||
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 %s", identifier)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func mapToInfraProviderResource(in *infraProviderResource) (*types.InfraProviderResource, error) {
|
||||
metadataParamsMap := make(map[string]string)
|
||||
marshalErr := json.Unmarshal(in.OpenTofuParams, &metadataParamsMap)
|
||||
marshalErr := json.Unmarshal(in.Metadata, &metadataParamsMap)
|
||||
if marshalErr != nil {
|
||||
return nil, marshalErr
|
||||
}
|
||||
|
@ -249,30 +227,8 @@ func mapToInfraProviderResource(in *infraProviderResource) (*types.InfraProvider
|
|||
Metadata: metadataParamsMap,
|
||||
Created: in.Created,
|
||||
Updated: in.Updated,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s infraProviderResourceStore) mapToInternalInfraProviderResource(
|
||||
in *types.InfraProviderResource,
|
||||
) (*infraProviderResource, error) {
|
||||
jsonBytes, marshalErr := json.Marshal(in.Metadata)
|
||||
if marshalErr != nil {
|
||||
return nil, marshalErr
|
||||
}
|
||||
return &infraProviderResource{
|
||||
Identifier: in.UID,
|
||||
InfraProviderConfigID: in.InfraProviderConfigID,
|
||||
InfraProviderType: in.InfraProviderType,
|
||||
Name: in.Name,
|
||||
SpaceID: in.SpaceID,
|
||||
CPU: null.StringFromPtr(in.CPU),
|
||||
Memory: null.StringFromPtr(in.Memory),
|
||||
Disk: null.StringFromPtr(in.Disk),
|
||||
Network: null.StringFromPtr(in.Network),
|
||||
Region: in.Region,
|
||||
OpenTofuParams: jsonBytes,
|
||||
Created: in.Created,
|
||||
Updated: in.Updated,
|
||||
IsDeleted: in.IsDeleted,
|
||||
Deleted: in.Deleted.Ptr(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
@ -371,3 +327,23 @@ func (i InfraProviderResourceView) FindMany(ctx context.Context, ids []int64) ([
|
|||
}
|
||||
return mapToInfraProviderResources(*dst)
|
||||
}
|
||||
|
||||
func (s infraProviderResourceStore) Delete(ctx context.Context, id int64) error {
|
||||
now := time.Now().UnixMilli()
|
||||
stmt := database.Builder.
|
||||
Update(infraProviderResourceTable).
|
||||
Set("ipreso_updated", now).
|
||||
Set("ipreso_deleted", now).
|
||||
Set("ipreso_is_deleted", true).
|
||||
Where("ipreso_id = $4", id)
|
||||
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 update infraprovider resource %d", id)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
DROP INDEX infra_provider_resources_uid_space_id_config_id_created;
|
||||
|
||||
ALTER TABLE infra_provider_resources
|
||||
RENAME COLUMN ipreso_metadata TO ipreso_opentofu_params;
|
||||
ALTER TABLE infra_provider_resources
|
||||
DROP COLUMN ipreso_is_deleted;
|
||||
ALTER TABLE infra_provider_resources
|
||||
DROP COLUMN ipreso_deleted;
|
||||
|
||||
|
||||
CREATE UNIQUE INDEX infra_provider_resources_uid_space_id ON infra_provider_resources (ipreso_uid, ipreso_space_id);
|
|
@ -0,0 +1,10 @@
|
|||
ALTER TABLE infra_provider_resources
|
||||
RENAME COLUMN ipreso_opentofu_params TO ipreso_metadata;
|
||||
ALTER TABLE infra_provider_resources
|
||||
ADD COLUMN ipreso_is_deleted BOOL NOT NULL DEFAULT false;
|
||||
ALTER TABLE infra_provider_resources
|
||||
ADD COLUMN ipreso_deleted BIGINT;
|
||||
|
||||
DROP INDEX infra_provider_resources_uid_space_id;
|
||||
CREATE UNIQUE INDEX infra_provider_resources_uid_space_id_config_id_created ON infra_provider_resources
|
||||
(ipreso_uid, ipreso_space_id, ipreso_infra_provider_config_id, ipreso_created);
|
|
@ -0,0 +1,11 @@
|
|||
DROP INDEX infra_provider_resources_uid_space_id_config_id_created;
|
||||
|
||||
ALTER TABLE infra_provider_resources
|
||||
RENAME COLUMN ipreso_metadata TO ipreso_opentofu_params;
|
||||
ALTER TABLE infra_provider_resources
|
||||
DROP COLUMN ipreso_is_deleted;
|
||||
ALTER TABLE infra_provider_resources
|
||||
DROP COLUMN ipreso_deleted;
|
||||
|
||||
|
||||
CREATE UNIQUE INDEX infra_provider_resources_uid_space_id ON infra_provider_resources (ipreso_uid, ipreso_space_id);
|
|
@ -0,0 +1,10 @@
|
|||
ALTER TABLE infra_provider_resources
|
||||
RENAME COLUMN ipreso_opentofu_params TO ipreso_metadata;
|
||||
ALTER TABLE infra_provider_resources
|
||||
ADD COLUMN ipreso_is_deleted BOOL NOT NULL DEFAULT false;
|
||||
ALTER TABLE infra_provider_resources
|
||||
ADD COLUMN ipreso_deleted BIGINT;
|
||||
|
||||
DROP INDEX infra_provider_resources_uid_space_id;
|
||||
CREATE UNIQUE INDEX infra_provider_resources_uid_space_id_config_id_created ON infra_provider_resources
|
||||
(ipreso_uid, ipreso_space_id, ipreso_infra_provider_config_id, ipreso_created);
|
|
@ -308,7 +308,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
|
|||
}
|
||||
dockerProvider := infraprovider.ProvideDockerProvider(dockerConfig, dockerClientFactory, reporter2)
|
||||
factory := infraprovider.ProvideFactory(dockerProvider)
|
||||
infraproviderService := infraprovider2.ProvideInfraProvider(transactor, infraProviderResourceStore, infraProviderConfigStore, infraProviderTemplateStore, factory, spaceFinder)
|
||||
infraproviderService := infraprovider2.ProvideInfraProvider(transactor, gitspaceConfigStore, infraProviderResourceStore, infraProviderConfigStore, infraProviderTemplateStore, factory, spaceFinder)
|
||||
gitnessSCM := scm.ProvideGitnessSCM(repoStore, repoFinder, gitInterface, tokenStore, principalStore, provider)
|
||||
genericSCM := scm.ProvideGenericSCM()
|
||||
scmFactory := scm.ProvideFactory(gitnessSCM, genericSCM)
|
||||
|
|
|
@ -330,6 +330,6 @@ func volumeName(spacePath string, resourceKey string) string {
|
|||
return name
|
||||
}
|
||||
|
||||
func (d DockerProvider) ValidateConfigAndResources(_ *types.InfraProviderConfig) error {
|
||||
func (d DockerProvider) ValidateConfig(_ *types.InfraProviderConfig) error {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -69,6 +69,6 @@ type InfraProvider interface {
|
|||
// ProvisioningType specifies whether the provider will provision new infra resources or it will reuse existing.
|
||||
ProvisioningType() enum.InfraProvisioningType
|
||||
|
||||
// ValidateConfigAndResources checks if the provided infra config and resources are valid as per the provider.
|
||||
ValidateConfigAndResources(infraProviderConfig *types.InfraProviderConfig) error
|
||||
// ValidateConfig checks if the provided infra config is as per the provider.
|
||||
ValidateConfig(infraProviderConfig *types.InfraProviderConfig) error
|
||||
}
|
||||
|
|
|
@ -54,6 +54,8 @@ type InfraProviderResource struct {
|
|||
InfraProviderType enum.InfraProviderType `json:"infra_provider_type"`
|
||||
Created int64 `json:"created"`
|
||||
Updated int64 `json:"updated"`
|
||||
IsDeleted bool `json:"is_deleted,omitempty"`
|
||||
Deleted *int64 `json:"deleted,omitempty"`
|
||||
}
|
||||
|
||||
func (i *InfraProviderResource) Identifier() int64 {
|
||||
|
|
Loading…
Reference in New Issue