Skip to content

Commit

Permalink
feat: [CDE-94]: Adding orchestration to start, stop and delete Gitspa…
Browse files Browse the repository at this point in the history
…ces. (harness#2159)

* Addressing review comments.
* feat: [CDE-94]: Rebasing PR. Adding StartResponse to store container orchestration start response. Refactoring provisioner to clean the method params.
* feat: [CDE-94]: Using ports returned by the container orchestrator
* feat: [CDE-94]: Adding orchestrtion to start, stop and delete Gitspaces.
  • Loading branch information
dhruv-harness authored and Harness committed Jul 8, 2024
1 parent b10fa3e commit 34df7cf
Show file tree
Hide file tree
Showing 10 changed files with 372 additions and 60 deletions.
21 changes: 7 additions & 14 deletions app/gitspace/infrastructure/provisioner.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,35 +28,28 @@ type InfraProvisioner interface {
// stores the details in the db depending on the provisioning type.
Provision(
ctx context.Context,
spaceID int64,
infraProviderResource *types.InfraProviderResource,
gitspaceConfigIdentifier string,
gitspaceInstanceID int64,
gitspaceInstanceIdentifier string,
gitspaceConfig *types.GitspaceConfig,
) (*infraprovider.Infrastructure, error)

// Stop unprovisions those resources which can be stopped without losing the gitspace data.
Stop(
ctx context.Context,
spaceID int64,
infraProviderResource *types.InfraProviderResource,
gitspaceConfigIdentifier string,
gitspaceInstanceID int64,
gitspaceInstanceIdentifier string,
gitspaceConfig *types.GitspaceConfig,
) (*infraprovider.Infrastructure, error)

// Unprovision unprovisions all the resources created for the gitspace.
Unprovision(
ctx context.Context,
spaceID int64,
infraProviderResource *types.InfraProviderResource,
gitspaceConfigIdentifier string,
gitspaceInstanceID int64,
gitspaceInstanceIdentifier string,
gitspaceConfig *types.GitspaceConfig,
) (*infraprovider.Infrastructure, error)

// Find finds the provisioned infra resources for the gitspace instance.
Find(
ctx context.Context,
spaceID int64,
infraProviderResource *types.InfraProviderResource,
gitspaceInstanceID int64,
gitspaceConfig *types.GitspaceConfig,
) (*infraprovider.Infrastructure, error)
}
26 changes: 8 additions & 18 deletions app/gitspace/infrastructure/provisioner_impl.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,11 +46,8 @@ func NewInfraProvisionerService(

func (i infraProvisioner) Provision(
ctx context.Context,
_ int64,
infraProviderResource *types.InfraProviderResource,
gitspaceConfigIdentifier string,
_ int64,
_ string,
gitspaceConfig *types.GitspaceConfig,
) (*infraprovider.Infrastructure, error) {
infraProviderEntity, err := i.getConfigFromResource(ctx, infraProviderResource)
if err != nil {
Expand Down Expand Up @@ -83,11 +80,11 @@ func (i infraProvisioner) Provision(
return nil, fmt.Errorf("invalid provisioning params %v: %w", infraProviderResource.Metadata, err)
}

provisionedInfra, err := infraProvider.Provision(ctx, gitspaceConfigIdentifier, allParams)
provisionedInfra, err := infraProvider.Provision(ctx, gitspaceConfig.Identifier, allParams)
if err != nil {
return nil, fmt.Errorf(
"unable to provision infrastructure for gitspaceConfigIdentifier %v: %w",
gitspaceConfigIdentifier,
gitspaceConfig.Identifier,
err,
)
}
Expand All @@ -101,11 +98,8 @@ func (i infraProvisioner) Provision(

func (i infraProvisioner) Stop(
ctx context.Context,
_ int64,
infraProviderResource *types.InfraProviderResource,
gitspaceConfigIdentifier string,
_ int64,
_ string,
gitspaceConfig *types.GitspaceConfig,
) (*infraprovider.Infrastructure, error) {
infraProviderEntity, err := i.getConfigFromResource(ctx, infraProviderResource)
if err != nil {
Expand Down Expand Up @@ -144,7 +138,7 @@ func (i infraProvisioner) Stop(
// TODO: Fetch and check existing infraProvisioned record
} else {
provisionedInfra = infraprovider.Infrastructure{
ResourceKey: gitspaceConfigIdentifier,
ResourceKey: gitspaceConfig.Identifier,
ProviderType: infraProviderEntity.Type,
Parameters: allParams,
}
Expand All @@ -164,11 +158,8 @@ func (i infraProvisioner) Stop(

func (i infraProvisioner) Unprovision(
ctx context.Context,
_ int64,
infraProviderResource *types.InfraProviderResource,
gitspaceConfigIdentifier string,
_ int64,
_ string,
gitspaceConfig *types.GitspaceConfig,
) (*infraprovider.Infrastructure, error) {
infraProviderEntity, err := i.getConfigFromResource(ctx, infraProviderResource)
if err != nil {
Expand Down Expand Up @@ -207,7 +198,7 @@ func (i infraProvisioner) Unprovision(
// TODO: Fetch and check existing infraProvisioned record
} else {
provisionedInfra = infraprovider.Infrastructure{
ResourceKey: gitspaceConfigIdentifier,
ResourceKey: gitspaceConfig.Identifier,
ProviderType: infraProviderEntity.Type,
Parameters: allParams,
}
Expand All @@ -227,9 +218,8 @@ func (i infraProvisioner) Unprovision(

func (i infraProvisioner) Find(
ctx context.Context,
_ int64,
infraProviderResource *types.InfraProviderResource,
_ int64,
_ *types.GitspaceConfig,
) (*infraprovider.Infrastructure, error) {
infraProviderEntity, err := i.getConfigFromResource(ctx, infraProviderResource)
if err != nil {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (

"github.com/harness/gitness/infraprovider"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum"
)

type Orchestrator interface {
Expand All @@ -30,7 +29,7 @@ type Orchestrator interface {
gitspaceConfig *types.GitspaceConfig,
devcontainerConfig *types.DevcontainerConfig,
infra *infraprovider.Infrastructure,
) (map[enum.IDEType]string, error)
) (*StartResponse, error)

// StopGitspace stops and removes the gitspace container.
StopGitspace(ctx context.Context, gitspaceConfig *types.GitspaceConfig, infra *infraprovider.Infrastructure) error
Expand Down
26 changes: 17 additions & 9 deletions app/gitspace/orchestrator/container/embedded_docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ func (e *EmbeddedDockerOrchestrator) StartGitspace(
gitspaceConfig *types.GitspaceConfig,
devcontainerConfig *types.DevcontainerConfig,
infra *infraprovider.Infrastructure,
) (map[enum.IDEType]string, error) {
) (*StartResponse, error) {
containerName := getGitspaceContainerName(gitspaceConfig)

log := log.Ctx(ctx).With().Str(loggingKey, containerName).Logger()
Expand All @@ -108,7 +108,7 @@ func (e *EmbeddedDockerOrchestrator) StartGitspace(
}

var usedPorts map[enum.IDEType]string

var containerID string
switch state {
case containerStateRunning:
log.Debug().Msg("gitspace is already running")
Expand All @@ -118,11 +118,13 @@ func (e *EmbeddedDockerOrchestrator) StartGitspace(
return nil, startErr
}

ports, startErr := e.getUsedPorts(ctx, containerName, dockerClient, ideService)
id, ports, startErr := e.getContainerInfo(ctx, containerName, dockerClient, ideService)
if startErr != nil {
return nil, startErr
}

usedPorts = ports
containerID = id

case containerStateRemoved:
log.Debug().Msg("gitspace is not running, starting it...")
Expand All @@ -143,10 +145,12 @@ func (e *EmbeddedDockerOrchestrator) StartGitspace(
if startErr != nil {
return nil, fmt.Errorf("failed to start gitspace %s: %w", containerName, startErr)
}
ports, startErr := e.getUsedPorts(ctx, containerName, dockerClient, ideService)
id, ports, startErr := e.getContainerInfo(ctx, containerName, dockerClient, ideService)
if startErr != nil {
return nil, startErr
}

containerID = id
usedPorts = ports

// TODO: Add gitspace status reporting.
Expand All @@ -156,7 +160,11 @@ func (e *EmbeddedDockerOrchestrator) StartGitspace(
return nil, fmt.Errorf("gitspace %s is in a bad state: %s", containerName, state)
}

return usedPorts, nil
return &StartResponse{
ContainerID: containerID,
ContainerName: containerName,
PortsUsed: usedPorts,
}, nil
}

func (e *EmbeddedDockerOrchestrator) startGitspace(
Expand Down Expand Up @@ -211,15 +219,15 @@ func (e *EmbeddedDockerOrchestrator) startGitspace(
return nil
}

func (e *EmbeddedDockerOrchestrator) getUsedPorts(
func (e *EmbeddedDockerOrchestrator) getContainerInfo(
ctx context.Context,
containerName string,
dockerClient *client.Client,
ideService IDE,
) (map[enum.IDEType]string, error) {
) (string, map[enum.IDEType]string, error) {
inspectResp, err := dockerClient.ContainerInspect(ctx, containerName)
if err != nil {
return nil, fmt.Errorf("could not inspect container %s: %w", containerName, err)
return "", nil, fmt.Errorf("could not inspect container %s: %w", containerName, err)
}

usedPorts := map[enum.IDEType]string{}
Expand All @@ -232,7 +240,7 @@ func (e *EmbeddedDockerOrchestrator) getUsedPorts(
}
}

return usedPorts, nil
return inspectResp.ID, usedPorts, nil
}

func (e *EmbeddedDockerOrchestrator) getIDEService(gitspaceConfig *types.GitspaceConfig) (IDE, error) {
Expand Down
23 changes: 23 additions & 0 deletions app/gitspace/orchestrator/container/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// 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 container

import "github.com/harness/gitness/types/enum"

type StartResponse struct {
ContainerID string
ContainerName string
PortsUsed map[enum.IDEType]string
}
45 changes: 45 additions & 0 deletions app/gitspace/orchestrator/orchestrator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// 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 orchestrator

import (
"context"

"github.com/harness/gitness/types"
)

type Orchestrator interface {
// StartGitspace is responsible for all the operations necessary to create the Gitspace container. It fetches the
// devcontainer.json from the code repo, provisions infra using the infra provisioner and setting up the Gitspace
// through the container orchestrator.
StartGitspace(
ctx context.Context,
gitspaceConfig *types.GitspaceConfig,
) (*types.GitspaceInstance, error)

// StopGitspace is responsible for stopping a running Gitspace. It stops the Gitspace container and unprovisions
// all the infra resources which are not required to restart the Gitspace.
StopGitspace(
ctx context.Context,
gitspaceConfig *types.GitspaceConfig,
) (*types.GitspaceInstance, error)

// DeleteGitspace is responsible for deleting a Gitspace. It stops the Gitspace container and unprovisions
// all the infra resources.
DeleteGitspace(
ctx context.Context,
gitspaceConfig *types.GitspaceConfig,
) (*types.GitspaceInstance, error)
}
Loading

0 comments on commit 34df7cf

Please sign in to comment.