Skip to content

Commit b67e3ec

Browse files
csweichelroboquat
authored andcommitted
[workspace-cluster] Introduce has-more-resources constraint
1 parent dbeeafa commit b67e3ec

File tree

9 files changed

+131
-22
lines changed

9 files changed

+131
-22
lines changed

components/gitpod-protocol/src/workspace-cluster.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,11 @@ export namespace TLSConfig {
5252
export type WorkspaceClusterWoTLS = Omit<WorkspaceCluster, "tls">;
5353
export type WorkspaceManagerConnectionInfo = Pick<WorkspaceCluster, "name" | "url" | "tls">;
5454

55-
export type AdmissionConstraint = AdmissionConstraintFeaturePreview | AdmissionConstraintHasRole | AdmissionConstraintHasUserLevel;
55+
export type AdmissionConstraint = AdmissionConstraintFeaturePreview | AdmissionConstraintHasRole | AdmissionConstraintHasUserLevel | AdmissionConstraintHasMoreResources;
5656
export type AdmissionConstraintFeaturePreview = { type: "has-feature-preview" };
5757
export type AdmissionConstraintHasRole = { type: "has-permission", permission: PermissionName };
5858
export type AdmissionConstraintHasUserLevel = { type: "has-user-level", level: string };
59-
60-
export type AdmissionPreference = AdmissionPreferenceUserLevel;
61-
export type AdmissionPreferenceUserLevel = { type: 'user-level', level: string };
59+
export type AdmissionConstraintHasMoreResources = { type: "has-more-resources" };
6260

6361

6462
export const WorkspaceClusterDB = Symbol("WorkspaceClusterDB");

components/ws-manager-api/typescript/src/client-provider.spec.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import { WorkspaceManagerClientProviderCompositeSource, WorkspaceManagerClientPr
1414
import { WorkspaceCluster, WorkspaceClusterWoTLS } from "@gitpod/gitpod-protocol/lib/workspace-cluster";
1515
import { User, Workspace, WorkspaceInstance } from "@gitpod/gitpod-protocol";
1616
import { PromisifiedWorkspaceManagerClient } from ".";
17-
import { Constraint, constraintNewWorkspaceCluster, ExtendedUser, intersect, invert } from "./constraints";
17+
import { Constraint, constraintInverseMoreResources, constraintMoreResources, constraintNewWorkspaceCluster, ExtendedUser, intersect, invert } from "./constraints";
1818
const expect = chai.expect;
1919

2020
@suite
@@ -90,6 +90,18 @@ class TestClientProvider {
9090
expect(constraintNewWorkspaceCluster(clusters, {rolesOrPermissions:["new-workspace-cluster"]} as ExtendedUser, {} as Workspace, {} as WorkspaceInstance).map(c => c.name)).to.be.eql(["a1"]);
9191
}
9292

93+
@test
94+
public testConstraintHasMoreResources() {
95+
const clusters: WorkspaceClusterWoTLS[] = [
96+
{name: "a1", admissionConstraints: [{ type: "has-more-resources" }]} as WorkspaceClusterWoTLS,
97+
{name: "b1" } as WorkspaceClusterWoTLS,
98+
]
99+
expect(constraintMoreResources(clusters, {} as ExtendedUser, {} as Workspace, {} as WorkspaceInstance).map(c => c.name), "gets no more resources").to.be.empty;
100+
expect(constraintMoreResources(clusters, {getsMoreResources: true} as ExtendedUser, {} as Workspace, {} as WorkspaceInstance).map(c => c.name), "gets more resources").to.be.eql(["a1"]);
101+
expect(constraintInverseMoreResources(clusters, {} as ExtendedUser, {} as Workspace, {} as WorkspaceInstance).map(c => c.name), "inverse more resources").to.be.eql(["b1"]);
102+
expect(constraintInverseMoreResources(clusters, {getsMoreResources: true} as ExtendedUser, {} as Workspace, {} as WorkspaceInstance).map(c => c.name), "inverse more resources").to.be.eql(["b1"]);
103+
}
104+
93105
private async expectInstallations(expected: string[], actual: IWorkspaceClusterStartSet, msg: string) {
94106
const a: string[] = [];
95107
for await (const c of actual) {

components/ws-manager-api/typescript/src/constraints.ts

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import { WorkspaceClusterWoTLS } from "@gitpod/gitpod-protocol/lib/workspace-clu
1313
*/
1414
export interface ExtendedUser extends User {
1515
level?: string;
16+
getsMoreResources?: boolean;
1617
}
1718

1819
export interface WorkspaceClusterConstraintSet {
@@ -39,11 +40,11 @@ export const workspaceClusterSets: WorkspaceClusterConstraintSet[] = [
3940
)
4041
},
4142
{
42-
name: "regional reguilar",
43+
name: "regional regular",
4344
constraint:
4445
intersect(
4546
constraintRegional,
46-
invert(constraintMoreResources),
47+
constraintInverseMoreResources,
4748
constraintInverseNewWorkspaceCluster
4849
)
4950
},
@@ -60,12 +61,8 @@ export const workspaceClusterSets: WorkspaceClusterConstraintSet[] = [
6061
name: "non-regional non-paying",
6162
constraint:
6263
intersect(
63-
invert(
64-
intersect(
65-
constraintRegional,
66-
constraintMoreResources,
67-
)
68-
),
64+
invert(constraintRegional),
65+
constraintInverseMoreResources,
6966
constraintInverseNewWorkspaceCluster
7067
)
7168
},
@@ -112,7 +109,16 @@ export function constraintRegional(all: WorkspaceClusterWoTLS[], user: ExtendedU
112109
return [];
113110
}
114111

112+
export function constraintInverseMoreResources(all: WorkspaceClusterWoTLS[], user: ExtendedUser, workspace: Workspace, instance: WorkspaceInstance): WorkspaceClusterWoTLS[] {
113+
return all.filter(cluster => !cluster.admissionConstraints?.find(constraint => constraint.type === "has-more-resources"));
114+
}
115+
115116
export function constraintMoreResources(all: WorkspaceClusterWoTLS[], user: ExtendedUser, workspace: Workspace, instance: WorkspaceInstance): WorkspaceClusterWoTLS[] {
116-
// TODO(cw): implement me
117-
return [];
117+
if (!user.getsMoreResources) {
118+
// if the user does not get more resources, we don't have to go and find any
119+
// which carry this constraint - the user would not be able to access it anyways.
120+
return [];
121+
}
122+
123+
return all.filter(cluster => !!cluster.admissionConstraints?.find(constraint => constraint.type === "has-more-resources"));
118124
}

components/ws-manager-bridge-api/cluster-service.proto

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ message AdmissionConstraint {
5151
FeaturePreview has_feature_preview = 1;
5252
HasPermission has_permission = 2;
5353
string has_user_level = 3;
54+
bool has_more_resources = 4;
5455
}
5556
}
5657

components/ws-manager-bridge-api/go/cluster-service.pb.go

Lines changed: 20 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

components/ws-manager-bridge-api/typescript/src/cluster-service_pb.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,11 @@ export class AdmissionConstraint extends jspb.Message {
138138
getHasUserLevel(): string;
139139
setHasUserLevel(value: string): AdmissionConstraint;
140140

141+
hasHasMoreResources(): boolean;
142+
clearHasMoreResources(): void;
143+
getHasMoreResources(): boolean;
144+
setHasMoreResources(value: boolean): AdmissionConstraint;
145+
141146
getConstraintCase(): AdmissionConstraint.ConstraintCase;
142147

143148
serializeBinary(): Uint8Array;
@@ -155,6 +160,7 @@ export namespace AdmissionConstraint {
155160
hasFeaturePreview?: AdmissionConstraint.FeaturePreview.AsObject,
156161
hasPermission?: AdmissionConstraint.HasPermission.AsObject,
157162
hasUserLevel: string,
163+
hasMoreResources: boolean,
158164
}
159165

160166

@@ -201,6 +207,7 @@ export namespace AdmissionConstraint {
201207
HAS_FEATURE_PREVIEW = 1,
202208
HAS_PERMISSION = 2,
203209
HAS_USER_LEVEL = 3,
210+
HAS_MORE_RESOURCES = 4,
204211
}
205212

206213
}

components/ws-manager-bridge-api/typescript/src/cluster-service_pb.js

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1173,7 +1173,7 @@ proto.workspacemanagerbridge.RegistrationHints.prototype.setGovern = function(va
11731173
* @private {!Array<!Array<number>>}
11741174
* @const
11751175
*/
1176-
proto.workspacemanagerbridge.AdmissionConstraint.oneofGroups_ = [[1,2,3]];
1176+
proto.workspacemanagerbridge.AdmissionConstraint.oneofGroups_ = [[1,2,3,4]];
11771177

11781178
/**
11791179
* @enum {number}
@@ -1182,7 +1182,8 @@ proto.workspacemanagerbridge.AdmissionConstraint.ConstraintCase = {
11821182
CONSTRAINT_NOT_SET: 0,
11831183
HAS_FEATURE_PREVIEW: 1,
11841184
HAS_PERMISSION: 2,
1185-
HAS_USER_LEVEL: 3
1185+
HAS_USER_LEVEL: 3,
1186+
HAS_MORE_RESOURCES: 4
11861187
};
11871188

11881189
/**
@@ -1225,7 +1226,8 @@ proto.workspacemanagerbridge.AdmissionConstraint.toObject = function(includeInst
12251226
var f, obj = {
12261227
hasFeaturePreview: (f = msg.getHasFeaturePreview()) && proto.workspacemanagerbridge.AdmissionConstraint.FeaturePreview.toObject(includeInstance, f),
12271228
hasPermission: (f = msg.getHasPermission()) && proto.workspacemanagerbridge.AdmissionConstraint.HasPermission.toObject(includeInstance, f),
1228-
hasUserLevel: jspb.Message.getFieldWithDefault(msg, 3, "")
1229+
hasUserLevel: jspb.Message.getFieldWithDefault(msg, 3, ""),
1230+
hasMoreResources: jspb.Message.getBooleanFieldWithDefault(msg, 4, false)
12291231
};
12301232

12311233
if (includeInstance) {
@@ -1276,6 +1278,10 @@ proto.workspacemanagerbridge.AdmissionConstraint.deserializeBinaryFromReader = f
12761278
var value = /** @type {string} */ (reader.readString());
12771279
msg.setHasUserLevel(value);
12781280
break;
1281+
case 4:
1282+
var value = /** @type {boolean} */ (reader.readBool());
1283+
msg.setHasMoreResources(value);
1284+
break;
12791285
default:
12801286
reader.skipField();
12811287
break;
@@ -1328,6 +1334,13 @@ proto.workspacemanagerbridge.AdmissionConstraint.serializeBinaryToWriter = funct
13281334
f
13291335
);
13301336
}
1337+
f = /** @type {boolean} */ (jspb.Message.getField(message, 4));
1338+
if (f != null) {
1339+
writer.writeBool(
1340+
4,
1341+
f
1342+
);
1343+
}
13311344
};
13321345

13331346

@@ -1672,6 +1685,42 @@ proto.workspacemanagerbridge.AdmissionConstraint.prototype.hasHasUserLevel = fun
16721685
};
16731686

16741687

1688+
/**
1689+
* optional bool has_more_resources = 4;
1690+
* @return {boolean}
1691+
*/
1692+
proto.workspacemanagerbridge.AdmissionConstraint.prototype.getHasMoreResources = function() {
1693+
return /** @type {boolean} */ (jspb.Message.getBooleanFieldWithDefault(this, 4, false));
1694+
};
1695+
1696+
1697+
/**
1698+
* @param {boolean} value
1699+
* @return {!proto.workspacemanagerbridge.AdmissionConstraint} returns this
1700+
*/
1701+
proto.workspacemanagerbridge.AdmissionConstraint.prototype.setHasMoreResources = function(value) {
1702+
return jspb.Message.setOneofField(this, 4, proto.workspacemanagerbridge.AdmissionConstraint.oneofGroups_[0], value);
1703+
};
1704+
1705+
1706+
/**
1707+
* Clears the field making it undefined.
1708+
* @return {!proto.workspacemanagerbridge.AdmissionConstraint} returns this
1709+
*/
1710+
proto.workspacemanagerbridge.AdmissionConstraint.prototype.clearHasMoreResources = function() {
1711+
return jspb.Message.setOneofField(this, 4, proto.workspacemanagerbridge.AdmissionConstraint.oneofGroups_[0], undefined);
1712+
};
1713+
1714+
1715+
/**
1716+
* Returns whether this field is set.
1717+
* @return {boolean}
1718+
*/
1719+
proto.workspacemanagerbridge.AdmissionConstraint.prototype.hasHasMoreResources = function() {
1720+
return jspb.Message.getField(this, 4) != null;
1721+
};
1722+
1723+
16751724

16761725
/**
16771726
* List of repeated fields within this message type.

components/ws-manager-bridge/src/cluster-service-server.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import { WorkspaceDB } from '@gitpod/gitpod-db/lib/workspace-db';
88
import { Queue } from '@gitpod/gitpod-protocol';
99
import { log } from '@gitpod/gitpod-protocol/lib/util/logging';
10-
import { WorkspaceCluster, WorkspaceClusterDB, WorkspaceClusterState, TLSConfig, AdmissionConstraint, AdmissionConstraintHasRole, WorkspaceClusterWoTLS, AdmissionConstraintHasUserLevel } from '@gitpod/gitpod-protocol/lib/workspace-cluster';
10+
import { WorkspaceCluster, WorkspaceClusterDB, WorkspaceClusterState, TLSConfig, AdmissionConstraint, AdmissionConstraintHasRole, WorkspaceClusterWoTLS, AdmissionConstraintHasUserLevel, AdmissionConstraintHasMoreResources } from '@gitpod/gitpod-protocol/lib/workspace-cluster';
1111
import {
1212
ClusterServiceService,
1313
ClusterState,
@@ -188,6 +188,8 @@ export class ClusterService implements IClusterServiceServer {
188188
if (v.level === (c as AdmissionConstraintHasUserLevel).level) {
189189
return false;
190190
}
191+
case "has-more-resources":
192+
return false;
191193
}
192194
return true;
193195
})
@@ -288,6 +290,8 @@ function convertToGRPC(ws: WorkspaceClusterWoTLS): ClusterStatus {
288290
break;
289291
case "has-user-level":
290292
constraint.setHasUserLevel(c.level);
293+
case "has-more-resources":
294+
constraint.setHasMoreResources(true);
291295
default:
292296
return;
293297
}
@@ -319,6 +323,9 @@ function mapAdmissionConstraint(c: GRPCAdmissionConstraint | undefined): Admissi
319323
}
320324
return <AdmissionConstraintHasUserLevel>{type: "has-user-level", level };
321325
}
326+
if (c.hasHasMoreResources()) {
327+
return <AdmissionConstraintHasMoreResources>{type: "has-more-resources"};
328+
}
322329
return;
323330
}
324331

dev/gpctl/cmd/clusters-update.go

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ var clustersUpdateMaxScoreCmd = &cobra.Command{
8787
}
8888

8989
var clustersUpdateAdmissionConstraintCmd = &cobra.Command{
90-
Use: "admission-constraint add|remove has-feature-preview|has-permission=<permission>|has-user-level=<level>",
90+
Use: "admission-constraint add|remove has-feature-preview|has-permission=<permission>|has-user-level=<level>|has-more-resources",
9191
Short: "Updates a cluster's admission constraints",
9292
Args: cobra.ExactArgs(2),
9393
Run: func(cmd *cobra.Command, args []string) {
@@ -137,6 +137,17 @@ var clustersUpdateAdmissionConstraintCmd = &cobra.Command{
137137
},
138138
},
139139
}
140+
} else if strings.HasPrefix(args[1], "has-more-resources") {
141+
request.Property = &api.UpdateRequest_AdmissionConstraint{
142+
AdmissionConstraint: &api.ModifyAdmissionConstraint{
143+
Add: add,
144+
Constraint: &api.AdmissionConstraint{
145+
Constraint: &api.AdmissionConstraint_HasMoreResources{
146+
HasMoreResources: true,
147+
},
148+
},
149+
},
150+
}
140151
} else {
141152
log.Fatalf("unknown constraint: %s", args[1])
142153
}

0 commit comments

Comments
 (0)