Skip to content

Commit bfeb6ba

Browse files
committed
[server] Ensure old workspaces can be started
1 parent f817d5f commit bfeb6ba

File tree

1 file changed

+117
-120
lines changed

1 file changed

+117
-120
lines changed

components/server/src/workspace/workspace-starter.ts

Lines changed: 117 additions & 120 deletions
Original file line numberDiff line numberDiff line change
@@ -689,152 +689,149 @@ export class WorkspaceStarter {
689689
ideConfig: IDEConfig,
690690
forcePVC: boolean,
691691
): Promise<WorkspaceInstance> {
692+
const span = TraceContext.startSpan("buildWorkspaceImage", ctx);
692693
//#endregion IDE resolution TODO(ak) move to IDE service
693694
// TODO: Compatible with ide-config not deployed, need revert after ide-config deployed
694695
delete ideConfig.ideOptions.options["code-latest"];
695696
delete ideConfig.ideOptions.options["code-desktop-insiders"];
696697

697-
const migrated = migrationIDESettings(user);
698-
if (user.additionalData?.ideSettings && migrated) {
699-
user.additionalData.ideSettings = migrated;
700-
}
698+
try {
699+
const migrated = migrationIDESettings(user);
700+
if (user.additionalData?.ideSettings && migrated) {
701+
user.additionalData.ideSettings = migrated;
702+
}
701703

702-
const ideChoice = user.additionalData?.ideSettings?.defaultIde;
703-
const useLatest = !!user.additionalData?.ideSettings?.useLatestVersion;
704-
705-
// TODO(cw): once we allow changing the IDE in the workspace config (i.e. .gitpod.yml), we must
706-
// give that value precedence over the default choice.
707-
const configuration: WorkspaceInstanceConfiguration = {
708-
ideImage: ideConfig.ideOptions.options[ideConfig.ideOptions.defaultIde].image,
709-
supervisorImage: ideConfig.supervisorImage,
710-
ideConfig: {
711-
// We only check user setting because if code(insider) but desktopIde has no latestImage
712-
// it still need to notice user that this workspace is using latest IDE
713-
useLatest: user.additionalData?.ideSettings?.useLatestVersion,
714-
},
715-
};
704+
const ideChoice = user.additionalData?.ideSettings?.defaultIde;
705+
const useLatest = !!user.additionalData?.ideSettings?.useLatestVersion;
706+
707+
// TODO(cw): once we allow changing the IDE in the workspace config (i.e. .gitpod.yml), we must
708+
// give that value precedence over the default choice.
709+
const configuration: WorkspaceInstanceConfiguration = {
710+
ideImage: ideConfig.ideOptions.options[ideConfig.ideOptions.defaultIde].image,
711+
supervisorImage: ideConfig.supervisorImage,
712+
ideConfig: {
713+
// We only check user setting because if code(insider) but desktopIde has no latestImage
714+
// it still need to notice user that this workspace is using latest IDE
715+
useLatest: user.additionalData?.ideSettings?.useLatestVersion,
716+
},
717+
};
716718

717-
if (!!ideChoice) {
718-
const choose = chooseIDE(
719-
ideChoice,
720-
ideConfig.ideOptions,
721-
useLatest,
722-
this.authService.hasPermission(user, "ide-settings"),
723-
);
724-
configuration.ideImage = choose.ideImage;
725-
configuration.desktopIdeImage = choose.desktopIdeImage;
726-
}
719+
if (!!ideChoice) {
720+
const choose = chooseIDE(
721+
ideChoice,
722+
ideConfig.ideOptions,
723+
useLatest,
724+
this.authService.hasPermission(user, "ide-settings"),
725+
);
726+
configuration.ideImage = choose.ideImage;
727+
configuration.desktopIdeImage = choose.desktopIdeImage;
728+
}
727729

728-
const referrerIde = this.resolveReferrerIDE(workspace, user, ideConfig);
729-
if (referrerIde) {
730-
configuration.desktopIdeImage = useLatest
731-
? referrerIde.option.latestImage ?? referrerIde.option.image
732-
: referrerIde.option.image;
733-
if (!user.additionalData?.ideSettings) {
734-
// A user does not have IDE settings configured yet configure it with a referrer ide as default.
735-
const additionalData = user?.additionalData || {};
736-
const settings = additionalData.ideSettings || {};
737-
settings.settingVersion = "2.0";
738-
settings.defaultIde = referrerIde.id;
739-
additionalData.ideSettings = settings;
740-
user.additionalData = additionalData;
741-
this.userDB
742-
.trace(ctx)
743-
.updateUserPartial(user)
744-
.catch((e) => {
745-
log.error({ userId: user.id }, "cannot configure default desktop ide", e);
746-
});
730+
const referrerIde = this.resolveReferrerIDE(workspace, user, ideConfig);
731+
if (referrerIde) {
732+
configuration.desktopIdeImage = useLatest
733+
? referrerIde.option.latestImage ?? referrerIde.option.image
734+
: referrerIde.option.image;
735+
if (!user.additionalData?.ideSettings) {
736+
// A user does not have IDE settings configured yet configure it with a referrer ide as default.
737+
const additionalData = user?.additionalData || {};
738+
const settings = additionalData.ideSettings || {};
739+
settings.settingVersion = "2.0";
740+
settings.defaultIde = referrerIde.id;
741+
additionalData.ideSettings = settings;
742+
user.additionalData = additionalData;
743+
this.userDB
744+
.trace(ctx)
745+
.updateUserPartial(user)
746+
.catch((e) => {
747+
log.error({ userId: user.id }, "cannot configure default desktop ide", e);
748+
});
749+
}
747750
}
748-
}
749-
//#endregion
751+
//#endregion
750752

751-
let featureFlags: NamedWorkspaceFeatureFlag[] = workspace.config._featureFlags || [];
752-
featureFlags = featureFlags.concat(this.config.workspaceDefaults.defaultFeatureFlags);
753-
if (user.featureFlags && user.featureFlags.permanentWSFeatureFlags) {
754-
featureFlags = featureFlags.concat(featureFlags, user.featureFlags.permanentWSFeatureFlags);
755-
}
753+
let featureFlags: NamedWorkspaceFeatureFlag[] = workspace.config._featureFlags || [];
754+
featureFlags = featureFlags.concat(this.config.workspaceDefaults.defaultFeatureFlags);
755+
if (user.featureFlags && user.featureFlags.permanentWSFeatureFlags) {
756+
featureFlags = featureFlags.concat(featureFlags, user.featureFlags.permanentWSFeatureFlags);
757+
}
756758

757-
// if the user has feature preview enabled, we need to add the respective feature flags.
758-
// Beware: all feature flags we add here are not workspace-persistent feature flags, e.g. no full-workspace backup.
759-
if (!!user.additionalData?.featurePreview) {
760-
featureFlags = featureFlags.concat(
761-
this.config.workspaceDefaults.previewFeatureFlags.filter((f) => !featureFlags.includes(f)),
762-
);
763-
}
759+
// if the user has feature preview enabled, we need to add the respective feature flags.
760+
// Beware: all feature flags we add here are not workspace-persistent feature flags, e.g. no full-workspace backup.
761+
if (!!user.additionalData?.featurePreview) {
762+
featureFlags = featureFlags.concat(
763+
this.config.workspaceDefaults.previewFeatureFlags.filter((f) => !featureFlags.includes(f)),
764+
);
765+
}
764766

765-
featureFlags = featureFlags.filter((f) => !excludeFeatureFlags.includes(f));
767+
featureFlags = featureFlags.filter((f) => !excludeFeatureFlags.includes(f));
766768

767-
if (forcePVC === true) {
768-
featureFlags = featureFlags.concat(["persistent_volume_claim"]);
769-
}
769+
if (forcePVC === true) {
770+
featureFlags = featureFlags.concat(["persistent_volume_claim"]);
771+
}
770772

771-
if (!!featureFlags) {
772-
// only set feature flags if there actually are any. Otherwise we waste the
773-
// few bytes of JSON in the database for no good reason.
774-
configuration.featureFlags = featureFlags;
775-
}
773+
if (!!featureFlags) {
774+
// only set feature flags if there actually are any. Otherwise we waste the
775+
// few bytes of JSON in the database for no good reason.
776+
configuration.featureFlags = featureFlags;
777+
}
776778

777-
const usageAttributionId = await this.userService.getWorkspaceUsageAttributionId(user, workspace.projectId);
779+
const usageAttributionId = await this.userService.getWorkspaceUsageAttributionId(user, workspace.projectId);
778780

779-
let workspaceClass = "";
780-
let classesEnabled = await getExperimentsClientForBackend().getValueAsync("workspace_classes", false, {
781-
user: user,
782-
});
783-
if (classesEnabled) {
784-
workspaceClass = this.config.workspaceClasses.default;
785-
if (workspace.type == "regular") {
786-
if (user.additionalData?.workspaceClasses?.regular) {
787-
workspaceClass = user.additionalData?.workspaceClasses?.regular;
788-
} else {
789-
// legacy support
781+
let workspaceClass = "";
782+
let classesEnabled = await getExperimentsClientForBackend().getValueAsync("workspace_classes", false, {
783+
user: user,
784+
});
785+
if (classesEnabled) {
786+
// this is a workspace that was started before workspace classes
787+
// set the workspace class based on if the user "has more resources"
788+
if (!workspace.workspaceClass) {
790789
if (await this.userService.userGetsMoreResources(user)) {
791790
workspaceClass = this.config.workspaceClasses.defaultMoreResources;
791+
} else {
792+
workspaceClass = this.config.workspaceClasses.default;
792793
}
793-
}
794-
}
795794

796-
if (workspace.type == "prebuild") {
797-
if (user.additionalData?.workspaceClasses?.prebuild) {
798-
workspaceClass = user.additionalData?.workspaceClasses?.prebuild;
795+
workspace.workspaceClass = workspaceClass;
796+
this.workspaceDb.trace({ span }).store(workspace);
799797
} else {
800-
// legacy support
801-
if (await this.userService.userGetsMoreResources(user)) {
802-
workspaceClass = this.config.workspaceClasses.defaultMoreResources;
803-
}
798+
workspaceClass = workspace.workspaceClass;
804799
}
805800
}
806-
}
807801

808-
const now = new Date().toISOString();
809-
const instance: WorkspaceInstance = {
810-
id: uuidv4(),
811-
workspaceId: workspace.id,
812-
creationTime: now,
813-
ideUrl: "", // Initially empty, filled during starting process
814-
region: this.config.installationShortname, // Shortname set to bridge can cleanup workspaces stuck preparing
815-
workspaceImage: "", // Initially empty, filled during starting process
816-
status: {
817-
version: 0,
818-
conditions: {},
819-
phase: "preparing",
820-
},
821-
configuration,
822-
usageAttributionId,
823-
workspaceClass,
824-
};
825-
if (WithReferrerContext.is(workspace.context)) {
826-
this.analytics.track({
827-
userId: user.id,
828-
event: "ide_referrer",
829-
properties: {
830-
workspaceId: workspace.id,
831-
instanceId: instance.id,
832-
referrer: workspace.context.referrer,
833-
referrerIde: workspace.context.referrerIde,
802+
const now = new Date().toISOString();
803+
const instance: WorkspaceInstance = {
804+
id: uuidv4(),
805+
workspaceId: workspace.id,
806+
creationTime: now,
807+
ideUrl: "", // Initially empty, filled during starting process
808+
region: this.config.installationShortname, // Shortname set to bridge can cleanup workspaces stuck preparing
809+
workspaceImage: "", // Initially empty, filled during starting process
810+
status: {
811+
version: 0,
812+
conditions: {},
813+
phase: "preparing",
834814
},
835-
});
815+
configuration,
816+
usageAttributionId,
817+
workspaceClass,
818+
};
819+
if (WithReferrerContext.is(workspace.context)) {
820+
this.analytics.track({
821+
userId: user.id,
822+
event: "ide_referrer",
823+
properties: {
824+
workspaceId: workspace.id,
825+
instanceId: instance.id,
826+
referrer: workspace.context.referrer,
827+
referrerIde: workspace.context.referrerIde,
828+
},
829+
});
830+
}
831+
return instance;
832+
} finally {
833+
span.finish();
836834
}
837-
return instance;
838835
}
839836

840837
// TODO(ak) move to IDE service

0 commit comments

Comments
 (0)