mirror of https://github.com/harness/drone.git
220 lines
7.0 KiB
Go
220 lines
7.0 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 infrastructure
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"strconv"
|
|
"time"
|
|
|
|
"github.com/harness/gitness/app/store"
|
|
"github.com/harness/gitness/infraprovider"
|
|
"github.com/harness/gitness/types"
|
|
"github.com/harness/gitness/types/enum"
|
|
)
|
|
|
|
var _ InfraProvisioner = (*infraProvisioner)(nil)
|
|
|
|
type Config struct {
|
|
AgentPort int
|
|
}
|
|
|
|
type infraProvisioner struct {
|
|
infraProviderConfigStore store.InfraProviderConfigStore
|
|
infraProviderResourceStore store.InfraProviderResourceStore
|
|
providerFactory infraprovider.Factory
|
|
infraProviderTemplateStore store.InfraProviderTemplateStore
|
|
infraProvisionedStore store.InfraProvisionedStore
|
|
config *Config
|
|
}
|
|
|
|
func NewInfraProvisionerService(
|
|
infraProviderConfigStore store.InfraProviderConfigStore,
|
|
infraProviderResourceStore store.InfraProviderResourceStore,
|
|
providerFactory infraprovider.Factory,
|
|
infraProviderTemplateStore store.InfraProviderTemplateStore,
|
|
infraProvisionedStore store.InfraProvisionedStore,
|
|
config *Config,
|
|
) InfraProvisioner {
|
|
return &infraProvisioner{
|
|
infraProviderConfigStore: infraProviderConfigStore,
|
|
infraProviderResourceStore: infraProviderResourceStore,
|
|
providerFactory: providerFactory,
|
|
infraProviderTemplateStore: infraProviderTemplateStore,
|
|
infraProvisionedStore: infraProvisionedStore,
|
|
config: config,
|
|
}
|
|
}
|
|
|
|
func (i infraProvisioner) getConfigFromResource(
|
|
ctx context.Context,
|
|
infraProviderResource types.InfraProviderResource,
|
|
) (*types.InfraProviderConfig, error) {
|
|
config, err := i.infraProviderConfigStore.Find(ctx, infraProviderResource.InfraProviderConfigID)
|
|
if err != nil {
|
|
return nil, fmt.Errorf(
|
|
"unable to get infra provider details for ID %d: %w",
|
|
infraProviderResource.InfraProviderConfigID, err)
|
|
}
|
|
return config, nil
|
|
}
|
|
|
|
func (i infraProvisioner) getInfraProvider(
|
|
infraProviderType enum.InfraProviderType,
|
|
) (infraprovider.InfraProvider, error) {
|
|
infraProvider, err := i.providerFactory.GetInfraProvider(infraProviderType)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("unable to get infra provider of type %v: %w", infraProviderType, err)
|
|
}
|
|
return infraProvider, nil
|
|
}
|
|
|
|
func (i infraProvisioner) getTemplateParams(
|
|
ctx context.Context,
|
|
infraProvider infraprovider.InfraProvider,
|
|
infraProviderResource types.InfraProviderResource,
|
|
) ([]types.InfraProviderParameter, error) {
|
|
var params []types.InfraProviderParameter
|
|
templateParams := infraProvider.TemplateParams()
|
|
|
|
for _, param := range templateParams {
|
|
key := param.Name
|
|
if infraProviderResource.Metadata[key] != "" {
|
|
templateIdentifier := infraProviderResource.Metadata[key]
|
|
|
|
template, err := i.infraProviderTemplateStore.FindByIdentifier(
|
|
ctx, infraProviderResource.SpaceID, templateIdentifier)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("unable to get template params for ID %s: %w",
|
|
infraProviderResource.Metadata[key], err)
|
|
}
|
|
|
|
params = append(params, types.InfraProviderParameter{
|
|
Name: key,
|
|
Value: template.Data,
|
|
})
|
|
}
|
|
}
|
|
|
|
return params, nil
|
|
}
|
|
|
|
func (i infraProvisioner) paramsFromResource(
|
|
infraProviderResource types.InfraProviderResource,
|
|
infraProvider infraprovider.InfraProvider,
|
|
) []types.InfraProviderParameter {
|
|
// NOTE: templateParamsMap is required to filter out template params since their values have already been fetched
|
|
// and we dont need the template identifiers, which are the values for template params in the resource Metadata.
|
|
templateParamsMap := make(map[string]bool)
|
|
for _, templateParam := range infraProvider.TemplateParams() {
|
|
templateParamsMap[templateParam.Name] = true
|
|
}
|
|
|
|
params := make([]types.InfraProviderParameter, 0)
|
|
|
|
for key, value := range infraProviderResource.Metadata {
|
|
if key == "" || value == "" || templateParamsMap[key] {
|
|
continue
|
|
}
|
|
params = append(params, types.InfraProviderParameter{
|
|
Name: key,
|
|
Value: value,
|
|
})
|
|
}
|
|
return params
|
|
}
|
|
|
|
func serializeInfraProviderParams(in []types.InfraProviderParameter) (string, error) {
|
|
output, err := json.Marshal(in)
|
|
if err != nil {
|
|
return "", fmt.Errorf("unable to marshal infra provider params: %w", err)
|
|
}
|
|
return string(output), nil
|
|
}
|
|
|
|
func deserializeInfraProviderParams(in string) ([]types.InfraProviderParameter, error) {
|
|
var parameters []types.InfraProviderParameter
|
|
err := json.Unmarshal([]byte(in), ¶meters)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("unable to unmarshal infra provider params %+v: %w", in, err)
|
|
}
|
|
return parameters, nil
|
|
}
|
|
|
|
func (i infraProvisioner) responseMetadata(infra types.Infrastructure) (string, error) {
|
|
output, err := json.Marshal(infra)
|
|
if err != nil {
|
|
return "", fmt.Errorf("unable to marshal infra object %+v: %w", infra, err)
|
|
}
|
|
|
|
return string(output), nil
|
|
}
|
|
|
|
func (i infraProvisioner) getAllParamsFromDB(
|
|
ctx context.Context,
|
|
infraProviderResource types.InfraProviderResource,
|
|
infraProvider infraprovider.InfraProvider,
|
|
) ([]types.InfraProviderParameter, error) {
|
|
var allParams []types.InfraProviderParameter
|
|
|
|
templateParams, err := i.getTemplateParams(ctx, infraProvider, infraProviderResource)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
allParams = append(allParams, templateParams...)
|
|
|
|
params := i.paramsFromResource(infraProviderResource, infraProvider)
|
|
|
|
allParams = append(allParams, params...)
|
|
|
|
return allParams, nil
|
|
}
|
|
|
|
func (i infraProvisioner) updateInfraProvisionedRecord(
|
|
ctx context.Context,
|
|
gitspaceConfig types.GitspaceConfig,
|
|
deprovisionedInfra types.Infrastructure,
|
|
) error {
|
|
infraProvisionedLatest, err := i.infraProvisionedStore.FindLatestByGitspaceInstanceID(
|
|
ctx, gitspaceConfig.SpaceID, gitspaceConfig.GitspaceInstance.ID)
|
|
if err != nil {
|
|
return fmt.Errorf(
|
|
"could not find latest infra provisioned entity for instance %d: %w",
|
|
gitspaceConfig.GitspaceInstance.ID, err)
|
|
}
|
|
|
|
responseMetadata, err := i.responseMetadata(deprovisionedInfra)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
infraProvisionedLatest.InfraStatus = deprovisionedInfra.Status
|
|
infraProvisionedLatest.ServerHostIP = deprovisionedInfra.AgentHost
|
|
infraProvisionedLatest.ServerHostPort = strconv.Itoa(deprovisionedInfra.AgentPort)
|
|
infraProvisionedLatest.ProxyHost = deprovisionedInfra.ProxyAgentHost
|
|
infraProvisionedLatest.ProxyPort = int32(deprovisionedInfra.ProxyAgentPort)
|
|
infraProvisionedLatest.ResponseMetadata = &responseMetadata
|
|
infraProvisionedLatest.Updated = time.Now().UnixMilli()
|
|
|
|
err = i.infraProvisionedStore.Update(ctx, infraProvisionedLatest)
|
|
if err != nil {
|
|
return fmt.Errorf("unable to update infraProvisioned %d: %w", infraProvisionedLatest.ID, err)
|
|
}
|
|
return nil
|
|
}
|