feat: [CDE-507]:add connector details to gitspace config (#3020)

* Merge branch 'main' of https://git0.harness.io/l7B_kbSEQD2wjrM7PShm5w/PROD/Harness_Commons/gitness into pull-image-secret
* modify resume gitspace
* unchange provision func
* change provision func
* remove unnecessary arg
* add password field
* modify platform connector type
* remove unnecessary func
* fix lint
* remove docker registry
* modify event name
* add connector details package
* separate types into different files
* fix lint
* change func name
* change func name
* change connector name
* change package name
* add git config arg
* add comment
* remove unused const
* change event name
* fix wire gen
* add wire for artifact registry
* remove fmt print
* add artifact secret resolver
This commit is contained in:
Deepak Bhatt 2024-11-22 06:21:10 +00:00 committed by Harness
parent d3d1ba32ff
commit 266e7a7866
14 changed files with 362 additions and 6 deletions

View File

@ -90,6 +90,10 @@ func eventsMessageMapping() map[enum.GitspaceEventType]string {
gitspaceConfigsMap[enum.GitspaceEventTypeFetchDevcontainerCompleted] = "Fetched devcontainer config"
gitspaceConfigsMap[enum.GitspaceEventTypeFetchDevcontainerFailed] = "Fetching devcontainer config failed"
gitspaceConfigsMap[enum.GitspaceEventTypeFetchConnectorsDetailsStart] = "Fetching connectors details..."
gitspaceConfigsMap[enum.GitspaceEventTypeFetchConnectorsDetailsCompleted] = "Fetched connectors details"
gitspaceConfigsMap[enum.GitspaceEventTypeFetchConnectorsDetailsFailed] = "Fetching connectors details failed"
gitspaceConfigsMap[enum.GitspaceEventTypeInfraProvisioningStart] = "Provisioning infrastructure..."
gitspaceConfigsMap[enum.GitspaceEventTypeInfraProvisioningCompleted] = "Provisioning infrastructure completed"
gitspaceConfigsMap[enum.GitspaceEventTypeInfraProvisioningFailed] = "Provisioning infrastructure failed"

View File

@ -135,6 +135,21 @@ func (o orchestrator) ResumeStartGitspace(
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceCreationStart)
// fetch connector information and send details to gitspace agent
gitspaceSpecs := scmResolvedDetails.DevcontainerConfig.Customizations.ExtractGitspaceSpec()
connectors, err := o.platformConnector.FetchConnectors(ctx, getConnectorIDs(gitspaceSpecs))
if err != nil {
fetchConnectorErr := fmt.Errorf("failed to fetch connectors for gitspace: %v :%w",
getConnectorIDs(gitspaceSpecs),
err,
)
return *gitspaceInstance, &types.GitspaceError{
Error: fetchConnectorErr,
ErrorMessage: ptr.String(fetchConnectorErr.Error()),
}
}
gitspaceConfig.Connectors = connectors
// NOTE: Currently we use a static identifier as the Gitspace user.
gitspaceConfig.GitspaceUser.Identifier = harnessUser

View File

@ -23,6 +23,7 @@ import (
"github.com/harness/gitness/app/gitspace/infrastructure"
"github.com/harness/gitness/app/gitspace/orchestrator/container"
"github.com/harness/gitness/app/gitspace/orchestrator/ide"
"github.com/harness/gitness/app/gitspace/platformconnector"
"github.com/harness/gitness/app/gitspace/scm"
"github.com/harness/gitness/app/gitspace/secret"
"github.com/harness/gitness/app/store"
@ -42,6 +43,7 @@ type Config struct {
type orchestrator struct {
scm *scm.SCM
platformConnector platformconnector.PlatformConnector
infraProviderResourceStore store.InfraProviderResourceStore
infraProvisioner infrastructure.InfraProvisioner
containerOrchestrator container.Orchestrator
@ -56,6 +58,7 @@ var _ Orchestrator = (*orchestrator)(nil)
func NewOrchestrator(
scm *scm.SCM,
platformConnector platformconnector.PlatformConnector,
infraProviderResourceStore store.InfraProviderResourceStore,
infraProvisioner infrastructure.InfraProvisioner,
containerOrchestrator container.Orchestrator,
@ -67,6 +70,7 @@ func NewOrchestrator(
) Orchestrator {
return orchestrator{
scm: scm,
platformConnector: platformConnector,
infraProviderResourceStore: infraProviderResourceStore,
infraProvisioner: infraProvisioner,
containerOrchestrator: containerOrchestrator,
@ -96,6 +100,26 @@ func (o orchestrator) TriggerStartGitspace(
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeFetchDevcontainerCompleted)
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeFetchConnectorsDetailsStart)
gitspaceSpecs := devcontainerConfig.Customizations.ExtractGitspaceSpec()
connectors, err := o.platformConnector.FetchConnectors(ctx, getConnectorIDs(gitspaceSpecs))
if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeFetchConnectorsDetailsFailed)
log.Ctx(ctx).Err(err).Msgf("failed to fetch connectors for gitspace: %v",
getConnectorIDs(gitspaceSpecs),
)
return &types.GitspaceError{
Error: fmt.Errorf("failed to fetch connectors for gitspace: %v :%w",
getConnectorIDs(gitspaceSpecs),
err,
),
ErrorMessage: ptr.String(err.Error()),
}
}
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeFetchConnectorsDetailsCompleted)
gitspaceConfig.Connectors = connectors
requiredGitspacePorts, err := o.getPortsRequiredForGitspace(gitspaceConfig, devcontainerConfig)
if err != nil {
err = fmt.Errorf("cannot get the ports required for gitspace during start: %w", err)
@ -120,6 +144,19 @@ func (o orchestrator) TriggerStartGitspace(
return nil
}
func getConnectorIDs(specs *types.GitspaceCustomizationSpecs) []string {
if specs == nil {
return nil
}
var connectorIDs []string
for _, connector := range specs.Connectors {
connectorIDs = append(connectorIDs, connector.ID)
}
return connectorIDs
}
func (o orchestrator) TriggerStopGitspace(
ctx context.Context,
gitspaceConfig types.GitspaceConfig,

View File

@ -19,6 +19,7 @@ import (
"github.com/harness/gitness/app/gitspace/infrastructure"
"github.com/harness/gitness/app/gitspace/orchestrator/container"
"github.com/harness/gitness/app/gitspace/orchestrator/ide"
"github.com/harness/gitness/app/gitspace/platformconnector"
"github.com/harness/gitness/app/gitspace/scm"
"github.com/harness/gitness/app/gitspace/secret"
"github.com/harness/gitness/app/store"
@ -33,6 +34,7 @@ var WireSet = wire.NewSet(
func ProvideOrchestrator(
scm *scm.SCM,
platformConnector platformconnector.PlatformConnector,
infraProviderResourceStore store.InfraProviderResourceStore,
infraProvisioner infrastructure.InfraProvisioner,
containerOrchestrator container.Orchestrator,
@ -44,6 +46,7 @@ func ProvideOrchestrator(
) Orchestrator {
return NewOrchestrator(
scm,
platformConnector,
infraProviderResourceStore,
infraProvisioner,
containerOrchestrator,

View File

@ -0,0 +1,40 @@
// 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 platformconnector
import (
"context"
"github.com/harness/gitness/types"
)
var _ PlatformConnector = (*GitnessPlatformConnector)(nil)
type GitnessPlatformConnector struct{}
func NewGitnessPlatformConnector() *GitnessPlatformConnector {
return &GitnessPlatformConnector{}
}
func (g *GitnessPlatformConnector) FetchConnectors(
_ context.Context,
ids []string,
) ([]types.PlatformConnector, error) {
result := make([]types.PlatformConnector, len(ids))
for i, id := range ids {
result[i] = types.PlatformConnector{ID: id}
}
return result, nil
}

View File

@ -0,0 +1,29 @@
// 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 platformconnector
import (
"context"
"github.com/harness/gitness/types"
)
type PlatformConnector interface {
// FetchConnectors fetches connector details from given list of connector IDs
FetchConnectors(
ctx context.Context,
connectorIDs []string,
) ([]types.PlatformConnector, error)
}

View File

@ -0,0 +1,28 @@
// 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 platformconnector
import (
"github.com/google/wire"
)
// WireSet provides a wire set for this package.
var WireSet = wire.NewSet(
ProvideGitnessPlatformConnector,
)
func ProvideGitnessPlatformConnector() PlatformConnector {
return NewGitnessPlatformConnector()
}

View File

@ -67,6 +67,7 @@ import (
containerGit "github.com/harness/gitness/app/gitspace/orchestrator/git"
"github.com/harness/gitness/app/gitspace/orchestrator/ide"
containerUser "github.com/harness/gitness/app/gitspace/orchestrator/user"
"github.com/harness/gitness/app/gitspace/platformconnector"
"github.com/harness/gitness/app/gitspace/scm"
gitspacesecret "github.com/harness/gitness/app/gitspace/secret"
"github.com/harness/gitness/app/pipeline/canceler"
@ -256,6 +257,7 @@ func initSystem(ctx context.Context, config *types.Config) (*cliserver.System, e
publickey.WireSet,
migrate.WireSet,
scm.WireSet,
platformconnector.WireSet,
gitspacesecret.WireSet,
orchestrator.WireSet,
containerorchestrator.WireSet,

View File

@ -56,6 +56,7 @@ import (
git2 "github.com/harness/gitness/app/gitspace/orchestrator/git"
"github.com/harness/gitness/app/gitspace/orchestrator/ide"
user2 "github.com/harness/gitness/app/gitspace/orchestrator/user"
"github.com/harness/gitness/app/gitspace/platformconnector"
"github.com/harness/gitness/app/gitspace/scm"
"github.com/harness/gitness/app/gitspace/secret"
"github.com/harness/gitness/app/pipeline/canceler"
@ -310,6 +311,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
genericSCM := scm.ProvideGenericSCM()
scmFactory := scm.ProvideFactory(gitnessSCM, genericSCM)
scmSCM := scm.ProvideSCM(scmFactory)
platformConnector := platformconnector.ProvideGitnessPlatformConnector()
infraProvisionedStore := database.ProvideInfraProvisionedStore(db)
infrastructureConfig := server.ProvideGitspaceInfraProvisionerConfig(config)
infraProvisioner := infrastructure.ProvideInfraProvisionerService(infraProviderConfigStore, infraProviderResourceStore, factory, infraProviderTemplateStore, infraProvisionedStore, infrastructureConfig)
@ -324,7 +326,7 @@ func initSystem(ctx context.Context, config *types.Config) (*server.System, erro
vsCodeWeb := ide.ProvideVSCodeWebService(vsCodeWebConfig)
passwordResolver := secret.ProvidePasswordResolver()
resolverFactory := secret.ProvideResolverFactory(passwordResolver)
orchestratorOrchestrator := orchestrator.ProvideOrchestrator(scmSCM, infraProviderResourceStore, infraProvisioner, containerOrchestrator, eventsReporter, orchestratorConfig, vsCode, vsCodeWeb, resolverFactory)
orchestratorOrchestrator := orchestrator.ProvideOrchestrator(scmSCM, platformConnector, infraProviderResourceStore, infraProvisioner, containerOrchestrator, eventsReporter, orchestratorConfig, vsCode, vsCodeWeb, resolverFactory)
gitspaceService := gitspace.ProvideGitspace(transactor, gitspaceConfigStore, gitspaceInstanceStore, eventsReporter, gitspaceEventStore, spaceStore, infraproviderService, orchestratorOrchestrator, scmSCM, config)
spaceController := space.ProvideController(config, transactor, provider, streamer, spaceIdentifier, authorizer, spacePathStore, pipelineStore, secretStore, connectorStore, templateStore, spaceStore, repoStore, principalStore, repoController, membershipStore, listService, repository, exporterRepository, resourceLimiter, publicaccessService, auditService, gitspaceService, labelService, instrumentService, executionStore, rulesService)
reporter3, err := events5.ProvideReporter(eventsSystem)

View File

@ -18,9 +18,10 @@ import "encoding/json"
// DevcontainerConfig is parsed from code repos and follows the devcontainer.json spec. It uses camelCase.
type DevcontainerConfig struct {
Image string `json:"image"`
PostCreateCommand string `json:"postCreateCommand"` //nolint:tagliatelle
PostStartCommand string `json:"postStartCommand"` //nolint:tagliatelle
ForwardPorts []json.Number `json:"forwardPorts"` //nolint:tagliatelle
ContainerEnv map[string]string `json:"containerEnv"` //nolint:tagliatelle
Image string `json:"image"`
PostCreateCommand string `json:"postCreateCommand"` //nolint:tagliatelle
PostStartCommand string `json:"postStartCommand"` //nolint:tagliatelle
ForwardPorts []json.Number `json:"forwardPorts"` //nolint:tagliatelle
ContainerEnv map[string]string `json:"containerEnv"` //nolint:tagliatelle
Customizations DevContainerConfigCustomizations `json:"customizations"`
}

View File

@ -0,0 +1,53 @@
// 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 types
import "encoding/json"
const (
GitspaceCustomizationsKey CustomizationsKey = "harnessGitspaces"
)
type CustomizationsKey string
func (ck CustomizationsKey) String() string {
return string(ck)
}
type DevContainerConfigCustomizations map[string]interface{}
func (dcc DevContainerConfigCustomizations) ExtractGitspaceSpec() *GitspaceCustomizationSpecs {
val, ok := dcc[GitspaceCustomizationsKey.String()]
if !ok {
return nil
}
// val has underlying map[string]interface{} type as it is default for JSON objects
// converting to json so that val can be marshaled to GitspaceCustomizationSpecs type.
rawData, _ := json.Marshal(&val)
var gitspaceSpecs GitspaceCustomizationSpecs
if err := json.Unmarshal(rawData, &gitspaceSpecs); err != nil {
return nil
}
return &gitspaceSpecs
}
type GitspaceCustomizationSpecs struct {
Connectors []struct {
Type string `json:"type"`
ID string `json:"identifier"`
} `json:"connectors"`
}

View File

@ -85,6 +85,11 @@ const (
GitspaceEventTypeFetchDevcontainerCompleted GitspaceEventType = "fetch_devcontainer_completed"
GitspaceEventTypeFetchDevcontainerFailed GitspaceEventType = "fetch_devcontainer_failed"
// Fetch artifact registry secret.
GitspaceEventTypeFetchConnectorsDetailsStart GitspaceEventType = "fetch_connectors_details_start"
GitspaceEventTypeFetchConnectorsDetailsCompleted GitspaceEventType = "fetch_connectors_details_completed" //nolint
GitspaceEventTypeFetchConnectorsDetailsFailed GitspaceEventType = "fetch_connectors_details_failed"
// Infra provisioning events.
GitspaceEventTypeInfraProvisioningStart GitspaceEventType = "infra_provisioning_start"
GitspaceEventTypeInfraProvisioningCompleted GitspaceEventType = "infra_provisioning_completed"

View File

@ -35,6 +35,7 @@ type GitspaceConfig struct {
InfraProviderResource InfraProviderResource `json:"resource"`
CodeRepo
GitspaceUser
Connectors []PlatformConnector `json:"-"`
}
type CodeRepo struct {

136
types/platform_connector.go Normal file
View File

@ -0,0 +1,136 @@
// 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 types
const (
UnknownPlatformConnectorType PlatformConnectorType = "unknown"
ArtifactoryPlatformConnectorType PlatformConnectorType = "Artifactory"
DockerRegistryPlatformConnectorType PlatformConnectorType = "DockerRegistry"
UnknownPlatformConnectorAuthType PlatformConnectorAuthType = "unknown"
UserNamePasswordPlatformConnectorAuthType PlatformConnectorAuthType = "UsernamePassword"
AnonymousPlatformConnectorAuthType PlatformConnectorAuthType = "Anonymous"
)
var (
platformConnectorTypeMapping = map[string]PlatformConnectorType{
ArtifactoryPlatformConnectorType.String(): ArtifactoryPlatformConnectorType,
DockerRegistryPlatformConnectorType.String(): DockerRegistryPlatformConnectorType,
}
platformConnectorAuthTypeMapping = map[string]PlatformConnectorAuthType{
UserNamePasswordPlatformConnectorAuthType.String(): UserNamePasswordPlatformConnectorAuthType,
AnonymousPlatformConnectorAuthType.String(): AnonymousPlatformConnectorAuthType,
}
)
type PlatformConnectorType string
func (t PlatformConnectorType) String() string { return string(t) }
func ToPlatformConnectorType(s string) PlatformConnectorType {
if val, ok := platformConnectorTypeMapping[s]; ok {
return val
}
return UnknownPlatformConnectorType
}
type PlatformConnectorAuthType string
func (t PlatformConnectorAuthType) String() string { return string(t) }
func ToPlatformConnectorAuthType(s string) PlatformConnectorAuthType {
if val, ok := platformConnectorAuthTypeMapping[s]; ok {
return val
}
return UnknownPlatformConnectorAuthType
}
type PlatformConnector struct {
ID string
Name string
ConnectorSpec PlatformConnectorSpec
}
type PlatformConnectorSpec struct {
Type PlatformConnectorType
// ArtifactoryURL is for ArtifactoryPlatformConnectorType
ArtifactoryURL string
// DockerRegistryURL is for DockerRegistryPlatformConnectorType
DockerRegistryURL string
AuthSpec PlatformConnectorAuthSpec
EnabledProxy bool
}
// PlatformConnectorAuthSpec provide auth details.
// PlatformConnectorAuthSpec is empty for AnonymousPlatformConnectorAuthType.
type PlatformConnectorAuthSpec struct {
AuthType PlatformConnectorAuthType
// userName can be empty when userName is encrypted.
UserName string
// UserNameRef can be empty when userName is not encrypted
UserNameRef string
Password string
PasswordRef string
}
func (c PlatformConnectorSpec) ExtractRegistryURL() string {
switch c.Type {
case DockerRegistryPlatformConnectorType:
return c.DockerRegistryURL
case ArtifactoryPlatformConnectorType:
return c.ArtifactoryURL
case UnknownPlatformConnectorType:
return ""
default:
return ""
}
}
func (c PlatformConnectorAuthSpec) ExtractUserName() string {
if c.AuthType == UserNamePasswordPlatformConnectorAuthType &&
c.UserNameRef == "" {
return c.UserName
}
return ""
}
func (c PlatformConnectorAuthSpec) ExtractUserNameRef() string {
if c.AuthType == UserNamePasswordPlatformConnectorAuthType &&
c.UserName == "" {
return c.UserNameRef
}
return ""
}
func (c PlatformConnectorAuthSpec) ExtractPasswordRef() string {
if c.AuthType == UserNamePasswordPlatformConnectorAuthType {
return c.PasswordRef
}
return ""
}
func (c PlatformConnectorAuthSpec) ExtractPassword() string {
if c.AuthType == UserNamePasswordPlatformConnectorAuthType {
return c.Password
}
return ""
}