Path: blob/main/install/installer/pkg/config/v1/config.go
2501 views
// Copyright (c) 2021 Gitpod GmbH. All rights reserved.1// Licensed under the GNU Affero General Public License (AGPL).2// See License.AGPL.txt in the project root for license information.34package config56import (7"time"89agentSmith "github.com/gitpod-io/gitpod/agent-smith/pkg/config"10"github.com/gitpod-io/gitpod/common-go/util"11"github.com/gitpod-io/gitpod/installer/pkg/config"12"github.com/gitpod-io/gitpod/installer/pkg/config/v1/experimental"13"github.com/gitpod-io/gitpod/installer/pkg/containerd"14"github.com/gitpod-io/gitpod/ws-daemon/pkg/cpulimit"1516corev1 "k8s.io/api/core/v1"17"k8s.io/apimachinery/pkg/api/resource"18metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"19"k8s.io/utils/pointer"20)2122func init() {23config.AddVersion("v1", version{})24}2526type version struct{}2728func (v version) Factory() interface{} {29return &Config{30AuthProviders: []ObjectRef{},31BlockNewUsers: BlockNewUsers{32Enabled: false,33Passlist: []string{},34},35}36}3738var (39defaultRepositoryUrl = config.GitpodContainerRegistry40)4142const (43defaultOpenVSXURL = "https://open-vsx.org"44defaultMetadataRegion = "local"45)4647func (v version) Defaults(in interface{}) error {48cfg, ok := in.(*Config)49if !ok {50return config.ErrInvalidType51}5253cfg.Kind = InstallationFull54cfg.Repository = defaultRepositoryUrl55cfg.Observability = Observability{56LogLevel: LogLevelInfo,57}58cfg.Certificate.Kind = ObjectRefSecret59cfg.Certificate.Name = "https-certificates"60cfg.Database.InCluster = pointer.Bool(true)61cfg.Metadata.Region = defaultMetadataRegion62cfg.Metadata.InstallationShortname = InstallationShortNameOldDefault // TODO(gpl): we're tied to "default" here because that's what we put into static bridges in the past63cfg.ObjectStorage.InCluster = pointer.Bool(true)64cfg.ObjectStorage.Resources = &Resources{65Requests: corev1.ResourceList{66corev1.ResourceMemory: resource.MustParse("2Gi"),67},68}69cfg.ContainerRegistry.InCluster = pointer.Bool(true)70cfg.ContainerRegistry.PrivateBaseImageAllowList = []string{}71cfg.Workspace.Resources.Requests = corev1.ResourceList{72corev1.ResourceCPU: resource.MustParse("1000m"),73corev1.ResourceMemory: resource.MustParse("2Gi"),74}75cfg.Workspace.Runtime.FSShiftMethod = FSShiftShiftFS76cfg.Workspace.Runtime.ContainerDSocketDir = containerd.ContainerdSocketLocationDefault.String()77cfg.Workspace.Runtime.ContainerDRuntimeDir = containerd.ContainerdLocationDefault.String()78cfg.Workspace.MaxLifetime = util.Duration(36 * time.Hour)79cfg.OpenVSX.URL = defaultOpenVSXURL80cfg.DisableDefinitelyGP = true8182return nil83}8485// Looks for deprecated parameters86func (v version) CheckDeprecated(rawCfg interface{}) (map[string]interface{}, []string) {87warnings := make(map[string]interface{}, 0) // A warning is for when a deprecated field is used88conflicts := make([]string, 0)89cfg := rawCfg.(*Config) // A conflict is for when both the deprecated and current field is used9091for key, field := range deprecatedFields {92// Check if the deprecated field is in use93inUse, val := parseDeprecatedSelector(cfg, field)9495if inUse {96// Deprecated field in use - print the value to the warnings97warnings[key] = val9899if field.MapValue != nil {100// There's a MapValue field101if err := field.MapValue(cfg); err != nil {102// There's a conflict on the mapped value - set in both old and new places103conflicts = append(conflicts, err.Error())104}105}106}107}108109return warnings, conflicts110}111112// Config defines the v1 version structure of the gitpod config file113type Config struct {114// Installation type to run - for most users, this will be Full115Kind InstallationKind `json:"kind" validate:"required,installation_kind"`116// The domain to deploy to117Domain string `json:"domain" validate:"required,fqdn"`118Metadata Metadata `json:"metadata"`119Repository string `json:"repository" validate:"required,ascii"`120121Observability Observability `json:"observability"`122Analytics *Analytics `json:"analytics,omitempty"`123124Database Database `json:"database" validate:"required"`125126ObjectStorage ObjectStorage `json:"objectStorage" validate:"required"`127128ContainerRegistry ContainerRegistry `json:"containerRegistry" validate:"required"`129130Certificate ObjectRef `json:"certificate" validate:"required"`131132HTTPProxy *ObjectRef `json:"httpProxy,omitempty"`133134ImagePullSecrets []ObjectRef `json:"imagePullSecrets,omitempty"`135136Workspace Workspace `json:"workspace" validate:"required"`137138OpenVSX OpenVSX `json:"openVSX"`139140AuthProviders []ObjectRef `json:"authProviders" validate:"dive"`141BlockNewUsers BlockNewUsers `json:"blockNewUsers"`142143SSHGatewayHostKey *ObjectRef `json:"sshGatewayHostKey,omitempty"`144145SSHGatewayCAKey *ObjectRef `json:"sshGatewayCAKey,omitempty"`146147DisableDefinitelyGP bool `json:"disableDefinitelyGp"`148149CustomCACert *ObjectRef `json:"customCACert,omitempty"`150151DropImageRepo *bool `json:"dropImageRepo,omitempty"`152153Customization *[]Customization `json:"customization,omitempty"`154155Components *Components `json:"components,omitempty"`156157Experimental *experimental.Config `json:"experimental,omitempty"`158}159160type Metadata struct {161// Location for your objectStorage provider162Region string `json:"region" validate:"required"`163// InstallationShortname establishes the "identity" of the (application) cluster.164InstallationShortname string `json:"shortname"`165}166167const (168InstallationShortNameOldDefault string = "default"169)170171type Observability struct {172LogLevel LogLevel `json:"logLevel" validate:"required,log_level"`173Tracing *Tracing `json:"tracing,omitempty"`174}175176type Analytics struct {177SegmentKey string `json:"segmentKey"`178Writer string `json:"writer"`179SegmentEndpoint string `json:"segmentEndpoint,omitempty"`180}181182type Tracing struct {183Endpoint *string `json:"endpoint,omitempty"`184AgentHost *string `json:"agentHost,omitempty"`185// Name of the kubernetes secret to use for Jaeger authentication186// The secret should contains two definitions: JAEGER_USER and JAEGER_PASSWORD187SecretName *string `json:"secretName,omitempty"`188}189190type Database struct {191InCluster *bool `json:"inCluster,omitempty"`192External *DatabaseExternal `json:"external,omitempty"`193CloudSQL *DatabaseCloudSQL `json:"cloudSQL,omitempty"`194SSL *SSLOptions `json:"ssl,omitempty"`195}196197type DatabaseExternal struct {198Certificate ObjectRef `json:"certificate"`199}200201type DatabaseCloudSQL struct {202ServiceAccount ObjectRef `json:"serviceAccount"`203Instance string `json:"instance" validate:"required"`204}205206type SSLOptions struct {207CaCert *ObjectRef `json:"caCert,omitempty"`208}209210type ObjectStorage struct {211InCluster *bool `json:"inCluster,omitempty"`212S3 *ObjectStorageS3 `json:"s3,omitempty"`213CloudStorage *ObjectStorageCloudStorage `json:"cloudStorage,omitempty"`214// DEPRECATED215MaximumBackupCount *int `json:"maximumBackupCount,omitempty"`216BlobQuota *int64 `json:"blobQuota,omitempty"`217Resources *Resources `json:"resources,omitempty"`218}219220type ObjectStorageS3 struct {221Endpoint string `json:"endpoint" validate:"required"`222Credentials *ObjectRef `json:"credentials"`223224BucketName string `json:"bucket" validate:"required"`225226AllowInsecureConnection bool `json:"allowInsecureConnection"`227}228229type ObjectStorageCloudStorage struct {230ServiceAccount ObjectRef `json:"serviceAccount" validate:"required"`231Project string `json:"project" validate:"required"`232}233234type InstallationKind string235236const (237InstallationIDE InstallationKind = "IDE"238InstallationWebApp InstallationKind = "WebApp"239InstallationMeta InstallationKind = "Meta" // IDE plus WebApp components240InstallationWorkspace InstallationKind = "Workspace"241InstallationFull InstallationKind = "Full"242)243244type ObjectRef struct {245Kind ObjectRefKind `json:"kind" validate:"required,objectref_kind"`246Name string `json:"name" validate:"required"`247}248249type ObjectRefKind string250251const (252ObjectRefSecret ObjectRefKind = "secret"253)254255type ContainerRegistry struct {256InCluster *bool `json:"inCluster,omitempty" validate:"required"`257External *ContainerRegistryExternal `json:"external,omitempty" validate:"required_if=InCluster false"`258S3Storage *S3Storage `json:"s3storage,omitempty"`259260PrivateBaseImageAllowList []string `json:"privateBaseImageAllowList"`261EnableAdditionalECRAuth bool `json:"enableAdditionalECRAuth"`262263SubassemblyBucket string `json:"subassemblyBucket"`264}265266type ContainerRegistryExternal struct {267URL string `json:"url" validate:"required"`268Certificate *ObjectRef `json:"certificate,omitempty"`269Credentials *ObjectRef `json:"credentials,omitempty"`270}271272type S3Storage struct {273Bucket string `json:"bucket" validate:"required"`274Region string `json:"region" validate:"required"`275Endpoint string `json:"endpoint" validate:"required"`276Certificate *ObjectRef `json:"certificate,omitempty"`277}278279type ServiceAnnotations map[string]string280281type LogLevel string282283// Taken from github.com/gitpod-io/gitpod/components/gitpod-protocol/src/util/logging.ts284const (285LogLevelTrace LogLevel = "trace"286LogLevelDebug LogLevel = "debug"287LogLevelInfo LogLevel = "info"288LogLevelWarning LogLevel = "warning"289LogLevelError LogLevel = "error"290LogLevelFatal LogLevel = "fatal"291LogLevelPanic LogLevel = "panic"292)293294type Resources struct {295// todo(sje): add custom validation to corev1.ResourceList296Requests corev1.ResourceList `json:"requests" validate:"required"`297Limits corev1.ResourceList `json:"limits,omitempty"`298}299300type WorkspaceRuntime struct {301// File system302FSShiftMethod FSShiftMethod `json:"fsShiftMethod" validate:"required,fs_shift_method"`303// The location of containerd socket on the host machine304ContainerDRuntimeDir string `json:"containerdRuntimeDir" validate:"required,startswith=/"`305// The location of containerd socket on the host machine306ContainerDSocketDir string `json:"containerdSocketDir" validate:"required,startswith=/"`307}308309type WorkspaceResources struct {310Requests corev1.ResourceList `json:"requests" validate:"required"`311Limits WorkspaceLimits `json:"limits,omitempty"`312}313314type WorkspaceLimits struct {315Cpu WorkspaceCpuLimits `json:"cpu"`316Memory string `json:"memory"`317Storage string `json:"storage"`318EphemeralStorage string `json:"ephemeral-storage"`319}320321type WorkspaceCpuLimits struct {322Buckets []cpulimit.Bucket `json:"buckets"`323MinLimit string `json:"min"`324BurstLimit string `json:"burst"`325}326327type WorkspaceTemplates struct {328Default *corev1.Pod `json:"default"`329Prebuild *corev1.Pod `json:"prebuild"`330ImageBuild *corev1.Pod `json:"imagebuild"`331Regular *corev1.Pod `json:"regular"`332}333334type Workspace struct {335Runtime WorkspaceRuntime `json:"runtime" validate:"required"`336Resources Resources `json:"resources" validate:"required"`337Templates *WorkspaceTemplates `json:"templates,omitempty"`338339// MaxLifetime is the maximum time a workspace is allowed to run. After that, the workspace times out despite activity340MaxLifetime util.Duration `json:"maxLifetime" validate:"required"`341342// TimeoutDefault is the default timeout of a regular workspace343TimeoutDefault *util.Duration `json:"timeoutDefault,omitempty"`344345// TimeoutExtended is the workspace timeout that a user can extend to for one workspace346TimeoutExtended *util.Duration `json:"timeoutExtended,omitempty"`347348// 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)349TimeoutAfterClose *util.Duration `json:"timeoutAfterClose,omitempty"`350351WorkspaceImage string `json:"workspaceImage,omitempty"`352}353354type OpenVSX struct {355URL string `json:"url" validate:"url"`356Proxy *OpenVSXProxy `json:"proxy,omitempty"`357}358359type OpenVSXProxy struct {360DisablePVC bool `json:"disablePVC"`361Proxy `json:",inline"`362}363364type Proxy struct {365ServiceAnnotations ServiceAnnotations `json:"serviceAnnotations"`366}367368type FSShiftMethod string369370const (371FSShiftShiftFS FSShiftMethod = "shiftfs"372)373374type BlockNewUsers struct {375Enabled bool `json:"enabled"`376// Passlist []string `json:"passlist" validate:"min=1,unique,dive,fqdn"`377Passlist []string `json:"passlist" validate:"block_new_users_passlist"`378}379380// AuthProviderConfigs this only contains what is necessary for validation381type AuthProviderConfigs struct {382ID string `json:"id" validate:"required"`383Host string `json:"host" validate:"required"`384Type string `json:"type" validate:"required"`385OAuth OAuth `json:"oauth" validate:"required"`386}387388// OAuth this only contains what is necessary for validation389type OAuth struct {390ClientId string `json:"clientId" validate:"required"`391ClientSecret string `json:"clientSecret" validate:"required"`392CallBackUrl string `json:"callBackUrl" validate:"required"`393}394395// Customization is a stripped-down version of the Kubernetes YAML396type Customization struct {397metav1.TypeMeta `json:",inline"`398Metadata metav1.ObjectMeta `json:"metadata"`399Spec CustomizationSpec `json:"spec,omitempty"`400}401402type CustomizationSpec struct {403Env []corev1.EnvVar `json:"env"`404}405406type Components struct {407AgentSmith *agentSmith.Config `json:"agentSmith,omitempty"`408IDE *IDEComponents `json:"ide"`409PodConfig map[string]*PodConfig `json:"podConfig,omitempty"`410Proxy *ProxyComponent `json:"proxy,omitempty"`411}412413type IDEComponents struct {414Metrics *IDEMetrics `json:"metrics,omitempty"`415Proxy *Proxy `json:"proxy,omitempty"`416ResolveLatest *bool `json:"resolveLatest,omitempty"`417}418419type IDEMetrics struct {420ErrorReportingEnabled bool `json:"errorReportingEnabled,omitempty"`421}422423type PodConfig struct {424Replicas *int32 `json:"replicas,omitempty"`425Resources map[string]*corev1.ResourceRequirements `json:"resources,omitempty"`426}427428type ProxyComponent struct {429Service *ComponentTypeService `json:"service,omitempty"`430}431432type ComponentTypeService struct {433ServiceType *corev1.ServiceType `json:"serviceType,omitempty" validate:"omitempty,service_config_type"`434}435436437