feat: [CDE-241]: Adding protocol to the gitspace port returned by the IDE and corresponding changes. Fixing gitspace instance's reference instead of value in the orchestrator. (#2521)

* feat: [CDE-241]: Addressing review comment.
* feat: [CDE-241]: Addressing review comment.
* feat: [CDE-241]: Adding protocol to the gitspace port returned by the IDE and corresponding changes. Fixing gitspace instance's reference instead of value in the orchestrator.
pull/3545/head
Dhruv Dhruv 2024-08-16 08:31:05 +00:00 committed by Harness
parent 2f3b6a6f85
commit 0f8eb568e2
12 changed files with 103 additions and 37 deletions

View File

@ -27,7 +27,7 @@ func (i infraProvisioner) Find(
ctx context.Context, ctx context.Context,
infraProviderResource types.InfraProviderResource, infraProviderResource types.InfraProviderResource,
gitspaceConfig types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
requiredGitspacePorts []int, requiredGitspacePorts []types.GitspacePort,
) (*types.Infrastructure, error) { ) (*types.Infrastructure, error) {
infraProviderEntity, err := i.getConfigFromResource(ctx, infraProviderResource) infraProviderEntity, err := i.getConfigFromResource(ctx, infraProviderResource)
if err != nil { if err != nil {

View File

@ -31,7 +31,7 @@ func (i infraProvisioner) TriggerProvision(
ctx context.Context, ctx context.Context,
infraProviderResource types.InfraProviderResource, infraProviderResource types.InfraProviderResource,
gitspaceConfig types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
requiredPorts []int, requiredGitspacePorts []types.GitspacePort,
) error { ) error {
infraProviderEntity, err := i.getConfigFromResource(ctx, infraProviderResource) infraProviderEntity, err := i.getConfigFromResource(ctx, infraProviderResource)
if err != nil { if err != nil {
@ -45,10 +45,10 @@ func (i infraProvisioner) TriggerProvision(
if infraProvider.ProvisioningType() == enum.InfraProvisioningTypeNew { if infraProvider.ProvisioningType() == enum.InfraProvisioningTypeNew {
return i.triggerProvisionForNewProvisioning( return i.triggerProvisionForNewProvisioning(
ctx, infraProviderResource, infraProvider, infraProviderEntity.Type, gitspaceConfig, requiredPorts) ctx, infraProviderResource, infraProvider, infraProviderEntity.Type, gitspaceConfig, requiredGitspacePorts)
} }
return i.triggerProvisionForExistingProvisioning( return i.triggerProvisionForExistingProvisioning(
ctx, infraProviderResource, infraProvider, gitspaceConfig, requiredPorts) ctx, infraProviderResource, infraProvider, gitspaceConfig, requiredGitspacePorts)
} }
func (i infraProvisioner) triggerProvisionForNewProvisioning( func (i infraProvisioner) triggerProvisionForNewProvisioning(
@ -57,7 +57,7 @@ func (i infraProvisioner) triggerProvisionForNewProvisioning(
infraProvider infraprovider.InfraProvider, infraProvider infraprovider.InfraProvider,
infraProviderType enum.InfraProviderType, infraProviderType enum.InfraProviderType,
gitspaceConfig types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
requiredGitspacePorts []int, requiredGitspacePorts []types.GitspacePort,
) error { ) error {
infraProvisionedLatest, _ := i.infraProvisionedStore.FindLatestByGitspaceInstanceID( infraProvisionedLatest, _ := i.infraProvisionedStore.FindLatestByGitspaceInstanceID(
ctx, gitspaceConfig.SpaceID, gitspaceConfig.GitspaceInstance.ID) ctx, gitspaceConfig.SpaceID, gitspaceConfig.GitspaceInstance.ID)
@ -140,7 +140,7 @@ func (i infraProvisioner) triggerProvisionForExistingProvisioning(
infraProviderResource types.InfraProviderResource, infraProviderResource types.InfraProviderResource,
infraProvider infraprovider.InfraProvider, infraProvider infraprovider.InfraProvider,
gitspaceConfig types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
requiredPorts []int, requiredGitspacePorts []types.GitspacePort,
) error { ) error {
allParams, err := i.getAllParamsFromDB(ctx, infraProviderResource, infraProvider) allParams, err := i.getAllParamsFromDB(ctx, infraProviderResource, infraProvider)
if err != nil { if err != nil {
@ -159,7 +159,7 @@ func (i infraProvisioner) triggerProvisionForExistingProvisioning(
gitspaceConfig.Identifier, gitspaceConfig.Identifier,
gitspaceConfig.GitspaceInstance.Identifier, gitspaceConfig.GitspaceInstance.Identifier,
0, // NOTE: Agent port is not required for provisioning type Existing. 0, // NOTE: Agent port is not required for provisioning type Existing.
requiredPorts, requiredGitspacePorts,
allParams, allParams,
) )
if err != nil { if err != nil {

View File

@ -29,7 +29,7 @@ type InfraProvisioner interface {
ctx context.Context, ctx context.Context,
infraProviderResource types.InfraProviderResource, infraProviderResource types.InfraProviderResource,
gitspaceConfig types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
requiredGitspacePorts []int, requiredGitspacePorts []types.GitspacePort,
) error ) error
// ResumeProvision stores the provisioned infra details in the db depending on the provisioning type. // ResumeProvision stores the provisioned infra details in the db depending on the provisioning type.
@ -73,6 +73,6 @@ type InfraProvisioner interface {
ctx context.Context, ctx context.Context,
infraProviderResource types.InfraProviderResource, infraProviderResource types.InfraProviderResource,
gitspaceConfig types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
requiredGitspacePorts []int, requiredGitspacePorts []types.GitspacePort,
) (*types.Infrastructure, error) ) (*types.Infrastructure, error)
} }

View File

@ -90,7 +90,6 @@ func (e *EmbeddedDockerOrchestrator) CreateAndStartGitspace(
gitspaceConfig.GitspaceInstance.AccessKey != nil { gitspaceConfig.GitspaceInstance.AccessKey != nil {
accessKey = *gitspaceConfig.GitspaceInstance.AccessKey accessKey = *gitspaceConfig.GitspaceInstance.AccessKey
} else { } else {
log.Error().Msgf("no access key is configured: %s", gitspaceConfig.Identifier)
return nil, fmt.Errorf("no access key is configured: %s", gitspaceConfig.Identifier) return nil, fmt.Errorf("no access key is configured: %s", gitspaceConfig.Identifier)
} }

View File

@ -18,6 +18,7 @@ import (
"context" "context"
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer" "github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum" "github.com/harness/gitness/types/enum"
) )
@ -30,7 +31,7 @@ type IDE interface {
Run(ctx context.Context, exec *devcontainer.Exec) ([]byte, error) Run(ctx context.Context, exec *devcontainer.Exec) ([]byte, error)
// Port provides the port which will be used by this IDE. // Port provides the port which will be used by this IDE.
Port() int Port() *types.GitspacePort
// Type provides the IDE type to which the service belongs. // Type provides the IDE type to which the service belongs.
Type() enum.IDEType Type() enum.IDEType

View File

@ -21,6 +21,7 @@ import (
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer" "github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
"github.com/harness/gitness/app/gitspace/orchestrator/template" "github.com/harness/gitness/app/gitspace/orchestrator/template"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum" "github.com/harness/gitness/types/enum"
) )
@ -92,8 +93,11 @@ func (v *VSCode) Run(ctx context.Context, exec *devcontainer.Exec) ([]byte, erro
} }
// Port returns the port on which the ssh-server is listening. // Port returns the port on which the ssh-server is listening.
func (v *VSCode) Port() int { func (v *VSCode) Port() *types.GitspacePort {
return v.config.Port return &types.GitspacePort{
Port: v.config.Port,
Protocol: enum.CommunicationProtocolSSH,
}
} }
func (v *VSCode) Type() enum.IDEType { func (v *VSCode) Type() enum.IDEType {

View File

@ -27,6 +27,7 @@ import (
"github.com/harness/gitness/app/gitspace/orchestrator/devcontainer" "github.com/harness/gitness/app/gitspace/orchestrator/devcontainer"
"github.com/harness/gitness/app/gitspace/orchestrator/template" "github.com/harness/gitness/app/gitspace/orchestrator/template"
"github.com/harness/gitness/types"
"github.com/harness/gitness/types/enum" "github.com/harness/gitness/types/enum"
"github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/container"
@ -115,8 +116,11 @@ func (v *VSCodeWeb) Run(ctx context.Context, exec *devcontainer.Exec) ([]byte, e
} }
// PortAndProtocol returns the port on which the code-server is listening. // PortAndProtocol returns the port on which the code-server is listening.
func (v *VSCodeWeb) Port() int { func (v *VSCodeWeb) Port() *types.GitspacePort {
return v.config.Port return &types.GitspacePort{
Port: v.config.Port,
Protocol: enum.CommunicationProtocolHTTP,
}
} }
func (v *VSCodeWeb) Type() enum.IDEType { func (v *VSCodeWeb) Type() enum.IDEType {

View File

@ -290,18 +290,18 @@ func (o orchestrator) ResumeStartGitspace(
gitspaceConfig types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
provisionedInfra types.Infrastructure, provisionedInfra types.Infrastructure,
) (types.GitspaceInstance, error) { ) (types.GitspaceInstance, error) {
gitspaceInstance := *gitspaceConfig.GitspaceInstance gitspaceInstance := gitspaceConfig.GitspaceInstance
gitspaceInstance.State = enum.GitspaceInstanceStateError gitspaceInstance.State = enum.GitspaceInstanceStateError
secretResolver, err := o.getSecretResolver(gitspaceInstance.AccessType) secretResolver, err := o.getSecretResolver(gitspaceInstance.AccessType)
if err != nil { if err != nil {
log.Err(err).Msgf("could not find secret resolver for type: %s", gitspaceInstance.AccessType) log.Err(err).Msgf("could not find secret resolver for type: %s", gitspaceInstance.AccessType)
return gitspaceInstance, err return *gitspaceInstance, err
} }
rootSpaceID, _, err := paths.DisectRoot(gitspaceConfig.SpacePath) rootSpaceID, _, err := paths.DisectRoot(gitspaceConfig.SpacePath)
if err != nil { if err != nil {
log.Err(err).Msgf("unable to find root space id from space path: %s", gitspaceConfig.SpacePath) log.Err(err).Msgf("unable to find root space id from space path: %s", gitspaceConfig.SpacePath)
return gitspaceInstance, err return *gitspaceInstance, err
} }
resolvedSecret, err := secretResolver.Resolve(ctx, secret.ResolutionContext{ resolvedSecret, err := secretResolver.Resolve(ctx, secret.ResolutionContext{
UserIdentifier: gitspaceConfig.UserID, UserIdentifier: gitspaceConfig.UserID,
@ -312,13 +312,13 @@ func (o orchestrator) ResumeStartGitspace(
if err != nil { if err != nil {
log.Err(err).Msgf("could not resolve secret type: %s, ref: %s", log.Err(err).Msgf("could not resolve secret type: %s, ref: %s",
gitspaceInstance.AccessType, *gitspaceInstance.AccessKeyRef) gitspaceInstance.AccessType, *gitspaceInstance.AccessKeyRef)
return gitspaceInstance, err return *gitspaceInstance, err
} }
gitspaceInstance.AccessKey = &resolvedSecret.SecretValue gitspaceInstance.AccessKey = &resolvedSecret.SecretValue
ideSvc, err := o.getIDEService(gitspaceConfig) ideSvc, err := o.getIDEService(gitspaceConfig)
if err != nil { if err != nil {
return gitspaceInstance, err return *gitspaceInstance, err
} }
idePort := ideSvc.Port() idePort := ideSvc.Port()
@ -327,18 +327,19 @@ func (o orchestrator) ResumeStartGitspace(
if err != nil { if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraProvisioningFailed) o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraProvisioningFailed)
return gitspaceInstance, fmt.Errorf( return *gitspaceInstance, fmt.Errorf(
"cannot provision infrastructure for ID %d: %w", gitspaceConfig.InfraProviderResourceID, err) "cannot provision infrastructure for ID %d: %w", gitspaceConfig.InfraProviderResourceID, err)
} }
if provisionedInfra.Status != enum.InfraStatusProvisioned { if provisionedInfra.Status != enum.InfraStatusProvisioned {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraProvisioningFailed) o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraProvisioningFailed)
return gitspaceInstance, fmt.Errorf( return *gitspaceInstance, fmt.Errorf(
"infra state is %v, should be %v for gitspace instance identifier %s", "infra state is %v, should be %v for gitspace instance identifier %s",
provisionedInfra.Status, provisionedInfra.Status,
enum.InfraStatusProvisioned, enum.InfraStatusProvisioned,
gitspaceConfig.GitspaceInstance.Identifier) gitspaceConfig.GitspaceInstance.Identifier,
)
} }
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraProvisioningCompleted) o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeInfraProvisioningCompleted)
@ -349,7 +350,7 @@ func (o orchestrator) ResumeStartGitspace(
if err != nil { if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeFetchDevcontainerFailed) o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeFetchDevcontainerFailed)
return gitspaceInstance, fmt.Errorf( return *gitspaceInstance, fmt.Errorf(
"failed to fetch code repo details for gitspace config ID %w %d", err, gitspaceConfig.ID) "failed to fetch code repo details for gitspace config ID %w %d", err, gitspaceConfig.ID)
} }
devcontainerConfig := scmResolvedDetails.DevcontainerConfig devcontainerConfig := scmResolvedDetails.DevcontainerConfig
@ -366,7 +367,7 @@ func (o orchestrator) ResumeStartGitspace(
if err != nil { if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentConnectFailed) o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentConnectFailed)
return gitspaceInstance, fmt.Errorf("couldn't call the agent health API: %w", err) return *gitspaceInstance, fmt.Errorf("couldn't call the agent health API: %w", err)
} }
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentConnectCompleted) o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentConnectCompleted)
@ -381,7 +382,7 @@ func (o orchestrator) ResumeStartGitspace(
if err != nil { if err != nil {
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceCreationFailed) o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceCreationFailed)
return gitspaceInstance, fmt.Errorf("couldn't call the agent start API: %w", err) return *gitspaceInstance, fmt.Errorf("couldn't call the agent start API: %w", err)
} }
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceCreationCompleted) o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeAgentGitspaceCreationCompleted)
@ -390,10 +391,10 @@ func (o orchestrator) ResumeStartGitspace(
var forwardedPort string var forwardedPort string
if provisionedInfra.GitspacePortMappings[idePort].PublishedPort == 0 { if provisionedInfra.GitspacePortMappings[idePort.Port].PublishedPort == 0 {
forwardedPort = startResponse.PublishedPorts[idePort] forwardedPort = startResponse.PublishedPorts[idePort.Port]
} else { } else {
forwardedPort = strconv.Itoa(provisionedInfra.GitspacePortMappings[idePort].ForwardedPort) forwardedPort = strconv.Itoa(provisionedInfra.GitspacePortMappings[idePort.Port].ForwardedPort)
} }
scheme := provisionedInfra.GitspaceScheme scheme := provisionedInfra.GitspaceScheme
@ -431,7 +432,7 @@ func (o orchestrator) ResumeStartGitspace(
o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeGitspaceActionStartCompleted) o.emitGitspaceEvent(ctx, gitspaceConfig, enum.GitspaceEventTypeGitspaceActionStartCompleted)
return gitspaceInstance, nil return *gitspaceInstance, nil
} }
func (o orchestrator) getSecretResolver(accessType enum.GitspaceAccessType) (secret.Resolver, error) { func (o orchestrator) getSecretResolver(accessType enum.GitspaceAccessType) (secret.Resolver, error) {
@ -515,7 +516,7 @@ func (o orchestrator) ResumeDeleteGitspace(
func (o orchestrator) getPortsRequiredForGitspace( func (o orchestrator) getPortsRequiredForGitspace(
gitspaceConfig types.GitspaceConfig, gitspaceConfig types.GitspaceConfig,
) ([]int, error) { ) ([]types.GitspacePort, error) {
// TODO: What if the required ports in the config have deviated from when the last instance was created? // TODO: What if the required ports in the config have deviated from when the last instance was created?
ideSvc, err := o.getIDEService(gitspaceConfig) ideSvc, err := o.getIDEService(gitspaceConfig)
if err != nil { if err != nil {
@ -523,7 +524,7 @@ func (o orchestrator) getPortsRequiredForGitspace(
} }
idePort := ideSvc.Port() idePort := ideSvc.Port()
return []int{idePort}, nil return []types.GitspacePort{*idePort}, nil
} }
func (o orchestrator) GetGitspaceLogs(ctx context.Context, gitspaceConfig types.GitspaceConfig) (string, error) { func (o orchestrator) GetGitspaceLogs(ctx context.Context, gitspaceConfig types.GitspaceConfig) (string, error) {

View File

@ -57,7 +57,7 @@ func (d DockerProvider) Provision(
gitspaceConfigIdentifier string, gitspaceConfigIdentifier string,
_ string, _ string,
_ int, _ int,
requiredGitspacePorts []int, requiredGitspacePorts []types.GitspacePort,
inputParameters []types.InfraProviderParameter, inputParameters []types.InfraProviderParameter,
) error { ) error {
dockerClient, err := d.dockerClientFactory.NewDockerClient(ctx, types.Infrastructure{ dockerClient, err := d.dockerClientFactory.NewDockerClient(ctx, types.Infrastructure{
@ -99,7 +99,7 @@ func (d DockerProvider) Provision(
ForwardedPort: 0, ForwardedPort: 0,
} }
portMappings[requiredPort] = portMapping portMappings[requiredPort.Port] = portMapping
} }
infrastructure.GitspacePortMappings = portMappings infrastructure.GitspacePortMappings = portMappings
@ -125,7 +125,7 @@ func (d DockerProvider) Find(
gitspaceConfigIdentifier string, gitspaceConfigIdentifier string,
_ string, _ string,
_ int, _ int,
_ []int, _ []types.GitspacePort,
inputParameters []types.InfraProviderParameter, inputParameters []types.InfraProviderParameter,
) (*types.Infrastructure, error) { ) (*types.Infrastructure, error) {
dockerClient, err := d.dockerClientFactory.NewDockerClient(ctx, types.Infrastructure{ dockerClient, err := d.dockerClientFactory.NewDockerClient(ctx, types.Infrastructure{

View File

@ -30,9 +30,10 @@ type InfraProvider interface {
gitspaceConfigIdentifier string, gitspaceConfigIdentifier string,
gitspaceInstanceIdentifier string, gitspaceInstanceIdentifier string,
agentPort int, agentPort int,
requiredGitspacePorts []int, requiredGitspacePorts []types.GitspacePort,
inputParameters []types.InfraProviderParameter, inputParameters []types.InfraProviderParameter,
) error ) error
// Find finds infrastructure provisioned against a gitspace. // Find finds infrastructure provisioned against a gitspace.
Find( Find(
ctx context.Context, ctx context.Context,
@ -41,19 +42,25 @@ type InfraProvider interface {
gitspaceConfigIdentifier string, gitspaceConfigIdentifier string,
gitspaceInstanceIdentifier string, gitspaceInstanceIdentifier string,
agentPort int, agentPort int,
requiredGitspacePorts []int, requiredGitspacePorts []types.GitspacePort,
inputParameters []types.InfraProviderParameter, inputParameters []types.InfraProviderParameter,
) (*types.Infrastructure, error) ) (*types.Infrastructure, error)
// Stop frees up the resources allocated against a gitspace, which can be freed. // Stop frees up the resources allocated against a gitspace, which can be freed.
Stop(ctx context.Context, infra types.Infrastructure) error Stop(ctx context.Context, infra types.Infrastructure) error
// Deprovision removes all infrastructure provisioned against the gitspace. // Deprovision removes all infrastructure provisioned against the gitspace.
Deprovision(ctx context.Context, infra types.Infrastructure) error Deprovision(ctx context.Context, infra types.Infrastructure) error
// AvailableParams provides a schema to define the infrastructure. // AvailableParams provides a schema to define the infrastructure.
AvailableParams() []types.InfraProviderParameterSchema AvailableParams() []types.InfraProviderParameterSchema
// ValidateParams validates the supplied params before defining the infrastructure resource . // ValidateParams validates the supplied params before defining the infrastructure resource .
ValidateParams(inputParameters []types.InfraProviderParameter) error ValidateParams(inputParameters []types.InfraProviderParameter) error
// TemplateParams provides a list of params which are of type template. // TemplateParams provides a list of params which are of type template.
TemplateParams() []types.InfraProviderParameterSchema TemplateParams() []types.InfraProviderParameterSchema
// ProvisioningType specifies whether the provider will provision new infra resources or it will reuse existing. // ProvisioningType specifies whether the provider will provision new infra resources or it will reuse existing.
ProvisioningType() enum.InfraProvisioningType ProvisioningType() enum.InfraProvisioningType
} }

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 enum
type CommunicationProtocol string
func (CommunicationProtocol) Enum() []interface{} { return toInterfaceSlice(communicationProtocols) }
var communicationProtocols = []CommunicationProtocol{
CommunicationProtocolHTTP, CommunicationProtocolSSH,
}
const (
CommunicationProtocolHTTP CommunicationProtocol = "http"
CommunicationProtocolSSH CommunicationProtocol = "ssh"
)

22
types/gitspace_port.go Normal file
View File

@ -0,0 +1,22 @@
// 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 "github.com/harness/gitness/types/enum"
type GitspacePort struct {
Port int `json:"port"`
Protocol enum.CommunicationProtocol `json:"protocol"`
}