diff --git a/components/dashboard/src/admin/ProjectDetail.tsx b/components/dashboard/src/admin/ProjectDetail.tsx index bee215655b5620..9c140b3d4ab765 100644 --- a/components/dashboard/src/admin/ProjectDetail.tsx +++ b/components/dashboard/src/admin/ProjectDetail.tsx @@ -63,9 +63,6 @@ export default function ProjectDetail(props: { project: Project; owner: string | {props.project.settings?.useIncrementalPrebuilds ? "Yes" : "No"} - - {props.project.settings?.usePersistentVolumeClaim ? "Yes" : "No"} - {props.project.markedDeleted ? "Yes" : "No"} diff --git a/components/dashboard/src/service/service-mock.ts b/components/dashboard/src/service/service-mock.ts index 0c5f64a20dbd71..c2e74203344f4b 100644 --- a/components/dashboard/src/service/service-mock.ts +++ b/components/dashboard/src/service/service-mock.ts @@ -219,7 +219,7 @@ const gitpodServiceMock = createServiceMock({ displayName: "Standard", description: "Up to 4 vCPU, 8GB memory, 30GB disk", powerups: 1, - isSelected: true, + isDefault: true, }, { id: "g1-large", @@ -227,7 +227,7 @@ const gitpodServiceMock = createServiceMock({ displayName: "Large", description: "Up to 8 vCPU, 16GB memory, 50GB disk", powerups: 2, - isSelected: false, + isDefault: false, }, ]; }, diff --git a/components/dashboard/src/settings/Preferences.tsx b/components/dashboard/src/settings/Preferences.tsx index 99763cd42d7c69..ce4f0c4396f0ff 100644 --- a/components/dashboard/src/settings/Preferences.tsx +++ b/components/dashboard/src/settings/Preferences.tsx @@ -11,15 +11,12 @@ import { ThemeContext } from "../theme-context"; import { UserContext } from "../user-context"; import { trackEvent } from "../Analytics"; import SelectIDE from "./SelectIDE"; -import SelectWorkspaceClass from "./selectClass"; import { PageWithSettingsSubMenu } from "./PageWithSettingsSubMenu"; -import { BillingMode } from "@gitpod/gitpod-protocol/lib/billing-mode"; -import { WorkspaceClasses } from "@gitpod/gitpod-protocol"; type Theme = "light" | "dark" | "system"; export default function Preferences() { - const { user, userBillingMode } = useContext(UserContext); + const { user } = useContext(UserContext); const { setIsDark } = useContext(ThemeContext); const [theme, setTheme] = useState(localStorage.theme || "system"); @@ -50,30 +47,12 @@ export default function Preferences() { } }; - const setWorkspaceClass = async (value: string) => { - const additionalData = user?.additionalData || {}; - const prevWorkspaceClass = additionalData?.workspaceClasses?.regular; - const workspaceClasses = (additionalData?.workspaceClasses || {}) as WorkspaceClasses; - workspaceClasses.regular = value; - workspaceClasses.prebuild = value; - additionalData.workspaceClasses = workspaceClasses; - if (value !== prevWorkspaceClass) { - await getGitpodService().server.updateLoggedInUser({ additionalData }); - } - return prevWorkspaceClass; - }; - return (

Editor

Choose the editor for opening workspaces.

-

Theme

Early bird or night owl? Choose your side.

diff --git a/components/dashboard/src/settings/selectClass.tsx b/components/dashboard/src/settings/selectClass.tsx index 2d3b397626c5cc..7c051da5290e51 100644 --- a/components/dashboard/src/settings/selectClass.tsx +++ b/components/dashboard/src/settings/selectClass.tsx @@ -37,7 +37,7 @@ export default function SelectWorkspaceClass(props: SelectWorkspaceClassProps) { setSupportedClasses(classes); if (!workspaceClass) { - setWorkspaceClass(classes.find((c) => c.isSelected)?.id || ""); + setWorkspaceClass(classes.find((c) => c.isDefault)?.id || ""); } }; diff --git a/components/gitpod-protocol/src/teams-projects-protocol.ts b/components/gitpod-protocol/src/teams-projects-protocol.ts index 7de2881894d47c..4dabf36e1fe751 100644 --- a/components/gitpod-protocol/src/teams-projects-protocol.ts +++ b/components/gitpod-protocol/src/teams-projects-protocol.ts @@ -15,7 +15,6 @@ export interface ProjectConfig { export interface ProjectSettings { useIncrementalPrebuilds?: boolean; - usePersistentVolumeClaim?: boolean; keepOutdatedPrebuildsRunning?: boolean; // whether new workspaces can start on older prebuilds and incrementally update allowUsingPreviousPrebuilds?: boolean; diff --git a/components/gitpod-protocol/src/workspace-class.ts b/components/gitpod-protocol/src/workspace-class.ts index 4d3ce713e4f2f1..3128db9da1060b 100644 --- a/components/gitpod-protocol/src/workspace-class.ts +++ b/components/gitpod-protocol/src/workspace-class.ts @@ -10,5 +10,5 @@ export interface SupportedWorkspaceClass { displayName: string; description: string; powerups: number; - isSelected: boolean; + isDefault: boolean; } diff --git a/components/server/src/config.ts b/components/server/src/config.ts index 0d542d8f31b66a..bee13a32cd7fc8 100644 --- a/components/server/src/config.ts +++ b/components/server/src/config.ts @@ -16,7 +16,7 @@ import * as fs from "fs"; import * as yaml from "js-yaml"; import { log } from "@gitpod/gitpod-protocol/lib/util/logging"; import { filePathTelepresenceAware } from "@gitpod/gitpod-protocol/lib/env"; -import { WorkspaceClasses, WorkspaceClassesConfig } from "./workspace/workspace-classes"; +import { WorkspaceClassesConfig } from "./workspace/workspace-classes"; import { PrebuildRateLimiters } from "./workspace/prebuild-rate-limiter"; export const Config = Symbol("Config"); @@ -307,7 +307,12 @@ export namespace ConfigFile { } } - WorkspaceClasses.validate(config.workspaceClasses); + if (config.workspaceClasses.filter((c) => c.isDefault).length !== 1) { + log.error( + "Exactly one default workspace class needs to be configured: " + + JSON.stringify(config.workspaceClasses), + ); + } let patSigningKey = ""; if (config.patSigningKeyFile) { diff --git a/components/server/src/workspace/gitpod-server-impl.ts b/components/server/src/workspace/gitpod-server-impl.ts index 513b27ae996c1d..7d70926982a80b 100644 --- a/components/server/src/workspace/gitpod-server-impl.ts +++ b/components/server/src/workspace/gitpod-server-impl.ts @@ -174,7 +174,6 @@ import { WorkspaceClusterImagebuilderClientProvider } from "./workspace-cluster- import { VerificationService } from "../auth/verification-service"; import { BillingMode } from "@gitpod/gitpod-protocol/lib/billing-mode"; import { EntitlementService } from "../billing/entitlement-service"; -import { WorkspaceClasses } from "./workspace-classes"; import { formatPhoneNumber } from "../user/phone-numbers"; import { IDEService } from "../ide-service"; import { MessageBusIntegration } from "./messagebus-integration"; @@ -2947,25 +2946,15 @@ export class GitpodServerImpl implements GitpodServerWithTracing, Disposable { } async getSupportedWorkspaceClasses(ctx: TraceContext): Promise { - let user = this.checkAndBlockUser("getSupportedWorkspaceClasses"); - let selectedClass = await WorkspaceClasses.getConfiguredOrUpgradeFromLegacy( - user, - undefined, - this.config.workspaceClasses, - this.entitlementService, - ); - - let classes = this.config.workspaceClasses - .filter((c) => !c.deprecated) - .map((c) => ({ - id: c.id, - category: c.category, - displayName: c.displayName, - description: c.description, - powerups: c.powerups, - isSelected: selectedClass === c.id, - })); - + this.checkAndBlockUser("getSupportedWorkspaceClasses"); + const classes = this.config.workspaceClasses.map((c) => ({ + id: c.id, + category: c.category, + displayName: c.displayName, + description: c.description, + powerups: c.powerups, + isDefault: c.isDefault, + })); return classes; } diff --git a/components/server/src/workspace/workspace-classes.spec.ts b/components/server/src/workspace/workspace-classes.spec.ts deleted file mode 100644 index 1d7e5fbd222134..00000000000000 --- a/components/server/src/workspace/workspace-classes.spec.ts +++ /dev/null @@ -1,91 +0,0 @@ -/** - * Copyright (c) 2022 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. - */ - -import { WorkspaceClassesConfig, WorkspaceClasses } from "./workspace-classes"; -import * as chai from "chai"; -const expect = chai.expect; - -let config: WorkspaceClassesConfig = [ - { - id: "g1-standard", - isDefault: true, - category: "GENERAL PURPOSE", - displayName: "Standard", - description: "Up to 4 vCPU, 8 GB memory, 30GB storage", - powerups: 1, - deprecated: false, - }, -]; - -config.push({ - id: "g1-large", - isDefault: false, - category: "GENERAL PURPOSE", - displayName: "Large", - description: "Up to 8 vCPU, 16 GB memory, 50GB storage", - powerups: 2, - deprecated: false, - marker: { - moreResources: true, - }, -}); - -config.push({ - id: "g1-deprecated", - isDefault: false, - category: "GENERAL PURPOSE", - displayName: "Large", - description: "Up to 8 vCPU, 16 GB memory, 50GB storage", - powerups: 2, - deprecated: true, - marker: { - moreResources: true, - }, -}); - -describe("workspace-classes", function () { - describe("can substitute", function () { - it("classes are the same", function () { - const classId = WorkspaceClasses.selectClassForRegular("g1-large", "g1-large", config); - expect(classId).to.be.equal("g1-large"); - }); - - it("prebuild has more resources, substitute has not", function () { - const classId = WorkspaceClasses.selectClassForRegular("g1-large", "g1-standard", config); - expect(classId).to.be.equal("g1-large"); - }); - - it("prebuild has more resources, substitute also has more resources", function () { - const classId = WorkspaceClasses.selectClassForRegular("g1-large", "g1-large", config); - expect(classId).to.be.equal("g1-large"); - }); - - it("prebuild has more resources, substitute has not, prebuild is deprecated", function () { - const classId = WorkspaceClasses.selectClassForRegular("g1-deprecated", "g1-standard", config); - expect(classId).to.be.equal("g1-large"); - }); - - it("prebuild has more resources, substitute has not, prebuild not deprecated", function () { - const classId = WorkspaceClasses.selectClassForRegular("g1-large", "g1-standard", config); - expect(classId).to.be.equal("g1-large"); - }); - - it("prebuild does not have more resources, return substitute", function () { - const classId = WorkspaceClasses.selectClassForRegular("g1-standard", "g1-large", config); - expect(classId).to.be.equal("g1-large"); - }); - - it("prebuild does not have more resources, substitute unknown", function () { - const classId = WorkspaceClasses.selectClassForRegular("g1-standard", "g1-unknown", config); - expect(classId).to.be.equal("g1-standard"); - }); - - it("substitute is not acceptable", function () { - const classId = WorkspaceClasses.selectClassForRegular("g1-large", "g1-standard", config); - expect(classId).to.be.equal("g1-large"); - }); - }); -}); diff --git a/components/server/src/workspace/workspace-classes.ts b/components/server/src/workspace/workspace-classes.ts index 685f94123dcdd9..ad00998a890294 100644 --- a/components/server/src/workspace/workspace-classes.ts +++ b/components/server/src/workspace/workspace-classes.ts @@ -4,12 +4,6 @@ * See License-AGPL.txt in the project root for license information. */ -import { WorkspaceDB } from "@gitpod/gitpod-db/lib"; -import { Project, User, Workspace } from "@gitpod/gitpod-protocol"; -import { log } from "@gitpod/gitpod-protocol/lib/util/logging"; -import { TraceContext } from "@gitpod/gitpod-protocol/lib/util/tracing"; -import { EntitlementService } from "../billing/entitlement-service"; - export type WorkspaceClassesConfig = [WorkspaceClassConfig]; export interface WorkspaceClassConfig { @@ -31,191 +25,9 @@ export interface WorkspaceClassConfig { // The "power level" of the workspace class powerups: number; - // Whether or not to: - // - offer users this Workspace class for selection - // - use this class to start workspaces with. If a user has a class marked like this configured and starts a workspace they get the default class instead. - deprecated: boolean; - // Marks this class to have special semantics marker?: { // Marks this class as the one that users marked with "GetMoreResources" receive moreResources: boolean; }; } - -export namespace WorkspaceClasses { - /** - * @param workspaceClasses - * @return The WorkspaceClass ID of the first class that is marked with "moreResources" (and not deprecated). Falls back to "getDefaultId()". - */ - export function getMoreResourcesIdOrDefault(workspaceClasses: WorkspaceClassesConfig): string { - const moreResources = workspaceClasses.filter((c) => !c.deprecated).find((c) => !!c.marker?.moreResources); - if (moreResources) { - return moreResources.id; - } - - // fallback: default - return getDefaultId(workspaceClasses); - } - - /** - * @param workspaceClasses - * @return The WorkspaceClass ID of the "default" class - */ - export function getDefaultId(workspaceClasses: WorkspaceClassesConfig): string { - validate(workspaceClasses); - - return workspaceClasses.filter((c) => !c.deprecated).find((c) => c.isDefault)!.id; - } - - /** - * Checks that the given workspaceClass is: - * - still configured - * - not deprecated - * If any of that is the case, it returns the default class - * - * @param workspaceClasses - * @param previousWorkspaceClass - */ - export function getPreviousOrDefault( - workspaceClasses: WorkspaceClassesConfig, - previousWorkspaceClass: string | undefined, - ): string { - if (!previousWorkspaceClass) { - return getDefaultId(workspaceClasses); - } - - // todo: remove this once pvc has been rolled out - if (previousWorkspaceClass.endsWith("-pvc")) { - return previousWorkspaceClass; - } - - const config = workspaceClasses.find((c) => c.id === previousWorkspaceClass); - if (!config) { - log.error( - `Found previous instance with workspace class '${previousWorkspaceClass}' which is no longer configured! Falling back to default class.`, - { workspaceClasses }, - ); - return getDefaultId(workspaceClasses); - } - if (config.deprecated) { - log.info( - `Found previous instance with workspace class '${previousWorkspaceClass}' which is deprecated. Falling back to default class.`, - { workspaceClasses }, - ); - return getDefaultId(workspaceClasses); - } - return config.id; - } - - export function validate(workspaceClasses: WorkspaceClassesConfig): void { - const defaultClasses = workspaceClasses - .filter((c) => !c.deprecated) - .map((c) => (c.isDefault ? 1 : 0)) - .reduce((acc: number, isDefault: number) => (acc + isDefault) as number, 0); - - if (defaultClasses !== 1) { - throw new Error( - "Exactly one default workspace class needs to be configured:" + JSON.stringify(defaultClasses), - ); - } - } - - /** - * Gets the workspace class of the prebuild - * If the class is not supported anymore undefined will be returned - * @param ctx - * @param workspace - * @param db - * @param classes - */ - export async function getFromPrebuild( - ctx: TraceContext, - workspace: Workspace, - db: WorkspaceDB, - ): Promise { - const span = TraceContext.startSpan("getFromPrebuild", ctx); - try { - if (!workspace.basedOnPrebuildId) { - return undefined; - } - - const prebuild = await db.findPrebuildByID(workspace.basedOnPrebuildId); - if (!prebuild) { - return undefined; - } - - const buildWorkspaceInstance = await db.findCurrentInstance(prebuild.buildWorkspaceId); - return buildWorkspaceInstance?.workspaceClass; - } finally { - span.finish(); - } - } - - /** - * @param user - * @param classes - * @param entitlementService - */ - export async function getConfiguredOrUpgradeFromLegacy( - user: User, - project: Project | undefined, - classes: WorkspaceClassesConfig, - entitlementService: EntitlementService, - ): Promise { - if (project?.settings?.workspaceClasses?.regular) { - return project?.settings?.workspaceClasses?.regular; - } - if (user.additionalData?.workspaceClasses?.regular) { - return user.additionalData?.workspaceClasses?.regular; - } - - let workspaceClass = WorkspaceClasses.getDefaultId(classes); - if (await entitlementService.userGetsMoreResources(user)) { - workspaceClass = WorkspaceClasses.getMoreResourcesIdOrDefault(classes); - } - - return workspaceClass; - } - - /** - * @param currentClassId - * @param substituteClassId - * @param classes - */ - export function selectClassForRegular( - currentClassId: string, - substituteClassId: string | undefined, - classes: WorkspaceClassesConfig, - ): string { - if (currentClassId === substituteClassId) { - return currentClassId; - } - - const current = classes.find((c) => c.id === currentClassId); - let substitute = classes.find((c) => c.id === substituteClassId); - - // todo: remove this once pvc has been rolled out - if (currentClassId.endsWith("-pvc")) { - return currentClassId; - } - - if (current?.marker?.moreResources) { - if (substitute?.marker?.moreResources) { - return substitute?.id; - } else { - if (current.deprecated) { - return getMoreResourcesIdOrDefault(classes); - } else { - return current.id; - } - } - } else { - if (substitute?.id) { - return substitute.id; - } else { - return getDefaultId(classes); - } - } - } -} diff --git a/components/server/src/workspace/workspace-starter.spec.ts b/components/server/src/workspace/workspace-starter.spec.ts index 5226cc48600d6c..12fd1b290361ae 100644 --- a/components/server/src/workspace/workspace-starter.spec.ts +++ b/components/server/src/workspace/workspace-starter.spec.ts @@ -4,17 +4,10 @@ * See License-AGPL.txt in the project root for license information. */ -import { DBWithTracing, MaybeWorkspaceInstance, WorkspaceDB } from "@gitpod/gitpod-db/lib"; -import { WorkspaceClassesConfig } from "./workspace-classes"; -import { PrebuiltWorkspace, User, Workspace, WorkspaceInstance, WorkspaceType } from "@gitpod/gitpod-protocol"; +import { User } from "@gitpod/gitpod-protocol"; import { IDEOption, IDEOptions } from "@gitpod/gitpod-protocol/lib/ide-protocol"; import * as chai from "chai"; -import { migrationIDESettings, chooseIDE, getWorkspaceClassForInstance } from "./workspace-starter"; -import { MockTracer } from "opentracing"; -import { CustomTracerOpts, TraceContext, TracingManager } from "@gitpod/gitpod-protocol/lib/util/tracing"; -import { JaegerTracer } from "jaeger-client"; -import { EntitlementService } from "../billing/entitlement-service"; -import { EntitlementServiceChargebee } from "../../ee/src/billing/entitlement-service-chargebee"; +import { migrationIDESettings, chooseIDE } from "./workspace-starter"; const expect = chai.expect; describe("workspace-starter", function () { @@ -271,242 +264,4 @@ describe("workspace-starter", function () { expect(result.ideImage).to.equal(ideOptions.options["code"].latestImage); }); }); - describe("selectWorkspaceClass", function () { - it("new regular workspace, without prebuild, regular class configured", async function () { - const builder = new WorkspaceClassTestBuilder("regular").withRegularClassConfigured("g1-standard"); - await execute(builder, "g1-standard"); - }); - it("new regular workspace, without prebuild, class not configured, has more resources", async function () { - const builder = new WorkspaceClassTestBuilder("regular").withHasMoreResources(); - await execute(builder, "g1-large"); - }); - - it("new regular workspace, without prebuild, class not configured, does not have more resources", async function () { - const builder = new WorkspaceClassTestBuilder("regular"); - await execute(builder, "g1-standard"); - }); - - it("restarted workspace", async function () { - const builder = new WorkspaceClassTestBuilder("regular").withPreviousInstance("g1-large"); - await execute(builder, "g1-large"); - }); - - it("restarted workspace, class does not exist, fallback to default class", async function () { - const builder = new WorkspaceClassTestBuilder("regular").withPreviousInstance("g1-unknown"); - await execute(builder, "g1-standard"); - }); - - it("restarted workspace, class is deprecated, fallback to default class", async function () { - const builder = new WorkspaceClassTestBuilder("regular").withPreviousInstance("g1-deprecated"); - await execute(builder, "g1-standard"); - }); - - it("new prebuild workspace, prebuild class configured", async function () { - const builder = new WorkspaceClassTestBuilder("prebuild").withPrebuildClassConfigured("g1-large"); - await execute(builder, "g1-large"); - }); - - it("new prebuild workspace, prebuild class not configured, has more resources", async function () { - const builder = new WorkspaceClassTestBuilder("prebuild").withHasMoreResources(); - await execute(builder, "g1-large"); - }); - - it("new prebuild workspace, prebuild class not configured, does not have more resources", async function () { - const builder = new WorkspaceClassTestBuilder("prebuild"); - await execute(builder, "g1-standard"); - }); - }); }); - -async function execute(builder: WorkspaceClassTestBuilder, expectedClass: string) { - let [ctx, workspace, previousInstance, user, entitlementService, config, workspaceDb] = builder.build(); - - let actualClass = await getWorkspaceClassForInstance( - ctx, - workspace, - previousInstance, - user, - undefined, - entitlementService, - config, - workspaceDb, - ); - expect(actualClass).to.equal(expectedClass); -} - -class WorkspaceClassTestBuilder { - // Type of the workspace that is being created e.g. regular or prebuild - workspaceType: WorkspaceType; - - // The workspace class of the previous instance of the workspace - previousInstanceClass: string; - - // The class configured by the user for a regular workspace - configuredRegularClass: string; - - // The class configured by the user for a prebuild workspace - configuredPrebuildClass: string; - - // Workspace is based on a prebuild - basedOnPrebuild: string; - - // User has more resources - hasMoreResources: boolean; - - constructor(workspaceType: WorkspaceType) { - this.workspaceType = workspaceType; - } - - public withPreviousInstance(classId: string): WorkspaceClassTestBuilder { - this.previousInstanceClass = classId; - return this; - } - - public withPrebuild(): WorkspaceClassTestBuilder { - this.basedOnPrebuild = "0kaks09j"; - return this; - } - - public withRegularClassConfigured(classId: string): WorkspaceClassTestBuilder { - this.configuredRegularClass = classId; - return this; - } - - public withPrebuildClassConfigured(classId: string): WorkspaceClassTestBuilder { - this.configuredPrebuildClass = classId; - return this; - } - - public withHasMoreResources(): WorkspaceClassTestBuilder { - this.hasMoreResources = true; - return this; - } - - public build(): [ - TraceContext, - Workspace, - WorkspaceInstance, - User, - EntitlementService, - WorkspaceClassesConfig, - DBWithTracing, - ] { - const tracer = new MockTracer(); - const span = tracer.startSpan("testspan"); - const ctx = { - span, - }; - - const workspace: Workspace = { - basedOnPrebuildId: this.basedOnPrebuild, - type: this.workspaceType, - } as Workspace; - - const previousInstance: WorkspaceInstance = { - workspaceClass: this.previousInstanceClass, - } as WorkspaceInstance; - - let user: User = { - id: "string", - creationDate: "string", - identities: [], - additionalData: { - workspaceClasses: { - regular: this.configuredRegularClass, - prebuild: this.configuredPrebuildClass, - }, - }, - }; - - const entitlementService: EntitlementService = new MockEntitlementService(this.hasMoreResources); - - let config: WorkspaceClassesConfig = [ - { - id: "g1-standard", - isDefault: true, - category: "GENERAL PURPOSE", - displayName: "Standard", - description: "Up to 4 vCPU, 8 GB memory, 30GB storage", - powerups: 1, - deprecated: false, - }, - ]; - - config.push({ - id: "g1-large", - isDefault: false, - category: "GENERAL PURPOSE", - displayName: "Large", - description: "Up to 8 vCPU, 16 GB memory, 50GB storage", - powerups: 2, - deprecated: false, - marker: { - moreResources: this.hasMoreResources, - }, - }); - - config.push({ - id: "g1-deprecated", - isDefault: false, - category: "GENERAL PURPOSE", - displayName: "Large", - description: "Up to 8 vCPU, 16 GB memory, 50GB storage", - powerups: 2, - deprecated: true, - }); - - const workspaceDb = new MockWorkspaceDb(!!this.basedOnPrebuild); - const workspaceDbWithTracing: DBWithTracing = new DBWithTracing( - workspaceDb, - new MockTracingManager(), - ); - - return [ctx, workspace, previousInstance, user, entitlementService, config, workspaceDbWithTracing]; - } -} - -class MockEntitlementService extends EntitlementServiceChargebee { - constructor(protected hasMoreResources: boolean) { - super(); - } - - userGetsMoreResources(user: User): Promise { - return new Promise((resolve) => { - resolve(this.hasMoreResources); - }); - } -} - -class MockWorkspaceDb { - constructor(protected hasPrebuild: boolean) {} - - findPrebuildByID(pwsid: string): Promise { - return new Promise((resolve) => { - if (this.hasPrebuild) { - resolve({ - buildWorkspaceId: "string", - } as PrebuiltWorkspace); - } else { - resolve(undefined); - } - }); - } - - findCurrentInstance(workspaceId: string): Promise { - return new Promise((resolve) => { - if (this.hasPrebuild) { - resolve({ - id: "string", - } as MaybeWorkspaceInstance); - } else { - resolve(undefined); - } - }); - } -} - -class MockTracingManager extends TracingManager { - getTracerForService(serviceName: string, opts?: CustomTracerOpts | undefined): JaegerTracer { - return {} as JaegerTracer; - } -} diff --git a/components/server/src/workspace/workspace-starter.ts b/components/server/src/workspace/workspace-starter.ts index 2be9fc14e1765b..ee5355a3b30c58 100644 --- a/components/server/src/workspace/workspace-starter.ts +++ b/components/server/src/workspace/workspace-starter.ts @@ -121,11 +121,10 @@ import { import { ContextParser } from "./context-parser-service"; import { WorkspaceClusterImagebuilderClientProvider } from "./workspace-cluster-imagebuilder-client-provider"; import { getExperimentsClientForBackend } from "@gitpod/gitpod-protocol/lib/experiments/configcat-server"; -import { WorkspaceClasses, WorkspaceClassesConfig } from "./workspace-classes"; +import { WorkspaceClassesConfig } from "./workspace-classes"; import { EntitlementService } from "../billing/entitlement-service"; import { BillingModes } from "../../ee/src/billing/billing-mode"; import { AttributionId } from "@gitpod/gitpod-protocol/lib/attribution"; -import { BillingMode } from "@gitpod/gitpod-protocol/lib/billing-mode"; import { LogContext } from "@gitpod/gitpod-protocol/lib/util/logging"; import { repeat } from "@gitpod/gitpod-protocol/lib/util/repeat"; @@ -203,51 +202,29 @@ export const chooseIDE = ( export async function getWorkspaceClassForInstance( ctx: TraceContext, workspace: Workspace, - previousInstance: WorkspaceInstance | undefined, user: User, project: Project | undefined, entitlementService: EntitlementService, config: WorkspaceClassesConfig, - workspaceDb: DBWithTracing, ): Promise { const span = TraceContext.startSpan("getWorkspaceClassForInstance", ctx); try { - let workspaceClass = ""; - if (!previousInstance?.workspaceClass) { - if (workspace.type == "regular") { - const prebuildClass = await WorkspaceClasses.getFromPrebuild(ctx, workspace, workspaceDb.trace(ctx)); - if (prebuildClass) { - const userClass = await WorkspaceClasses.getConfiguredOrUpgradeFromLegacy( - user, - project, - config, - entitlementService, - ); - workspaceClass = WorkspaceClasses.selectClassForRegular(prebuildClass, userClass, config); - } else if (project?.settings?.workspaceClasses?.regular) { - workspaceClass = project?.settings?.workspaceClasses?.regular; - } else if (user.additionalData?.workspaceClasses?.regular) { - workspaceClass = user.additionalData?.workspaceClasses?.regular; - } - } - - if (workspace.type === "prebuild") { - if (project?.settings?.workspaceClasses?.prebuild) { - workspaceClass = project?.settings?.workspaceClasses?.prebuild; - } - } - - if (!workspaceClass) { - workspaceClass = WorkspaceClasses.getDefaultId(config); - if (await entitlementService.userGetsMoreResources(user)) { - workspaceClass = WorkspaceClasses.getMoreResourcesIdOrDefault(config); - } - } - } else { - workspaceClass = WorkspaceClasses.getPreviousOrDefault(config, previousInstance.workspaceClass); + let workspaceClass: string | undefined; + switch (workspace.type) { + case "prebuild": + workspaceClass = project?.settings?.workspaceClasses?.prebuild; + break; + case "regular": + workspaceClass = project?.settings?.workspaceClasses?.regular; + break; } - - return workspaceClass; + if (!workspaceClass && (await entitlementService.userGetsMoreResources(user))) { + workspaceClass = config.find((c) => !!c.marker?.moreResources)?.id; + } + if (!workspaceClass) { + workspaceClass = config.find((c) => !!c.isDefault)?.id; + } + return workspaceClass!; } finally { span.finish(); } @@ -918,41 +895,16 @@ export class WorkspaceStarter { await this.tryEnablePSI(featureFlags, user, billingTier); const usageAttributionId = await this.userService.getWorkspaceUsageAttributionId(user, workspace.projectId); - const billingMode = await this.billingModes.getBillingMode(usageAttributionId, new Date()); - - let workspaceClass = ""; - if (BillingMode.canSetWorkspaceClass(billingMode)) { - // this is either the first time we start the workspace or the workspace was started - // before workspace classes and does not have a class yet - workspaceClass = await getWorkspaceClassForInstance( - ctx, - workspace, - previousInstance, - user, - project, - this.entitlementService, - this.config.workspaceClasses, - this.workspaceDb, - ); + let workspaceClass = await getWorkspaceClassForInstance( + ctx, + workspace, + user, + project, + this.entitlementService, + this.config.workspaceClasses, + ); - featureFlags = featureFlags.concat(["workspace_class_limiting"]); - } else { - // todo: remove this once pvc has been rolled out - const prebuildClass = await WorkspaceClasses.getFromPrebuild( - ctx, - workspace, - this.workspaceDb.trace(ctx), - ); - if (prebuildClass?.endsWith("-pvc")) { - workspaceClass = prebuildClass; - // #### - } else { - workspaceClass = "default"; - if (await this.entitlementService.userGetsMoreResources(user)) { - workspaceClass = "gitpodio-internal-xl"; - } - } - } + featureFlags = featureFlags.concat(["workspace_class_limiting"]); if (!!featureFlags) { // only set feature flags if there actually are any. Otherwise we waste the diff --git a/dev/preview/workflow/preview/deploy-gitpod.sh b/dev/preview/workflow/preview/deploy-gitpod.sh index 9081a58a7a6d82..8e9d7726630d20 100755 --- a/dev/preview/workflow/preview/deploy-gitpod.sh +++ b/dev/preview/workflow/preview/deploy-gitpod.sh @@ -274,7 +274,6 @@ yq w -i "${INSTALLER_CONFIG_PATH}" experimental.webapp.workspaceClasses[0].displ yq w -i "${INSTALLER_CONFIG_PATH}" experimental.webapp.workspaceClasses[0].description "Default workspace class (30GB disk)" yq w -i "${INSTALLER_CONFIG_PATH}" experimental.webapp.workspaceClasses[0].powerups "1" yq w -i "${INSTALLER_CONFIG_PATH}" experimental.webapp.workspaceClasses[0].isDefault "true" -yq w -i "${INSTALLER_CONFIG_PATH}" experimental.webapp.workspaceClasses[0].deprecated "false" yq w -i "${INSTALLER_CONFIG_PATH}" experimental.webapp.workspaceClasses[0].credits.perMinute "0.3333333333" yq w -i "${INSTALLER_CONFIG_PATH}" experimental.webapp.workspaceClasses[+].id "small" @@ -282,8 +281,6 @@ yq w -i "${INSTALLER_CONFIG_PATH}" experimental.webapp.workspaceClasses[1].categ yq w -i "${INSTALLER_CONFIG_PATH}" experimental.webapp.workspaceClasses[1].displayName "Small" yq w -i "${INSTALLER_CONFIG_PATH}" experimental.webapp.workspaceClasses[1].description "Small workspace class (20GB disk)" yq w -i "${INSTALLER_CONFIG_PATH}" experimental.webapp.workspaceClasses[1].powerups "2" -yq w -i "${INSTALLER_CONFIG_PATH}" experimental.webapp.workspaceClasses[1].isDefault "false" -yq w -i "${INSTALLER_CONFIG_PATH}" experimental.webapp.workspaceClasses[1].deprecated "false" yq w -i "${INSTALLER_CONFIG_PATH}" experimental.webapp.workspaceClasses[1].credits.perMinute "0.1666666667" yq w -i "${INSTALLER_CONFIG_PATH}" experimental.webapp.workspaceClasses[1].marker.moreResources "true" diff --git a/install/installer/pkg/components/server/configmap.go b/install/installer/pkg/components/server/configmap.go index 43f70a00637286..c5670b80f65c95 100644 --- a/install/installer/pkg/components/server/configmap.go +++ b/install/installer/pkg/components/server/configmap.go @@ -139,7 +139,6 @@ func configmap(ctx *common.RenderContext) ([]runtime.Object, error) { Description: "Default workspace class", PowerUps: 1, IsDefault: true, - Deprecated: false, }, } ctx.WithExperimental(func(cfg *experimental.Config) error { @@ -153,7 +152,6 @@ func configmap(ctx *common.RenderContext) ([]runtime.Object, error) { Description: cl.Description, PowerUps: cl.PowerUps, IsDefault: cl.IsDefault, - Deprecated: cl.Deprecated, Marker: cl.Marker, } diff --git a/install/installer/pkg/components/slowserver/configmap.go b/install/installer/pkg/components/slowserver/configmap.go index 604d13b24a3a45..37bd09e61a0431 100644 --- a/install/installer/pkg/components/slowserver/configmap.go +++ b/install/installer/pkg/components/slowserver/configmap.go @@ -126,7 +126,6 @@ func configmap(ctx *common.RenderContext) ([]runtime.Object, error) { Description: "Default workspace class", PowerUps: 1, IsDefault: true, - Deprecated: false, }, } ctx.WithExperimental(func(cfg *experimental.Config) error { @@ -140,7 +139,6 @@ func configmap(ctx *common.RenderContext) ([]runtime.Object, error) { Description: cl.Description, PowerUps: cl.PowerUps, IsDefault: cl.IsDefault, - Deprecated: cl.Deprecated, Marker: cl.Marker, }