@mcpg-dev/pulumi 0.1.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BUILD.bazel +24 -0
- package/README.md +169 -0
- package/bin/cluster.d.ts +44 -0
- package/bin/cluster.js +80 -0
- package/bin/config.d.ts +30 -0
- package/bin/config.js +22 -0
- package/bin/config.test.d.ts +1 -0
- package/bin/config.test.js +36 -0
- package/bin/gateway.d.ts +52 -0
- package/bin/gateway.js +90 -0
- package/bin/index.d.ts +11 -0
- package/bin/index.js +27 -0
- package/bin/mcpgStack.d.ts +18 -0
- package/bin/mcpgStack.js +58 -0
- package/bin/oci.d.ts +8 -0
- package/bin/oci.js +41 -0
- package/bin/operator.d.ts +28 -0
- package/bin/operator.js +80 -0
- package/bin/pluginSet.d.ts +16 -0
- package/bin/pluginSet.js +55 -0
- package/bin/route.d.ts +35 -0
- package/bin/route.js +64 -0
- package/bin/tenant.d.ts +32 -0
- package/bin/tenant.js +95 -0
- package/bin/tenantCr.d.ts +32 -0
- package/bin/tenantCr.js +65 -0
- package/bin/trustBootstrap.d.ts +21 -0
- package/bin/trustBootstrap.js +56 -0
- package/copy.bara.sky +98 -0
- package/package.json +22 -0
- package/src/cluster.ts +75 -0
- package/src/config.test.ts +36 -0
- package/src/config.ts +44 -0
- package/src/gateway.ts +91 -0
- package/src/index.ts +11 -0
- package/src/mcpgStack.ts +37 -0
- package/src/oci.ts +40 -0
- package/src/operator.ts +65 -0
- package/src/pluginSet.ts +33 -0
- package/src/route.ts +45 -0
- package/src/tenant.ts +79 -0
- package/src/tenantCr.ts +45 -0
- package/src/trustBootstrap.ts +40 -0
- package/tsconfig.json +15 -0
package/bin/mcpgStack.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.McpgStack = void 0;
|
|
37
|
+
const pulumi = __importStar(require("@pulumi/pulumi"));
|
|
38
|
+
const operator_1 = require("./operator");
|
|
39
|
+
const gateway_1 = require("./gateway");
|
|
40
|
+
const trustBootstrap_1 = require("./trustBootstrap");
|
|
41
|
+
/** Convenience composition: operator + cluster trust + one gateway. */
|
|
42
|
+
class McpgStack extends pulumi.ComponentResource {
|
|
43
|
+
constructor(name, args, opts) {
|
|
44
|
+
super("mcpg:index:McpgStack", name, {}, opts);
|
|
45
|
+
this.operator = new operator_1.Operator(`${name}-operator`, args.operator, { parent: this });
|
|
46
|
+
if (args.trust !== false) {
|
|
47
|
+
new trustBootstrap_1.TrustBootstrap(`${name}-trust`, {}, { parent: this, dependsOn: this.operator });
|
|
48
|
+
}
|
|
49
|
+
if (args.gateway) {
|
|
50
|
+
this.gateway = new gateway_1.Gateway(`${name}-gateway`, {
|
|
51
|
+
...args.gateway,
|
|
52
|
+
namespace: args.gateway.namespace ?? this.operator.namespace,
|
|
53
|
+
}, { parent: this, dependsOn: this.operator });
|
|
54
|
+
}
|
|
55
|
+
this.registerOutputs({});
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.McpgStack = McpgStack;
|
package/bin/oci.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** The resolved `<host>/<namespace>[/<path>]` base. */
|
|
2
|
+
export declare function ociBase(env?: NodeJS.ProcessEnv): string;
|
|
3
|
+
/** Helm OCI repository the charts publish to (`repositoryOpts.repo`). */
|
|
4
|
+
export declare function ociChartRepo(env?: NodeJS.ProcessEnv): string;
|
|
5
|
+
/** Container image repository for a project's `release.docker.imageName`. */
|
|
6
|
+
export declare function ociImageRepo(imageName: string, env?: NodeJS.ProcessEnv): string;
|
|
7
|
+
/** Registry a bare `oci:` plugin reference resolves against. */
|
|
8
|
+
export declare function ociPluginRegistry(env?: NodeJS.ProcessEnv): string;
|
package/bin/oci.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// Registry coordinates every MCPG artefact hangs off. The defaults mirror the
|
|
3
|
+
// `internal` channel of tools/release/oci-registry.json — the manifest the
|
|
4
|
+
// publish steps read — and tools/ci/selftest-oci-registry.sh asserts the two
|
|
5
|
+
// still agree.
|
|
6
|
+
//
|
|
7
|
+
// A Pulumi program overrides per component (`chartRepo`, an explicit image
|
|
8
|
+
// repository) or, for a whole stack, through the same environment contract the
|
|
9
|
+
// shell and Node publish helpers honour:
|
|
10
|
+
//
|
|
11
|
+
// MCPG_OCI_HOST registry host (default: ghcr.io)
|
|
12
|
+
// MCPG_OCI_NAMESPACE org / user segment (default: mcpg-dev)
|
|
13
|
+
// MCPG_OCI_PATH repository path segment (default: source-code)
|
|
14
|
+
//
|
|
15
|
+
// MCPG_OCI_PATH set-but-empty means "no path segment" — the shape the public
|
|
16
|
+
// channel takes — so it is read by presence, not by truthiness.
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.ociBase = ociBase;
|
|
19
|
+
exports.ociChartRepo = ociChartRepo;
|
|
20
|
+
exports.ociImageRepo = ociImageRepo;
|
|
21
|
+
exports.ociPluginRegistry = ociPluginRegistry;
|
|
22
|
+
const trim = (s) => s.replace(/^\/+|\/+$/g, "");
|
|
23
|
+
/** The resolved `<host>/<namespace>[/<path>]` base. */
|
|
24
|
+
function ociBase(env = process.env) {
|
|
25
|
+
const host = trim(env.MCPG_OCI_HOST ?? "ghcr.io");
|
|
26
|
+
const namespace = trim(env.MCPG_OCI_NAMESPACE ?? "mcpg-dev");
|
|
27
|
+
const path = trim("MCPG_OCI_PATH" in env ? (env.MCPG_OCI_PATH ?? "") : "source-code");
|
|
28
|
+
return [host, namespace, path].filter(Boolean).join("/");
|
|
29
|
+
}
|
|
30
|
+
/** Helm OCI repository the charts publish to (`repositoryOpts.repo`). */
|
|
31
|
+
function ociChartRepo(env = process.env) {
|
|
32
|
+
return `oci://${ociBase(env)}/charts`;
|
|
33
|
+
}
|
|
34
|
+
/** Container image repository for a project's `release.docker.imageName`. */
|
|
35
|
+
function ociImageRepo(imageName, env = process.env) {
|
|
36
|
+
return `${ociBase(env)}/${trim(imageName)}`;
|
|
37
|
+
}
|
|
38
|
+
/** Registry a bare `oci:` plugin reference resolves against. */
|
|
39
|
+
function ociPluginRegistry(env = process.env) {
|
|
40
|
+
return `${ociBase(env)}/plugins`;
|
|
41
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
2
|
+
import * as k8s from "@pulumi/kubernetes";
|
|
3
|
+
export interface OperatorArgs {
|
|
4
|
+
namespace?: pulumi.Input<string>;
|
|
5
|
+
chartVersion: pulumi.Input<string>;
|
|
6
|
+
chartName?: pulumi.Input<string>;
|
|
7
|
+
/** Helm repository. Unset composes `oci://<ociBase()>/charts`. */
|
|
8
|
+
chartRepo?: pulumi.Input<string>;
|
|
9
|
+
/** Path to the split-by-kind CRD YAMLs (the generated schema snapshot). */
|
|
10
|
+
crdsDir?: string;
|
|
11
|
+
/** Restrict the operator to a single namespace (operator.watchNamespace → --watch-namespace). */
|
|
12
|
+
watchNamespace?: pulumi.Input<string>;
|
|
13
|
+
/** Extra chart values deep-merged last. */
|
|
14
|
+
values?: {
|
|
15
|
+
[key: string]: any;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Installs the MCPG operator via Helm with the CRDs managed as first-class
|
|
20
|
+
* resources (chart `crd.install=false`) so they upgrade independently — closing
|
|
21
|
+
* the Helm-doesn't-upgrade-CRDs hazard. Pulumi's K8s provider does SSA by
|
|
22
|
+
* default and awaits readiness.
|
|
23
|
+
*/
|
|
24
|
+
export declare class Operator extends pulumi.ComponentResource {
|
|
25
|
+
readonly namespace: pulumi.Output<string>;
|
|
26
|
+
readonly chart: k8s.helm.v4.Chart;
|
|
27
|
+
constructor(name: string, args: OperatorArgs, opts?: pulumi.ComponentResourceOptions);
|
|
28
|
+
}
|
package/bin/operator.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.Operator = void 0;
|
|
37
|
+
const pulumi = __importStar(require("@pulumi/pulumi"));
|
|
38
|
+
const k8s = __importStar(require("@pulumi/kubernetes"));
|
|
39
|
+
const oci_1 = require("./oci");
|
|
40
|
+
/**
|
|
41
|
+
* Installs the MCPG operator via Helm with the CRDs managed as first-class
|
|
42
|
+
* resources (chart `crd.install=false`) so they upgrade independently — closing
|
|
43
|
+
* the Helm-doesn't-upgrade-CRDs hazard. Pulumi's K8s provider does SSA by
|
|
44
|
+
* default and awaits readiness.
|
|
45
|
+
*/
|
|
46
|
+
class Operator extends pulumi.ComponentResource {
|
|
47
|
+
constructor(name, args, opts) {
|
|
48
|
+
super("mcpg:index:Operator", name, {}, opts);
|
|
49
|
+
const ns = pulumi.output(args.namespace ?? "mcpg-system");
|
|
50
|
+
const crdsDir = args.crdsDir ?? "../../codegen/schemas/v1alpha1/crds";
|
|
51
|
+
const crds = new k8s.yaml.v2.ConfigGroup(`${name}-crds`, {
|
|
52
|
+
files: [`${crdsDir}/*.yaml`],
|
|
53
|
+
}, { parent: this });
|
|
54
|
+
this.chart = new k8s.helm.v4.Chart(name, {
|
|
55
|
+
chart: args.chartName ?? "mcpg-operator",
|
|
56
|
+
version: args.chartVersion,
|
|
57
|
+
namespace: ns,
|
|
58
|
+
repositoryOpts: {
|
|
59
|
+
repo: args.chartRepo ?? (0, oci_1.ociChartRepo)(),
|
|
60
|
+
},
|
|
61
|
+
// The chart ships CRDs under crds/ (Helm install-only, value-ungated);
|
|
62
|
+
// the ConfigGroup above owns them as first-class resources, so skip the
|
|
63
|
+
// chart's copy to avoid two Pulumi resources managing the same CRDs.
|
|
64
|
+
skipCrds: true,
|
|
65
|
+
// Secure default: the admission webhook fails closed, so it needs real
|
|
66
|
+
// TLS. cert-manager templates a self-signed Issuer + Certificate and
|
|
67
|
+
// injects the caBundle. Requires cert-manager in the cluster; override
|
|
68
|
+
// via values.certManager (e.g. { enabled: false } for BYO TLS Secret).
|
|
69
|
+
values: {
|
|
70
|
+
crd: { install: false },
|
|
71
|
+
certManager: { enabled: true },
|
|
72
|
+
...(args.watchNamespace ? { operator: { watchNamespace: args.watchNamespace } } : {}),
|
|
73
|
+
...(args.values ?? {}),
|
|
74
|
+
},
|
|
75
|
+
}, { parent: this, dependsOn: crds });
|
|
76
|
+
this.namespace = ns;
|
|
77
|
+
this.registerOutputs({ namespace: this.namespace });
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
exports.Operator = Operator;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
2
|
+
import { mcpg } from "@mcpg-dev/pulumi-crds";
|
|
3
|
+
export interface PluginSetArgs {
|
|
4
|
+
namespace: pulumi.Input<string>;
|
|
5
|
+
entries: any[];
|
|
6
|
+
capabilityGrants?: any[];
|
|
7
|
+
labels?: {
|
|
8
|
+
[key: string]: string;
|
|
9
|
+
};
|
|
10
|
+
resourceName?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare class PluginSet extends pulumi.ComponentResource {
|
|
13
|
+
readonly pluginSet: mcpg.v1alpha1.MCPGPluginSet;
|
|
14
|
+
readonly name: pulumi.Output<string>;
|
|
15
|
+
constructor(name: string, args: PluginSetArgs, opts?: pulumi.ComponentResourceOptions);
|
|
16
|
+
}
|
package/bin/pluginSet.js
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.PluginSet = void 0;
|
|
37
|
+
const pulumi = __importStar(require("@pulumi/pulumi"));
|
|
38
|
+
const pulumi_crds_1 = require("@mcpg-dev/pulumi-crds");
|
|
39
|
+
class PluginSet extends pulumi.ComponentResource {
|
|
40
|
+
constructor(name, args, opts) {
|
|
41
|
+
super("mcpg:index:PluginSet", name, {}, opts);
|
|
42
|
+
const psName = args.resourceName ?? name;
|
|
43
|
+
const spec = { entries: args.entries };
|
|
44
|
+
if (args.capabilityGrants && args.capabilityGrants.length > 0) {
|
|
45
|
+
spec.capabilityGrants = args.capabilityGrants;
|
|
46
|
+
}
|
|
47
|
+
this.pluginSet = new pulumi_crds_1.mcpg.v1alpha1.MCPGPluginSet(psName, {
|
|
48
|
+
metadata: { name: psName, namespace: args.namespace, labels: args.labels },
|
|
49
|
+
spec: spec,
|
|
50
|
+
}, { parent: this });
|
|
51
|
+
this.name = pulumi.output(psName);
|
|
52
|
+
this.registerOutputs({ name: this.name });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
exports.PluginSet = PluginSet;
|
package/bin/route.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
2
|
+
import { mcpg } from "@mcpg-dev/pulumi-crds";
|
|
3
|
+
export interface RouteArgs {
|
|
4
|
+
namespace: pulumi.Input<string>;
|
|
5
|
+
/** Shared gateway this route binds into: { name } (non-empty). */
|
|
6
|
+
gatewayRef: {
|
|
7
|
+
name: string;
|
|
8
|
+
};
|
|
9
|
+
/** Tool matcher: { tools: [{ id }] } — at least one unique, non-empty id. */
|
|
10
|
+
match: {
|
|
11
|
+
tools: {
|
|
12
|
+
id: string;
|
|
13
|
+
}[];
|
|
14
|
+
};
|
|
15
|
+
identityChain?: string[];
|
|
16
|
+
policyChain?: string[];
|
|
17
|
+
auditChain?: string[];
|
|
18
|
+
/** e.g. { tenant: "team-a" }. Omit only for a single-tenant gateway (else reachable by any caller). */
|
|
19
|
+
attributes?: {
|
|
20
|
+
[key: string]: any;
|
|
21
|
+
};
|
|
22
|
+
labels?: {
|
|
23
|
+
[key: string]: string;
|
|
24
|
+
};
|
|
25
|
+
resourceName?: string;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* An MCPGRoute (namespaced): binds a tenant's tool subset into a SHARED gateway
|
|
29
|
+
* with identity/policy/audit chains — the soft-multi-tenancy primitive.
|
|
30
|
+
*/
|
|
31
|
+
export declare class Route extends pulumi.ComponentResource {
|
|
32
|
+
readonly route: mcpg.v1alpha1.MCPGRoute;
|
|
33
|
+
readonly name: pulumi.Output<string>;
|
|
34
|
+
constructor(name: string, args: RouteArgs, opts?: pulumi.ComponentResourceOptions);
|
|
35
|
+
}
|
package/bin/route.js
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.Route = void 0;
|
|
37
|
+
const pulumi = __importStar(require("@pulumi/pulumi"));
|
|
38
|
+
const pulumi_crds_1 = require("@mcpg-dev/pulumi-crds");
|
|
39
|
+
/**
|
|
40
|
+
* An MCPGRoute (namespaced): binds a tenant's tool subset into a SHARED gateway
|
|
41
|
+
* with identity/policy/audit chains — the soft-multi-tenancy primitive.
|
|
42
|
+
*/
|
|
43
|
+
class Route extends pulumi.ComponentResource {
|
|
44
|
+
constructor(name, args, opts) {
|
|
45
|
+
super("mcpg:index:Route", name, {}, opts);
|
|
46
|
+
const rName = args.resourceName ?? name;
|
|
47
|
+
const spec = { gatewayRef: args.gatewayRef, match: args.match };
|
|
48
|
+
if (args.identityChain && args.identityChain.length > 0)
|
|
49
|
+
spec.identityChain = args.identityChain;
|
|
50
|
+
if (args.policyChain && args.policyChain.length > 0)
|
|
51
|
+
spec.policyChain = args.policyChain;
|
|
52
|
+
if (args.auditChain && args.auditChain.length > 0)
|
|
53
|
+
spec.auditChain = args.auditChain;
|
|
54
|
+
if (args.attributes)
|
|
55
|
+
spec.attributes = args.attributes;
|
|
56
|
+
this.route = new pulumi_crds_1.mcpg.v1alpha1.MCPGRoute(rName, {
|
|
57
|
+
metadata: { name: rName, namespace: args.namespace, labels: args.labels },
|
|
58
|
+
spec: spec,
|
|
59
|
+
}, { parent: this });
|
|
60
|
+
this.name = pulumi.output(rName);
|
|
61
|
+
this.registerOutputs({ name: this.name });
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.Route = Route;
|
package/bin/tenant.d.ts
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
2
|
+
import { Gateway, GatewayArgs } from "./gateway";
|
|
3
|
+
import { PluginSet } from "./pluginSet";
|
|
4
|
+
export interface TenantArgs {
|
|
5
|
+
tenantName: string;
|
|
6
|
+
namespace?: string;
|
|
7
|
+
labels?: {
|
|
8
|
+
[key: string]: string;
|
|
9
|
+
};
|
|
10
|
+
/** Default true → default-deny cross-tenant ingress NetworkPolicy. */
|
|
11
|
+
networkPolicy?: boolean;
|
|
12
|
+
pluginSet?: {
|
|
13
|
+
entries: any[];
|
|
14
|
+
capabilityGrants?: any[];
|
|
15
|
+
};
|
|
16
|
+
gateway?: Omit<GatewayArgs, "namespace">;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* One tenant as an imperative fan-out: namespace + NetworkPolicy isolation +
|
|
20
|
+
* (optional) plugin-set + gateway. Instantiate in a loop to fan out a fleet.
|
|
21
|
+
*
|
|
22
|
+
* NB: this does NOT create an MCPGTenant CR, so it does NOT engage the
|
|
23
|
+
* operator's tenant GOVERNANCE (plugin allowlist, ResourceQuota, replica caps,
|
|
24
|
+
* exclusive namespace ownership). For declarative governance use {@link TenantCR}
|
|
25
|
+
* (the MCPGTenant CR) — alongside or instead of this helper.
|
|
26
|
+
*/
|
|
27
|
+
export declare class Tenant extends pulumi.ComponentResource {
|
|
28
|
+
readonly namespace: pulumi.Output<string>;
|
|
29
|
+
readonly gateway?: Gateway;
|
|
30
|
+
readonly pluginSet?: PluginSet;
|
|
31
|
+
constructor(name: string, args: TenantArgs, opts?: pulumi.ComponentResourceOptions);
|
|
32
|
+
}
|
package/bin/tenant.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.Tenant = void 0;
|
|
37
|
+
const pulumi = __importStar(require("@pulumi/pulumi"));
|
|
38
|
+
const k8s = __importStar(require("@pulumi/kubernetes"));
|
|
39
|
+
const gateway_1 = require("./gateway");
|
|
40
|
+
const pluginSet_1 = require("./pluginSet");
|
|
41
|
+
/**
|
|
42
|
+
* One tenant as an imperative fan-out: namespace + NetworkPolicy isolation +
|
|
43
|
+
* (optional) plugin-set + gateway. Instantiate in a loop to fan out a fleet.
|
|
44
|
+
*
|
|
45
|
+
* NB: this does NOT create an MCPGTenant CR, so it does NOT engage the
|
|
46
|
+
* operator's tenant GOVERNANCE (plugin allowlist, ResourceQuota, replica caps,
|
|
47
|
+
* exclusive namespace ownership). For declarative governance use {@link TenantCR}
|
|
48
|
+
* (the MCPGTenant CR) — alongside or instead of this helper.
|
|
49
|
+
*/
|
|
50
|
+
class Tenant extends pulumi.ComponentResource {
|
|
51
|
+
constructor(name, args, opts) {
|
|
52
|
+
super("mcpg:index:Tenant", name, {}, opts);
|
|
53
|
+
const nsName = args.namespace ?? args.tenantName;
|
|
54
|
+
const ns = new k8s.core.v1.Namespace(`${name}-ns`, {
|
|
55
|
+
metadata: {
|
|
56
|
+
name: nsName,
|
|
57
|
+
labels: {
|
|
58
|
+
"app.kubernetes.io/managed-by": "pulumi-mcpg",
|
|
59
|
+
"mcpg.dev/tenant": args.tenantName,
|
|
60
|
+
...(args.labels ?? {}),
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
}, { parent: this });
|
|
64
|
+
if (args.networkPolicy !== false) {
|
|
65
|
+
new k8s.networking.v1.NetworkPolicy(`${name}-isolation`, {
|
|
66
|
+
metadata: { name: "mcpg-tenant-isolation", namespace: nsName },
|
|
67
|
+
spec: {
|
|
68
|
+
podSelector: {},
|
|
69
|
+
policyTypes: ["Ingress"],
|
|
70
|
+
ingress: [{ from: [{ namespaceSelector: { matchLabels: { "mcpg.dev/tenant": args.tenantName } } }] }],
|
|
71
|
+
},
|
|
72
|
+
}, { parent: this, dependsOn: ns });
|
|
73
|
+
}
|
|
74
|
+
const setName = `${args.tenantName}-set`;
|
|
75
|
+
if (args.pluginSet) {
|
|
76
|
+
this.pluginSet = new pluginSet_1.PluginSet(`${name}-set`, {
|
|
77
|
+
namespace: nsName,
|
|
78
|
+
entries: args.pluginSet.entries,
|
|
79
|
+
capabilityGrants: args.pluginSet.capabilityGrants,
|
|
80
|
+
resourceName: setName,
|
|
81
|
+
}, { parent: this, dependsOn: ns });
|
|
82
|
+
}
|
|
83
|
+
if (args.gateway) {
|
|
84
|
+
this.gateway = new gateway_1.Gateway(`${name}-gw`, {
|
|
85
|
+
...args.gateway,
|
|
86
|
+
namespace: nsName,
|
|
87
|
+
pluginSetRef: args.pluginSet ? setName : args.gateway.pluginSetRef,
|
|
88
|
+
resourceName: args.gateway.resourceName ?? args.tenantName,
|
|
89
|
+
}, { parent: this, dependsOn: ns });
|
|
90
|
+
}
|
|
91
|
+
this.namespace = pulumi.output(nsName);
|
|
92
|
+
this.registerOutputs({ namespace: this.namespace });
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
exports.Tenant = Tenant;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
2
|
+
import { mcpg } from "@mcpg-dev/pulumi-crds";
|
|
3
|
+
export interface TenantCRArgs {
|
|
4
|
+
/** Namespaces this tenant owns (non-empty, unique). */
|
|
5
|
+
namespaces: string[];
|
|
6
|
+
/** Plugin allowlist: [{ name? , registryPrefix? }] (each sets ≥1 matcher; [] = deny-all). */
|
|
7
|
+
allowedPlugins?: any[];
|
|
8
|
+
/** { maxGateways?, maxPluginSets?, maxRoutes?, maxReplicasPerGateway? } — each ≥ 0. */
|
|
9
|
+
quotas?: {
|
|
10
|
+
[key: string]: number;
|
|
11
|
+
};
|
|
12
|
+
/** { key, ... } — key non-empty when set. */
|
|
13
|
+
identityAttribute?: {
|
|
14
|
+
[key: string]: any;
|
|
15
|
+
};
|
|
16
|
+
labels?: {
|
|
17
|
+
[key: string]: string;
|
|
18
|
+
};
|
|
19
|
+
resourceName?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* An MCPGTenant (cluster-scoped): the DECLARATIVE tenant governance boundary
|
|
23
|
+
* — plugin allowlist, per-namespace ResourceQuota, replica caps, and
|
|
24
|
+
* exclusive namespace ownership. Distinct from the {@link Tenant} component,
|
|
25
|
+
* which is an imperative namespace+RBAC+NetworkPolicy fan-out that does NOT
|
|
26
|
+
* engage tenant governance.
|
|
27
|
+
*/
|
|
28
|
+
export declare class TenantCR extends pulumi.ComponentResource {
|
|
29
|
+
readonly tenant: mcpg.v1alpha1.MCPGTenant;
|
|
30
|
+
readonly name: pulumi.Output<string>;
|
|
31
|
+
constructor(name: string, args: TenantCRArgs, opts?: pulumi.ComponentResourceOptions);
|
|
32
|
+
}
|
package/bin/tenantCr.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.TenantCR = void 0;
|
|
37
|
+
const pulumi = __importStar(require("@pulumi/pulumi"));
|
|
38
|
+
const pulumi_crds_1 = require("@mcpg-dev/pulumi-crds");
|
|
39
|
+
/**
|
|
40
|
+
* An MCPGTenant (cluster-scoped): the DECLARATIVE tenant governance boundary
|
|
41
|
+
* — plugin allowlist, per-namespace ResourceQuota, replica caps, and
|
|
42
|
+
* exclusive namespace ownership. Distinct from the {@link Tenant} component,
|
|
43
|
+
* which is an imperative namespace+RBAC+NetworkPolicy fan-out that does NOT
|
|
44
|
+
* engage tenant governance.
|
|
45
|
+
*/
|
|
46
|
+
class TenantCR extends pulumi.ComponentResource {
|
|
47
|
+
constructor(name, args, opts) {
|
|
48
|
+
super("mcpg:index:TenantCR", name, {}, opts);
|
|
49
|
+
const tName = args.resourceName ?? name;
|
|
50
|
+
const spec = { namespaces: args.namespaces };
|
|
51
|
+
if (args.allowedPlugins && args.allowedPlugins.length > 0)
|
|
52
|
+
spec.allowedPlugins = args.allowedPlugins;
|
|
53
|
+
if (args.quotas)
|
|
54
|
+
spec.quotas = args.quotas;
|
|
55
|
+
if (args.identityAttribute)
|
|
56
|
+
spec.identityAttribute = args.identityAttribute;
|
|
57
|
+
this.tenant = new pulumi_crds_1.mcpg.v1alpha1.MCPGTenant(tName, {
|
|
58
|
+
metadata: { name: tName, labels: args.labels },
|
|
59
|
+
spec: spec,
|
|
60
|
+
}, { parent: this });
|
|
61
|
+
this.name = pulumi.output(tName);
|
|
62
|
+
this.registerOutputs({ name: this.name });
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
exports.TenantCR = TenantCR;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
2
|
+
import { mcpg } from "@mcpg-dev/pulumi-crds";
|
|
3
|
+
export interface SecretRef {
|
|
4
|
+
name: string;
|
|
5
|
+
key: string;
|
|
6
|
+
}
|
|
7
|
+
export interface TrustBootstrapArgs {
|
|
8
|
+
revocationListName?: string;
|
|
9
|
+
revocations?: any[];
|
|
10
|
+
issuedAt?: string;
|
|
11
|
+
/** Signing-key Secret reference, passed through to plugin trust. Bytes are
|
|
12
|
+
* never read into state (the no-secret-in-state invariant). */
|
|
13
|
+
signingKeySecretRef?: SecretRef;
|
|
14
|
+
}
|
|
15
|
+
/** Seeds the cluster-default MCPGRevocationList and carries the signing-key ref. */
|
|
16
|
+
export declare class TrustBootstrap extends pulumi.ComponentResource {
|
|
17
|
+
readonly revocationList: mcpg.v1alpha1.MCPGRevocationList;
|
|
18
|
+
readonly revocationListName: pulumi.Output<string>;
|
|
19
|
+
readonly signingKeySecretRef?: SecretRef;
|
|
20
|
+
constructor(name: string, args?: TrustBootstrapArgs, opts?: pulumi.ComponentResourceOptions);
|
|
21
|
+
}
|