mirror of
https://github.com/gitpod-io/gitpod.git
synced 2025-12-08 17:36:30 +00:00
479 lines
16 KiB
Go
479 lines
16 KiB
Go
// Copyright (c) 2021 Gitpod GmbH. All rights reserved.
|
|
// Licensed under the GNU Affero General Public License (AGPL).
|
|
// See License.AGPL.txt in the project root for license information.
|
|
|
|
package config
|
|
|
|
import (
|
|
"time"
|
|
|
|
agentSmith "github.com/gitpod-io/gitpod/agent-smith/pkg/config"
|
|
"github.com/gitpod-io/gitpod/common-go/util"
|
|
"github.com/gitpod-io/gitpod/installer/pkg/config"
|
|
"github.com/gitpod-io/gitpod/installer/pkg/config/v1/experimental"
|
|
"github.com/gitpod-io/gitpod/installer/pkg/containerd"
|
|
"github.com/gitpod-io/gitpod/ws-daemon/pkg/cpulimit"
|
|
|
|
corev1 "k8s.io/api/core/v1"
|
|
"k8s.io/apimachinery/pkg/api/resource"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
"k8s.io/utils/pointer"
|
|
)
|
|
|
|
func init() {
|
|
config.AddVersion("v1", version{})
|
|
}
|
|
|
|
type version struct{}
|
|
|
|
func (v version) Factory() interface{} {
|
|
return &Config{
|
|
AuthProviders: []ObjectRef{},
|
|
BlockNewUsers: BlockNewUsers{
|
|
Enabled: false,
|
|
Passlist: []string{},
|
|
},
|
|
}
|
|
}
|
|
|
|
const (
|
|
defaultRepositoryUrl = "eu.gcr.io/gitpod-core-dev/build"
|
|
defaultOpenVSXURL = "https://open-vsx.org"
|
|
defaultMetadataRegion = "local"
|
|
)
|
|
|
|
func (v version) Defaults(in interface{}) error {
|
|
cfg, ok := in.(*Config)
|
|
if !ok {
|
|
return config.ErrInvalidType
|
|
}
|
|
|
|
cfg.Kind = InstallationFull
|
|
cfg.Repository = defaultRepositoryUrl
|
|
cfg.Observability = Observability{
|
|
LogLevel: LogLevelInfo,
|
|
}
|
|
cfg.Certificate.Kind = ObjectRefSecret
|
|
cfg.Certificate.Name = "https-certificates"
|
|
cfg.Database.InCluster = pointer.Bool(true)
|
|
cfg.Metadata.Region = defaultMetadataRegion
|
|
cfg.Metadata.InstallationShortname = InstallationShortNameOldDefault // TODO(gpl): we're tied to "default" here because that's what we put into static bridges in the past
|
|
cfg.ObjectStorage.InCluster = pointer.Bool(true)
|
|
cfg.ObjectStorage.Resources = &Resources{
|
|
Requests: corev1.ResourceList{
|
|
corev1.ResourceMemory: resource.MustParse("2Gi"),
|
|
},
|
|
}
|
|
cfg.ContainerRegistry.InCluster = pointer.Bool(true)
|
|
cfg.ContainerRegistry.PrivateBaseImageAllowList = []string{}
|
|
cfg.Workspace.Resources.Requests = corev1.ResourceList{
|
|
corev1.ResourceCPU: resource.MustParse("1000m"),
|
|
corev1.ResourceMemory: resource.MustParse("2Gi"),
|
|
}
|
|
cfg.Workspace.Runtime.FSShiftMethod = FSShiftFuseFS
|
|
cfg.Workspace.Runtime.ContainerDSocket = containerd.ContainerdSocketLocationDefault.String()
|
|
cfg.Workspace.Runtime.ContainerDRuntimeDir = containerd.ContainerdLocationDefault.String()
|
|
cfg.Workspace.MaxLifetime = util.Duration(36 * time.Hour)
|
|
cfg.Workspace.PrebuildPVC.Size = resource.MustParse("30Gi")
|
|
cfg.Workspace.PrebuildPVC.StorageClass = ""
|
|
cfg.Workspace.PrebuildPVC.SnapshotClass = ""
|
|
cfg.Workspace.PVC.Size = resource.MustParse("30Gi")
|
|
cfg.Workspace.PVC.StorageClass = ""
|
|
cfg.Workspace.PVC.SnapshotClass = ""
|
|
cfg.OpenVSX.URL = defaultOpenVSXURL
|
|
cfg.DisableDefinitelyGP = true
|
|
|
|
return nil
|
|
}
|
|
|
|
// Looks for deprecated parameters
|
|
func (v version) CheckDeprecated(rawCfg interface{}) (map[string]interface{}, []string) {
|
|
warnings := make(map[string]interface{}, 0) // A warning is for when a deprecated field is used
|
|
conflicts := make([]string, 0)
|
|
cfg := rawCfg.(*Config) // A conflict is for when both the deprecated and current field is used
|
|
|
|
for key, field := range deprecatedFields {
|
|
// Check if the deprecated field is in use
|
|
inUse, val := parseDeprecatedSelector(cfg, field)
|
|
|
|
if inUse {
|
|
// Deprecated field in use - print the value to the warnings
|
|
warnings[key] = val
|
|
|
|
if field.MapValue != nil {
|
|
// There's a MapValue field
|
|
if err := field.MapValue(cfg); err != nil {
|
|
// There's a conflict on the mapped value - set in both old and new places
|
|
conflicts = append(conflicts, err.Error())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return warnings, conflicts
|
|
}
|
|
|
|
// Config defines the v1 version structure of the gitpod config file
|
|
type Config struct {
|
|
// Installation type to run - for most users, this will be Full
|
|
Kind InstallationKind `json:"kind" validate:"required,installation_kind"`
|
|
// The domain to deploy to
|
|
Domain string `json:"domain" validate:"required,fqdn"`
|
|
Metadata Metadata `json:"metadata"`
|
|
Repository string `json:"repository" validate:"required,ascii"`
|
|
|
|
Observability Observability `json:"observability"`
|
|
Analytics *Analytics `json:"analytics,omitempty"`
|
|
|
|
Database Database `json:"database" validate:"required"`
|
|
|
|
MessageBus *MessageBus `json:"messageBus,omitempty"`
|
|
|
|
ObjectStorage ObjectStorage `json:"objectStorage" validate:"required"`
|
|
|
|
ContainerRegistry ContainerRegistry `json:"containerRegistry" validate:"required"`
|
|
|
|
Certificate ObjectRef `json:"certificate" validate:"required"`
|
|
|
|
HTTPProxy *ObjectRef `json:"httpProxy,omitempty"`
|
|
|
|
ImagePullSecrets []ObjectRef `json:"imagePullSecrets,omitempty"`
|
|
|
|
Workspace Workspace `json:"workspace" validate:"required"`
|
|
|
|
OpenVSX OpenVSX `json:"openVSX"`
|
|
|
|
AuthProviders []ObjectRef `json:"authProviders" validate:"dive"`
|
|
BlockNewUsers BlockNewUsers `json:"blockNewUsers"`
|
|
License *ObjectRef `json:"license,omitempty"`
|
|
|
|
SSHGatewayHostKey *ObjectRef `json:"sshGatewayHostKey,omitempty"`
|
|
|
|
DisableDefinitelyGP bool `json:"disableDefinitelyGp"`
|
|
|
|
CustomCACert *ObjectRef `json:"customCACert,omitempty"`
|
|
|
|
DropImageRepo *bool `json:"dropImageRepo,omitempty"`
|
|
|
|
Customization *[]Customization `json:"customization,omitempty"`
|
|
|
|
Components *Components `json:"components,omitempty"`
|
|
|
|
Telemetry *TelemetryConfig `json:"telemetry,omitempty"`
|
|
|
|
AdminLoginSecret *ObjectRef `json:"adminLoginSecret,omitempty"`
|
|
|
|
Experimental *experimental.Config `json:"experimental,omitempty"`
|
|
}
|
|
|
|
type Metadata struct {
|
|
// Location for your objectStorage provider
|
|
Region string `json:"region" validate:"required"`
|
|
// InstallationShortname establishes the "identity" of the (application) cluster.
|
|
InstallationShortname string `json:"shortname"`
|
|
}
|
|
|
|
const (
|
|
InstallationShortNameOldDefault string = "default"
|
|
)
|
|
|
|
type Observability struct {
|
|
LogLevel LogLevel `json:"logLevel" validate:"required,log_level"`
|
|
Tracing *Tracing `json:"tracing,omitempty"`
|
|
}
|
|
|
|
type Analytics struct {
|
|
SegmentKey string `json:"segmentKey"`
|
|
Writer string `json:"writer"`
|
|
}
|
|
|
|
type Tracing struct {
|
|
Endpoint *string `json:"endpoint,omitempty"`
|
|
AgentHost *string `json:"agentHost,omitempty"`
|
|
// Name of the kubernetes secret to use for Jaeger authentication
|
|
// The secret should contains two definitions: JAEGER_USER and JAEGER_PASSWORD
|
|
SecretName *string `json:"secretName,omitempty"`
|
|
}
|
|
|
|
type MessageBus struct {
|
|
Credentials *ObjectRef `json:"credentials"`
|
|
}
|
|
|
|
type Database struct {
|
|
InCluster *bool `json:"inCluster,omitempty"`
|
|
External *DatabaseExternal `json:"external,omitempty"`
|
|
CloudSQL *DatabaseCloudSQL `json:"cloudSQL,omitempty"`
|
|
SSL *SSLOptions `json:"ssl,omitempty"`
|
|
|
|
// Experimental. CloudSQLGlobal is configuration for a single CloudSQL DB across multiple regions.
|
|
CloudSQLGlobal *DatabaseCloudSQL `json:"cloudSQLGlobal,omitempty"`
|
|
}
|
|
|
|
type DatabaseExternal struct {
|
|
Certificate ObjectRef `json:"certificate"`
|
|
}
|
|
|
|
type DatabaseCloudSQL struct {
|
|
ServiceAccount ObjectRef `json:"serviceAccount"`
|
|
Instance string `json:"instance" validate:"required"`
|
|
}
|
|
|
|
type SSLOptions struct {
|
|
CaCert *ObjectRef `json:"caCert,omitempty"`
|
|
}
|
|
|
|
type ObjectStorage struct {
|
|
InCluster *bool `json:"inCluster,omitempty"`
|
|
S3 *ObjectStorageS3 `json:"s3,omitempty"`
|
|
CloudStorage *ObjectStorageCloudStorage `json:"cloudStorage,omitempty"`
|
|
// DEPRECATED
|
|
MaximumBackupCount *int `json:"maximumBackupCount,omitempty"`
|
|
BlobQuota *int64 `json:"blobQuota,omitempty"`
|
|
Resources *Resources `json:"resources,omitempty"`
|
|
}
|
|
|
|
type ObjectStorageS3 struct {
|
|
Endpoint string `json:"endpoint" validate:"required"`
|
|
Credentials *ObjectRef `json:"credentials"`
|
|
|
|
BucketName string `json:"bucket" validate:"required"`
|
|
|
|
AllowInsecureConnection bool `json:"allowInsecureConnection"`
|
|
}
|
|
|
|
type ObjectStorageCloudStorage struct {
|
|
ServiceAccount ObjectRef `json:"serviceAccount" validate:"required"`
|
|
Project string `json:"project" validate:"required"`
|
|
}
|
|
|
|
type InstallationKind string
|
|
|
|
const (
|
|
InstallationIDE InstallationKind = "IDE"
|
|
InstallationWebApp InstallationKind = "WebApp"
|
|
InstallationMeta InstallationKind = "Meta" // IDE plus WebApp components
|
|
InstallationWorkspace InstallationKind = "Workspace"
|
|
InstallationFull InstallationKind = "Full"
|
|
)
|
|
|
|
type ObjectRef struct {
|
|
Kind ObjectRefKind `json:"kind" validate:"required,objectref_kind"`
|
|
Name string `json:"name" validate:"required"`
|
|
}
|
|
|
|
type ObjectRefKind string
|
|
|
|
const (
|
|
ObjectRefSecret ObjectRefKind = "secret"
|
|
)
|
|
|
|
type ContainerRegistry struct {
|
|
InCluster *bool `json:"inCluster,omitempty" validate:"required"`
|
|
External *ContainerRegistryExternal `json:"external,omitempty" validate:"required_if=InCluster false"`
|
|
S3Storage *S3Storage `json:"s3storage,omitempty"`
|
|
PrivateBaseImageAllowList []string `json:"privateBaseImageAllowList"`
|
|
}
|
|
|
|
type ContainerRegistryExternal struct {
|
|
URL string `json:"url" validate:"required"`
|
|
Certificate *ObjectRef `json:"certificate,omitempty"`
|
|
Credentials *ObjectRef `json:"credentials,omitempty"`
|
|
}
|
|
|
|
type S3Storage struct {
|
|
Bucket string `json:"bucket" validate:"required"`
|
|
Region string `json:"region" validate:"required"`
|
|
Endpoint string `json:"endpoint" validate:"required"`
|
|
Certificate *ObjectRef `json:"certificate,omitempty"`
|
|
}
|
|
|
|
type ServiceAnnotations map[string]string
|
|
|
|
type LogLevel string
|
|
|
|
// Taken from github.com/gitpod-io/gitpod/components/gitpod-protocol/src/util/logging.ts
|
|
const (
|
|
LogLevelTrace LogLevel = "trace"
|
|
LogLevelDebug LogLevel = "debug"
|
|
LogLevelInfo LogLevel = "info"
|
|
LogLevelWarning LogLevel = "warning"
|
|
LogLevelError LogLevel = "error"
|
|
LogLevelFatal LogLevel = "fatal"
|
|
LogLevelPanic LogLevel = "panic"
|
|
)
|
|
|
|
type Resources struct {
|
|
// todo(sje): add custom validation to corev1.ResourceList
|
|
Requests corev1.ResourceList `json:"requests" validate:"required"`
|
|
Limits corev1.ResourceList `json:"limits,omitempty"`
|
|
}
|
|
|
|
type WorkspaceRuntime struct {
|
|
// File system
|
|
FSShiftMethod FSShiftMethod `json:"fsShiftMethod" validate:"required,fs_shift_method"`
|
|
// The location of containerd socket on the host machine
|
|
ContainerDRuntimeDir string `json:"containerdRuntimeDir" validate:"required,startswith=/"`
|
|
// The location of containerd socket on the host machine
|
|
ContainerDSocket string `json:"containerdSocket" validate:"required,startswith=/"`
|
|
}
|
|
|
|
type WorkspaceResources struct {
|
|
Requests corev1.ResourceList `json:"requests" validate:"required"`
|
|
Limits WorkspaceLimits `json:"limits,omitempty"`
|
|
}
|
|
|
|
type WorkspaceLimits struct {
|
|
Cpu WorkspaceCpuLimits `json:"cpu"`
|
|
Memory string `json:"memory"`
|
|
Storage string `json:"storage"`
|
|
EphemeralStorage string `json:"ephemeral-storage"`
|
|
}
|
|
|
|
type WorkspaceCpuLimits struct {
|
|
Buckets []cpulimit.Bucket `json:"buckets"`
|
|
MinLimit string `json:"min"`
|
|
BurstLimit string `json:"burst"`
|
|
}
|
|
|
|
type WorkspaceTemplates struct {
|
|
Default *corev1.Pod `json:"default"`
|
|
Prebuild *corev1.Pod `json:"prebuild"`
|
|
ImageBuild *corev1.Pod `json:"imagebuild"`
|
|
Regular *corev1.Pod `json:"regular"`
|
|
}
|
|
|
|
type PersistentVolumeClaim struct {
|
|
// Size is a size of persistent volume claim to use
|
|
Size resource.Quantity `json:"size" validate:"required"`
|
|
|
|
// StorageClass is a storage class of persistent volume claim to use
|
|
StorageClass string `json:"storageClass"`
|
|
|
|
// SnapshotClass is a snapshot class name that is used to create volume snapshot
|
|
SnapshotClass string `json:"snapshotClass"`
|
|
}
|
|
|
|
type Workspace struct {
|
|
Runtime WorkspaceRuntime `json:"runtime" validate:"required"`
|
|
Resources Resources `json:"resources" validate:"required"`
|
|
Templates *WorkspaceTemplates `json:"templates,omitempty"`
|
|
|
|
// PrebuildPVC is the struct that describes how to setup persistent volume claim for prebuild workspace
|
|
PrebuildPVC PersistentVolumeClaim `json:"prebuildPVC" validate:"required"`
|
|
|
|
// PVC is the struct that describes how to setup persistent volume claim for regular workspace
|
|
PVC PersistentVolumeClaim `json:"pvc" validate:"required"`
|
|
|
|
// MaxLifetime is the maximum time a workspace is allowed to run. After that, the workspace times out despite activity
|
|
MaxLifetime util.Duration `json:"maxLifetime" validate:"required"`
|
|
|
|
// TimeoutDefault is the default timeout of a regular workspace
|
|
TimeoutDefault *util.Duration `json:"timeoutDefault,omitempty"`
|
|
|
|
// TimeoutExtended is the workspace timeout that a user can extend to for one workspace
|
|
TimeoutExtended *util.Duration `json:"timeoutExtended,omitempty"`
|
|
|
|
// TimeoutAfterClose is the time a workspace timed out after it has been closed (“closed” means that it does not get a heartbeat from an IDE anymore)
|
|
TimeoutAfterClose *util.Duration `json:"timeoutAfterClose,omitempty"`
|
|
|
|
WorkspaceImage string `json:"workspaceImage,omitempty"`
|
|
}
|
|
|
|
type OpenVSX struct {
|
|
URL string `json:"url" validate:"url"`
|
|
Proxy *OpenVSXProxy `json:"proxy,omitempty"`
|
|
}
|
|
|
|
type OpenVSXProxy struct {
|
|
DisablePVC bool `json:"disablePVC"`
|
|
Proxy `json:",inline"`
|
|
}
|
|
|
|
type Proxy struct {
|
|
ServiceAnnotations ServiceAnnotations `json:"serviceAnnotations"`
|
|
}
|
|
|
|
type LicensorType string
|
|
|
|
const (
|
|
LicensorTypeGitpod LicensorType = "gitpod"
|
|
LicensorTypeReplicated LicensorType = "replicated"
|
|
)
|
|
|
|
type FSShiftMethod string
|
|
|
|
const (
|
|
FSShiftFuseFS FSShiftMethod = "fuse"
|
|
FSShiftShiftFS FSShiftMethod = "shiftfs"
|
|
)
|
|
|
|
type BlockNewUsers struct {
|
|
Enabled bool `json:"enabled"`
|
|
// Passlist []string `json:"passlist" validate:"min=1,unique,dive,fqdn"`
|
|
Passlist []string `json:"passlist" validate:"block_new_users_passlist"`
|
|
}
|
|
|
|
// AuthProviderConfigs this only contains what is necessary for validation
|
|
type AuthProviderConfigs struct {
|
|
ID string `json:"id" validate:"required"`
|
|
Host string `json:"host" validate:"required"`
|
|
Type string `json:"type" validate:"required"`
|
|
OAuth OAuth `json:"oauth" validate:"required"`
|
|
}
|
|
|
|
// OAuth this only contains what is necessary for validation
|
|
type OAuth struct {
|
|
ClientId string `json:"clientId" validate:"required"`
|
|
ClientSecret string `json:"clientSecret" validate:"required"`
|
|
CallBackUrl string `json:"callBackUrl" validate:"required"`
|
|
}
|
|
|
|
// Customization is a stripped-down version of the Kubernetes YAML
|
|
type Customization struct {
|
|
metav1.TypeMeta `json:",inline"`
|
|
Metadata metav1.ObjectMeta `json:"metadata"`
|
|
Spec CustomizationSpec `json:"spec,omitempty"`
|
|
}
|
|
|
|
type CustomizationSpec struct {
|
|
Env []corev1.EnvVar `json:"env"`
|
|
}
|
|
|
|
type Components struct {
|
|
AgentSmith *agentSmith.Config `json:"agentSmith,omitempty"`
|
|
IDE *IDEComponents `json:"ide"`
|
|
PodConfig map[string]*PodConfig `json:"podConfig,omitempty"`
|
|
Proxy *ProxyComponent `json:"proxy,omitempty"`
|
|
}
|
|
|
|
type IDEComponents struct {
|
|
Metrics *IDEMetrics `json:"metrics,omitempty"`
|
|
Proxy *Proxy `json:"proxy,omitempty"`
|
|
ResolveLatest *bool `json:"resolveLatest,omitempty"`
|
|
}
|
|
|
|
type IDEMetrics struct {
|
|
ErrorReportingEnabled bool `json:"errorReportingEnabled,omitempty"`
|
|
}
|
|
|
|
type PodConfig struct {
|
|
Replicas *int32 `json:"replicas,omitempty"`
|
|
Resources map[string]*corev1.ResourceRequirements `json:"resources,omitempty"`
|
|
}
|
|
|
|
type ProxyComponent struct {
|
|
Service *ComponentTypeService `json:"service,omitempty"`
|
|
}
|
|
|
|
type ComponentTypeService struct {
|
|
ServiceType *corev1.ServiceType `json:"serviceType,omitempty" validate:"omitempty,service_config_type"`
|
|
}
|
|
|
|
type TelemetryConfig struct {
|
|
Data *TelemetryData `json:"data,omitempty"`
|
|
}
|
|
|
|
type TelemetryData struct {
|
|
Platform string `json:"platform"`
|
|
}
|