mirror of
https://github.com/holos-run/holos.git
synced 2026-03-19 00:37:45 +00:00
Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6894f45b6c | ||
|
|
89d25be837 | ||
|
|
5b33e48552 |
@@ -18,6 +18,7 @@ import "encoding/yaml"
|
||||
Issuer?: [Name=_]: #Issuer & {metadata: name: Name}
|
||||
Gateway?: [Name=_]: #Gateway & {metadata: name: Name}
|
||||
ConfigMap?: [Name=_]: #ConfigMap & {metadata: name: Name}
|
||||
ServiceAccount?: [Name=_]: #ServiceAccount & {metadata: name: Name}
|
||||
|
||||
Deployment?: [_]: #Deployment
|
||||
StatefulSet?: [_]: #StatefulSet
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
package holos
|
||||
|
||||
let Namespace = "dev-holos"
|
||||
let Holos = "holos"
|
||||
|
||||
// spec represents the output provided to holos
|
||||
spec: components: KubernetesObjectsList: [
|
||||
#KubernetesObjects & {
|
||||
metadata: name: "dev-holos-app"
|
||||
apiObjectMap: OBJECTS.apiObjectMap
|
||||
},
|
||||
]
|
||||
|
||||
// OBJECTS represents the kubernetes api objects to manage.
|
||||
let OBJECTS = #APIObjects & {
|
||||
apiObjects: Deployment: holos: {
|
||||
metadata: {
|
||||
name: Holos
|
||||
namespace: Namespace
|
||||
labels: app: Holos
|
||||
}
|
||||
spec: {
|
||||
selector: matchLabels: app: Holos
|
||||
template: metadata: labels: {
|
||||
app: Holos
|
||||
"sidecar.istio.io/inject": "true"
|
||||
}
|
||||
strategy: rollingUpdate: maxSurge: 1
|
||||
strategy: rollingUpdate: maxUnavailable: 0
|
||||
template: {
|
||||
spec: {
|
||||
serviceAccountName: Holos
|
||||
securityContext: seccompProfile: type: "RuntimeDefault"
|
||||
containers: [
|
||||
{
|
||||
name: Holos
|
||||
image: "271053619184.dkr.ecr.us-east-2.amazonaws.com/holos-run/holos-server/holos:0.73.0"
|
||||
imagePullPolicy: "Always"
|
||||
env: [
|
||||
{
|
||||
name: "TZ"
|
||||
value: "America/Los_Angeles"
|
||||
},
|
||||
{
|
||||
name: "DATABASE_URL"
|
||||
valueFrom: secretKeyRef: {
|
||||
key: "uri"
|
||||
name: "holos-pguser-holos"
|
||||
}
|
||||
},
|
||||
]
|
||||
ports: [
|
||||
{
|
||||
containerPort: 3000
|
||||
name: "http"
|
||||
protocol: "TCP"
|
||||
},
|
||||
]
|
||||
securityContext: capabilities: drop: ["ALL"]
|
||||
securityContext: allowPrivilegeEscalation: false
|
||||
securityContext: runAsNonRoot: true
|
||||
resources: limits: {
|
||||
cpu: "0.25"
|
||||
memory: "256Mi"
|
||||
}
|
||||
resources: requests: resources.limits
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,129 @@
|
||||
package holos
|
||||
|
||||
let Namespace = "dev-holos"
|
||||
let Holos = "holos"
|
||||
|
||||
// spec represents the output provided to holos
|
||||
spec: components: KubernetesObjectsList: [
|
||||
#KubernetesObjects & {
|
||||
metadata: name: "dev-holos-infra"
|
||||
apiObjectMap: OBJECTS.apiObjectMap
|
||||
},
|
||||
]
|
||||
|
||||
let Metadata = {
|
||||
name: Holos
|
||||
namespace: Namespace
|
||||
labels: app: Holos
|
||||
}
|
||||
|
||||
// OBJECTS represents the kubernetes api objects to manage.
|
||||
let OBJECTS = #APIObjects & {
|
||||
// Postgres
|
||||
// Deployment
|
||||
// VirtualService
|
||||
|
||||
apiObjects: ServiceAccount: holos: {
|
||||
metadata: Metadata
|
||||
imagePullSecrets: [{name: "kube-system-ecr-image-pull-creds"}]
|
||||
}
|
||||
|
||||
apiObjects: PostgresCluster: holos: {
|
||||
apiVersion: "postgres-operator.crunchydata.com/v1beta1"
|
||||
metadata: Metadata
|
||||
spec: {
|
||||
image: "registry.developers.crunchydata.com/crunchydata/crunchy-postgres:ubi8-16.1-0"
|
||||
instances: [{
|
||||
affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: [{
|
||||
podAffinityTerm: {
|
||||
labelSelector: matchLabels: "postgres-operator.crunchydata.com/cluster": "holos"
|
||||
topologyKey: "kubernetes.io/hostname"
|
||||
}
|
||||
weight: 1
|
||||
}]
|
||||
dataVolumeClaimSpec: {
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources: requests: storage: "1Gi"
|
||||
}
|
||||
name: "db"
|
||||
replicas: 1
|
||||
}]
|
||||
port: 5432
|
||||
postgresVersion: 16
|
||||
users: [{
|
||||
databases: ["holos"]
|
||||
name: "holos"
|
||||
options: "SUPERUSER"
|
||||
}]
|
||||
backups: pgbackrest: {
|
||||
global: {
|
||||
"archive-async": "y"
|
||||
"archive-push-queue-max": "100MiB"
|
||||
"spool-path": "/pgdata/backups"
|
||||
}
|
||||
image: "registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:ubi8-2.47-2"
|
||||
repos: [{
|
||||
name: "repo1"
|
||||
volume: volumeClaimSpec: {
|
||||
accessModes: ["ReadWriteOnce"]
|
||||
resources: requests: storage: "1Gi"
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
apiObjects: Service: holos: {
|
||||
apiVersion: "v1"
|
||||
metadata: Metadata
|
||||
spec: {
|
||||
type: "ClusterIP"
|
||||
selector: app: "holos"
|
||||
ports: [{
|
||||
appProtocol: "http2"
|
||||
name: "http"
|
||||
port: 3000
|
||||
protocol: "TCP"
|
||||
targetPort: 3000
|
||||
}, {
|
||||
appProtocol: "http"
|
||||
name: "metrics"
|
||||
port: 9090
|
||||
protocol: "TCP"
|
||||
targetPort: 9090
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
apiObjects: VirtualService: holos: {
|
||||
apiVersion: "networking.istio.io/v1beta1"
|
||||
metadata: Metadata
|
||||
spec: {
|
||||
gateways: ["istio-ingress/default"]
|
||||
hosts: [
|
||||
"app.dev.holos.run",
|
||||
"app.dev.\(#ClusterName).holos.run",
|
||||
]
|
||||
http: [{
|
||||
match: [{
|
||||
uri: prefix: "/ui"
|
||||
}]
|
||||
name: "ui"
|
||||
route: [{
|
||||
destination: {
|
||||
host: "holos"
|
||||
port: number: 3000
|
||||
}
|
||||
}]
|
||||
}, {
|
||||
name: "api"
|
||||
route: [{
|
||||
destination: {
|
||||
host: "holos"
|
||||
port: number: 3000
|
||||
}
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,5 +3,6 @@ USER root
|
||||
WORKDIR /app
|
||||
ADD bin bin
|
||||
RUN chown -R app: /app
|
||||
USER app
|
||||
# Kubernetes requires the user to be numeric
|
||||
USER 8192
|
||||
ENTRYPOINT bin/holos server
|
||||
|
||||
@@ -33,7 +33,8 @@
|
||||
</span>
|
||||
<app-profile-button [claims$]="claims$"></app-profile-button>
|
||||
</mat-toolbar>
|
||||
<!-- Add Content Here -->
|
||||
<router-outlet></router-outlet>
|
||||
<main class="main-content">
|
||||
<router-outlet></router-outlet>
|
||||
</main>
|
||||
</mat-sidenav-content>
|
||||
</mat-sidenav-container>
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
<mat-tab label="Detail">
|
||||
<div class="grid-container">
|
||||
<form [formGroup]="form" (ngSubmit)="onSubmit(model)">
|
||||
<formly-form [model]="model" [form]="form" [fields]="fields"></formly-form>
|
||||
<button type="submit" mat-flat-button color="primary">Submit</button>
|
||||
<formly-form [model]="model" [fields]="fields" [options]="options" [form]="form"></formly-form>
|
||||
<button type="submit" mat-flat-button color="primary" [disabled]="!form.valid">Submit</button>
|
||||
</form>
|
||||
</div>
|
||||
</mat-tab>
|
||||
@@ -14,6 +14,11 @@
|
||||
<pre>{{ model | json }}</pre>
|
||||
</div>
|
||||
</mat-tab>
|
||||
<mat-tab label="Form State">
|
||||
<div class="grid-container">
|
||||
<pre>{{ options.formState | json }}</pre>
|
||||
</div>
|
||||
</mat-tab>
|
||||
<mat-tab label="Fields">
|
||||
<div class="grid-container">
|
||||
<pre>{{ fields | json }}</pre>
|
||||
|
||||
@@ -34,23 +34,35 @@ export class PlatformDetailComponent implements OnDestroy {
|
||||
|
||||
private destroy$: Subject<any> = new Subject<any>();
|
||||
form = new FormGroup({});
|
||||
model: JsonValue = {};
|
||||
options: FormlyFormOptions = {};
|
||||
fields: FormlyFieldConfig[] = [];
|
||||
model: JsonValue = {};
|
||||
// Use form state to store the model for nested forms
|
||||
// Refer to https://formly.dev/docs/examples/form-options/form-state/
|
||||
options: FormlyFormOptions = {
|
||||
formState: {
|
||||
model: this.model,
|
||||
},
|
||||
};
|
||||
|
||||
private setModel(model: JsonValue) {
|
||||
if (model) {
|
||||
this.model = model
|
||||
this.options.formState.model = model
|
||||
}
|
||||
}
|
||||
|
||||
onSubmit(model: JsonValue) {
|
||||
// if (this.form.valid) {
|
||||
console.log(model)
|
||||
this.platformService
|
||||
.putModel(this.platformId, model)
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe(resp => {
|
||||
const model = JSON.parse(JSON.stringify(resp.model))
|
||||
if (model) {
|
||||
this.model = model
|
||||
}
|
||||
})
|
||||
// }
|
||||
if (this.form.valid) {
|
||||
console.log(model)
|
||||
this.platformService
|
||||
.putModel(this.platformId, model)
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe(resp => {
|
||||
if (resp.model !== undefined) {
|
||||
this.setModel(resp.model.toJson())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@Input()
|
||||
@@ -60,14 +72,15 @@ export class PlatformDetailComponent implements OnDestroy {
|
||||
.getForm(platformId)
|
||||
.pipe(takeUntil(this.destroy$))
|
||||
.subscribe(resp => {
|
||||
if (resp.model !== undefined) {
|
||||
this.setModel(resp.model.toJson())
|
||||
}
|
||||
if (resp.fields !== undefined) {
|
||||
// NOTE: We could map fields to mix in javascript functions. Refer to
|
||||
// NOTE: We could mix functions into the json data via mapped fields,
|
||||
// but consider carefully before doing so. Refer to
|
||||
// https://formly.dev/docs/examples/other/json-powered
|
||||
this.fields = resp.fields.map(field => field.toJson() as FormlyFieldConfig)
|
||||
}
|
||||
if (resp.model !== undefined) {
|
||||
this.model = resp.model.toJson()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,222 @@ let Platform = formsv1.#Platform & {
|
||||
}
|
||||
}
|
||||
|
||||
sections: privacy: {
|
||||
sections: cloud: {
|
||||
displayName: "Cloud Providers"
|
||||
description: "Select the services that provide resources for the platform."
|
||||
|
||||
fieldConfigs: {
|
||||
providers: {
|
||||
// https://formly.dev/docs/api/ui/material/select/
|
||||
type: "select"
|
||||
props: {
|
||||
label: "Select Providers"
|
||||
description: "Select the cloud providers the platform builds upon."
|
||||
multiple: true
|
||||
selectAllOption: "Select All"
|
||||
options: [
|
||||
{value: "aws", label: "Amazon Web Services"},
|
||||
{value: "gcp", label: "Google Cloud Platform"},
|
||||
{value: "azure", label: "Microsoft Azure"},
|
||||
{value: "cloudflare", label: "Cloudflare"},
|
||||
{value: "github", label: "GitHub"},
|
||||
{value: "ois", label: "Open Infrastructure Services"},
|
||||
{value: "onprem", label: "On Premises", disabled: true},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sections: aws: {
|
||||
displayName: "Amazon Web Services"
|
||||
description: "Provide the information necessary for Holos to manage AWS resources to provide the platform."
|
||||
|
||||
expressions: hide: "!\(AWSSelected)"
|
||||
|
||||
fieldConfigs: {
|
||||
primaryRoleARN: {
|
||||
// https://formly.dev/docs/api/ui/material/input
|
||||
type: "input"
|
||||
props: {
|
||||
label: "Holos Admin Role ARN"
|
||||
description: "Enter the AWS Role ARN Holos will use to bootstrap resources. For example, arn:aws:iam::123456789012:role/HolosAdminAccess"
|
||||
pattern: "^arn:.*"
|
||||
minLength: 4
|
||||
required: true
|
||||
}
|
||||
validation: messages: {
|
||||
pattern: "Must be a valid ARN. Refer to https://docs.aws.amazon.com/IAM/latest/UserGuide/reference-arns.html"
|
||||
}
|
||||
}
|
||||
|
||||
regions: {
|
||||
// https://formly.dev/docs/api/ui/material/select/
|
||||
type: "select"
|
||||
props: {
|
||||
label: "Select Regions"
|
||||
description: "Select the AWS regions this platform operates in."
|
||||
multiple: true
|
||||
required: true
|
||||
selectAllOption: "Select All"
|
||||
options: AWSRegions
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sections: gcp: {
|
||||
displayName: "Google Cloud Platform"
|
||||
description: "Use this form to configure platform level GCP settings."
|
||||
|
||||
expressions: hide: "!\(GCPSelected)"
|
||||
|
||||
fieldConfigs: {
|
||||
regions: {
|
||||
// https://formly.dev/docs/api/ui/material/select/
|
||||
type: "select"
|
||||
props: {
|
||||
label: "Select Regions"
|
||||
description: "Select the GCP regions this platform operates in."
|
||||
multiple: true
|
||||
selectAllOption: "Select All"
|
||||
// gcloud compute regions list --format=json | jq '.[] | {value: .name, label: .description}' regions.json | jq -s | cue export --out cue
|
||||
options: GCPRegions
|
||||
}
|
||||
}
|
||||
|
||||
gcpProjectID: {
|
||||
// https://formly.dev/docs/api/ui/material/input
|
||||
type: "input"
|
||||
props: {
|
||||
label: "Project ID"
|
||||
description: "Enter the project id where the provisioner cluster resides."
|
||||
pattern: "^[a-z]([0-9a-z]|-){1,28}[0-9a-z]$"
|
||||
minLength: 6
|
||||
maxLength: 30
|
||||
required: true
|
||||
}
|
||||
validation: messages: {
|
||||
pattern: "It must be 3 to 30 lowercase letters, digits, or hyphens. It must start with a letter. Trailing hyphens are prohibited."
|
||||
}
|
||||
}
|
||||
|
||||
gcpProjectNumber: {
|
||||
// https://formly.dev/docs/api/ui/material/input
|
||||
type: "input"
|
||||
props: {
|
||||
label: "Project Number"
|
||||
// note type number here
|
||||
type: "number"
|
||||
description: "Enter the project number where the provisioner cluster resides."
|
||||
pattern: "^[0-9]+$"
|
||||
required: true
|
||||
}
|
||||
validation: messages: {
|
||||
pattern: "Must be a valid project number."
|
||||
}
|
||||
}
|
||||
|
||||
provisionerCABundle: {
|
||||
type: "input"
|
||||
props: {
|
||||
label: "Provisioner CA Bundle"
|
||||
description: "Enter the provisioner cluster ca bundle. kubectl config view --minify --flatten -ojsonpath='{.clusters[0].cluster.certificate-authority-data}'"
|
||||
pattern: "^[0-9a-zA-Z]+=*$"
|
||||
required: true
|
||||
}
|
||||
validation: messages: {
|
||||
pattern: "Must be a base64 encoded pem encoded certificate bundle."
|
||||
}
|
||||
}
|
||||
|
||||
provisionerURL: {
|
||||
type: "input"
|
||||
props: {
|
||||
label: "Provisioner URL"
|
||||
description: "Enter the URL of the provisioner cluster API endpoint. kubectl config view --minify --flatten -ojsonpath='{.clusters[0].cluster.server}'"
|
||||
pattern: "^https://.*$"
|
||||
required: true
|
||||
}
|
||||
validation: messages: {
|
||||
pattern: "Must be a https:// URL."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sections: cloudflare: {
|
||||
displayName: "Cloudflare"
|
||||
description: "Cloudflare is primarily used for DNS automation."
|
||||
|
||||
expressions: hide: "!" + CloudflareSelected
|
||||
|
||||
fieldConfigs: {
|
||||
email: {
|
||||
// https://formly.dev/docs/api/ui/material/input
|
||||
type: "input"
|
||||
props: {
|
||||
label: "Account Email"
|
||||
description: "Enter the Cloudflare email address to manage DNS"
|
||||
minLength: 3
|
||||
required: true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sections: github: {
|
||||
displayName: "GitHub"
|
||||
description: "GitHub is primarily used to host Git repositories and execute Actions workflows."
|
||||
|
||||
expressions: hide: "!\(GitHubSelected)"
|
||||
|
||||
fieldConfigs: {
|
||||
primaryOrg: {
|
||||
// https://formly.dev/docs/api/ui/material/input
|
||||
type: "input"
|
||||
props: {
|
||||
label: "Organization"
|
||||
description: "Enter the primary GitHub organization associed with the platform."
|
||||
pattern: "^(?!-)(?!.*--)([a-zA-Z0-9]|-){1,39}$"
|
||||
minLength: 1
|
||||
maxLength: 39
|
||||
required: true
|
||||
}
|
||||
validation: messages: {
|
||||
pattern: "All characters must be either a hyphen or alphanumeric. Cannot start with a hyphen. Cannot include consecutive hyphens."
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sections: backups: {
|
||||
displayName: "Backups"
|
||||
description: "Configure platform level data backup settings. Requires AWS."
|
||||
|
||||
fieldConfigs: {
|
||||
s3bucket: {
|
||||
// https://formly.dev/docs/api/ui/material/input
|
||||
type: "select"
|
||||
props: {
|
||||
label: "S3 Bucket Region"
|
||||
description: "Select the S3 Bucket Region."
|
||||
multiple: true
|
||||
options: AWSRegions
|
||||
}
|
||||
expressions: {
|
||||
// Disable the control if AWS is not selected.
|
||||
"props.disabled": "!" + AWSSelected
|
||||
// Required if AWS is selected.
|
||||
"props.required": AWSSelected
|
||||
// Change the label depending on AWS
|
||||
"props.description": AWSSelected + " ? '\(props.description)' : 'Enable AWS in the Cloud Provider section to configure backups.'"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_sections: privacy: {
|
||||
displayName: "Data Privacy"
|
||||
description: "Configure data privacy aspects of the platform."
|
||||
|
||||
@@ -106,8 +321,7 @@ let Platform = formsv1.#Platform & {
|
||||
}
|
||||
}
|
||||
|
||||
// https://v5.formly.dev/ui/material
|
||||
sections: terms: {
|
||||
_sections: terms: {
|
||||
displayName: "Terms and Conditions"
|
||||
description: "Example of a boolean checkbox."
|
||||
|
||||
@@ -133,3 +347,80 @@ let Platform = formsv1.#Platform & {
|
||||
|
||||
// Provide the output form fields
|
||||
Platform.Form
|
||||
|
||||
let GCPRegions = [
|
||||
{value: "africa-south1", label: "africa-south1"},
|
||||
{value: "asia-east1", label: "asia-east1"},
|
||||
{value: "asia-east2", label: "asia-east2"},
|
||||
{value: "asia-northeast1", label: "asia-northeast1"},
|
||||
{value: "asia-northeast2", label: "asia-northeast2"},
|
||||
{value: "asia-northeast3", label: "asia-northeast3"},
|
||||
{value: "asia-south1", label: "asia-south1"},
|
||||
{value: "asia-south2", label: "asia-south2"},
|
||||
{value: "asia-southeast1", label: "asia-southeast1"},
|
||||
{value: "asia-southeast2", label: "asia-southeast2"},
|
||||
{value: "australia-southeast1", label: "australia-southeast1"},
|
||||
{value: "australia-southeast2", label: "australia-southeast2"},
|
||||
{value: "europe-central2", label: "europe-central2"},
|
||||
{value: "europe-north1", label: "europe-north1"},
|
||||
{value: "europe-southwest1", label: "europe-southwest1"},
|
||||
{value: "europe-west1", label: "europe-west1"},
|
||||
{value: "europe-west10", label: "europe-west10"},
|
||||
{value: "europe-west12", label: "europe-west12"},
|
||||
{value: "europe-west2", label: "europe-west2"},
|
||||
{value: "europe-west3", label: "europe-west3"},
|
||||
{value: "europe-west4", label: "europe-west4"},
|
||||
{value: "europe-west6", label: "europe-west6"},
|
||||
{value: "europe-west8", label: "europe-west8"},
|
||||
{value: "europe-west9", label: "europe-west9"},
|
||||
{value: "me-central1", label: "me-central1"},
|
||||
{value: "me-central2", label: "me-central2"},
|
||||
{value: "me-west1", label: "me-west1"},
|
||||
{value: "northamerica-northeast1", label: "northamerica-northeast1"},
|
||||
{value: "northamerica-northeast2", label: "northamerica-northeast2"},
|
||||
{value: "southamerica-east1", label: "southamerica-east1"},
|
||||
{value: "southamerica-west1", label: "southamerica-west1"},
|
||||
{value: "us-central1", label: "us-central1"},
|
||||
{value: "us-east1", label: "us-east1"},
|
||||
{value: "us-east4", label: "us-east4"},
|
||||
{value: "us-east5", label: "us-east5"},
|
||||
{value: "us-south1", label: "us-south1"},
|
||||
{value: "us-west1", label: "us-west1"},
|
||||
{value: "us-west2", label: "us-west2"},
|
||||
{value: "us-west3", label: "us-west3"},
|
||||
{value: "us-west4", label: "us-west4"},
|
||||
]
|
||||
|
||||
let AWSRegions = [
|
||||
{value: "us-east-1", label: "N. Virginia (us-east-1)"},
|
||||
{value: "us-east-2", label: "Ohio (us-east-2)"},
|
||||
{value: "us-west-1", label: "N. California (us-west-1)"},
|
||||
{value: "us-west-2", label: "Oregon (us-west-2)"},
|
||||
{value: "us-gov-west1", label: "US GovCloud West (us-gov-west1)"},
|
||||
{value: "us-gov-east1", label: "US GovCloud East (us-gov-east1)"},
|
||||
{value: "ca-central-1", label: "Canada (ca-central-1)"},
|
||||
{value: "eu-north-1", label: "Stockholm (eu-north-1)"},
|
||||
{value: "eu-west-1", label: "Ireland (eu-west-1)"},
|
||||
{value: "eu-west-2", label: "London (eu-west-2)"},
|
||||
{value: "eu-west-3", label: "Paris (eu-west-3)"},
|
||||
{value: "eu-central-1", label: "Frankfurt (eu-central-1)"},
|
||||
{value: "eu-south-1", label: "Milan (eu-south-1)"},
|
||||
{value: "af-south-1", label: "Cape Town (af-south-1)"},
|
||||
{value: "ap-northeast-1", label: "Tokyo (ap-northeast-1)"},
|
||||
{value: "ap-northeast-2", label: "Seoul (ap-northeast-2)"},
|
||||
{value: "ap-northeast-3", label: "Osaka (ap-northeast-3)"},
|
||||
{value: "ap-southeast-1", label: "Singapore (ap-southeast-1)"},
|
||||
{value: "ap-southeast-2", label: "Sydney (ap-southeast-2)"},
|
||||
{value: "ap-east-1", label: "Hong Kong (ap-east-1)"},
|
||||
{value: "ap-south-1", label: "Mumbai (ap-south-1)"},
|
||||
{value: "me-south-1", label: "Bahrain (me-south-1)"},
|
||||
{value: "sa-east-1", label: "São Paulo (sa-east-1)"},
|
||||
{value: "cn-north-1", label: "Bejing (cn-north-1)"},
|
||||
{value: "cn-northwest-1", label: "Ningxia (cn-northwest-1)"},
|
||||
{value: "ap-southeast-3", label: "Jakarta (ap-southeast-3)"},
|
||||
]
|
||||
|
||||
let AWSSelected = "formState.model.cloud?.providers?.includes(\"aws\")"
|
||||
let GCPSelected = "formState.model.cloud?.providers?.includes(\"gcp\")"
|
||||
let GitHubSelected = "formState.model.cloud?.providers?.includes(\"github\")"
|
||||
let CloudflareSelected = "formState.model.cloud?.providers?.includes(\"cloudflare\")"
|
||||
|
||||
@@ -26,16 +26,20 @@ package v1alpha1
|
||||
fields: [...#FieldConfig]
|
||||
}
|
||||
|
||||
// #ConfigSection represents a configuration section of the front end UI. For
|
||||
// #ConfigSection represents a configuration section of the front end UI. For
|
||||
// example, Organization config values. The fields of the section map to form
|
||||
// input fields.
|
||||
#ConfigSection: {
|
||||
name: string // e.g. "org"
|
||||
displayName: string // e.g. "Organization"
|
||||
description: string
|
||||
|
||||
expressions: {[string]: string}
|
||||
|
||||
fieldConfigs: {[NAME=string]: #FieldConfig & {key: NAME}}
|
||||
|
||||
let Description = description
|
||||
let Expressions = expressions
|
||||
|
||||
// Wrap the fields of the section into one FormlyFieldConfig
|
||||
wrapper: #FieldConfig & {
|
||||
@@ -44,6 +48,12 @@ package v1alpha1
|
||||
wrappers: ["holos-panel"]
|
||||
props: label: displayName
|
||||
props: description: Description
|
||||
for k, v in Expressions {
|
||||
expressions: "\(k)": v
|
||||
}
|
||||
|
||||
// Might need to initialize the default value for a fieldGroup
|
||||
// https://github.com/ngx-formly/ngx-formly/issues/3667
|
||||
fieldGroup: [for fc in fieldConfigs {fc}]
|
||||
}
|
||||
}
|
||||
@@ -70,6 +80,7 @@ package v1alpha1
|
||||
#FormlySelectProps
|
||||
|
||||
label: string
|
||||
type?: string
|
||||
placeholder?: string
|
||||
description: string
|
||||
required?: *true | false
|
||||
@@ -84,6 +95,10 @@ package v1alpha1
|
||||
messages?: [string]: string
|
||||
}
|
||||
|
||||
// Refer to: https://github.com/ngx-formly/ngx-formly/blob/v6.3.0/src/core/src/lib/models/fieldconfig.ts#L66-L71
|
||||
// We do not support validators because they must be javascript functions, not data.
|
||||
validators?: "not supported"
|
||||
|
||||
// Refer to: https://github.com/ngx-formly/ngx-formly/blob/v6.3.0/src/core/src/lib/models/fieldconfig.ts#L115-L120
|
||||
expressions?: [string]: string
|
||||
hide?: true | false
|
||||
|
||||
@@ -189,12 +189,14 @@ const BareForm = `
|
||||
"props": {
|
||||
"label": "Name",
|
||||
"description": "DNS label, e.g. 'example'",
|
||||
"pattern": "[a-z][0-9a-z]{4,29}",
|
||||
"pattern": "^[a-z]([0-9a-z]|-){1,28}[0-9a-z]$",
|
||||
"minLength": 3,
|
||||
"maxLength": 30,
|
||||
"required": true
|
||||
},
|
||||
"validation": {
|
||||
"messages": {
|
||||
"pattern": "It must be 6 to 30 lowercase letters, digits, or hyphens. It must start with a letter. Trailing hyphens are prohibited."
|
||||
"pattern": "It must be 3 to 30 lowercase letters, digits, or hyphens. It must start with a letter. Trailing hyphens are prohibited."
|
||||
}
|
||||
},
|
||||
"resetOnHide": true
|
||||
@@ -205,7 +207,10 @@ const BareForm = `
|
||||
"props": {
|
||||
"label": "Domain",
|
||||
"placeholder": "example.com",
|
||||
"description": "DNS domain, e.g. 'example.com'"
|
||||
"minLength": 3,
|
||||
"maxLength": 100,
|
||||
"description": "DNS domain, e.g. 'example.com'",
|
||||
"required": true
|
||||
},
|
||||
"resetOnHide": true
|
||||
},
|
||||
@@ -215,7 +220,9 @@ const BareForm = `
|
||||
"props": {
|
||||
"label": "Display Name",
|
||||
"placeholder": "Example Organization",
|
||||
"description": "Display name, e.g. 'Example Organization'"
|
||||
"description": "Display name, e.g. 'Example Organization'",
|
||||
"maxLength": 100,
|
||||
"required": true
|
||||
},
|
||||
"resetOnHide": true
|
||||
},
|
||||
@@ -225,90 +232,60 @@ const BareForm = `
|
||||
"props": {
|
||||
"label": "Contact Email",
|
||||
"placeholder": "platform-team@example.com",
|
||||
"description": "Technical contact email address"
|
||||
"description": "Technical contact email address",
|
||||
"required": true
|
||||
},
|
||||
"resetOnHide": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "privacy",
|
||||
"key": "cloud",
|
||||
"wrappers": [
|
||||
"holos-panel"
|
||||
],
|
||||
"props": {
|
||||
"label": "Data Privacy",
|
||||
"description": "Configure data privacy aspects of the platform."
|
||||
"label": "Cloud Providers",
|
||||
"description": "Select the services that provide resources for the platform."
|
||||
},
|
||||
"resetOnHide": true,
|
||||
"fieldGroup": [
|
||||
{
|
||||
"key": "country",
|
||||
"key": "providers",
|
||||
"type": "select",
|
||||
"props": {
|
||||
"label": "Select Planet",
|
||||
"description": "Juridiction of applicable data privacy laws.",
|
||||
"options": [
|
||||
{
|
||||
"value": "mercury",
|
||||
"label": "Mercury"
|
||||
},
|
||||
{
|
||||
"value": "venus",
|
||||
"label": "Venus"
|
||||
},
|
||||
{
|
||||
"value": "earth",
|
||||
"label": "Earth"
|
||||
},
|
||||
{
|
||||
"value": "mars",
|
||||
"label": "Mars"
|
||||
},
|
||||
{
|
||||
"value": "jupiter",
|
||||
"label": "Jupiter"
|
||||
},
|
||||
{
|
||||
"value": "saturn",
|
||||
"label": "Saturn"
|
||||
},
|
||||
{
|
||||
"value": "uranus",
|
||||
"label": "Uranus"
|
||||
},
|
||||
{
|
||||
"value": "neptune",
|
||||
"label": "Neptune"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resetOnHide": true
|
||||
},
|
||||
{
|
||||
"key": "regions",
|
||||
"type": "select",
|
||||
"props": {
|
||||
"label": "Select Regions",
|
||||
"description": "Select the regions this platform operates in.",
|
||||
"label": "Select Providers",
|
||||
"description": "Select the cloud providers the platform builds upon.",
|
||||
"multiple": true,
|
||||
"selectAllOption": "Select All",
|
||||
"options": [
|
||||
{
|
||||
"value": "us-east-2",
|
||||
"label": "Ohio"
|
||||
"value": "aws",
|
||||
"label": "Amazon Web Services"
|
||||
},
|
||||
{
|
||||
"value": "us-west-2",
|
||||
"label": "Oregon"
|
||||
"value": "gcp",
|
||||
"label": "Google Cloud Platform"
|
||||
},
|
||||
{
|
||||
"value": "eu-west-1",
|
||||
"label": "Ireland"
|
||||
"value": "azure",
|
||||
"label": "Microsoft Azure"
|
||||
},
|
||||
{
|
||||
"value": "eu-west-2",
|
||||
"label": "London",
|
||||
"value": "cloudflare",
|
||||
"label": "Cloudflare"
|
||||
},
|
||||
{
|
||||
"value": "github",
|
||||
"label": "GitHub"
|
||||
},
|
||||
{
|
||||
"value": "ois",
|
||||
"label": "Open Infrastructure Services"
|
||||
},
|
||||
{
|
||||
"value": "onprem",
|
||||
"label": "On Premises",
|
||||
"disabled": true
|
||||
}
|
||||
]
|
||||
@@ -318,31 +295,604 @@ const BareForm = `
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "terms",
|
||||
"key": "aws",
|
||||
"wrappers": [
|
||||
"holos-panel"
|
||||
],
|
||||
"props": {
|
||||
"label": "Terms and Conditions",
|
||||
"description": "Example of a boolean checkbox."
|
||||
"label": "Amazon Web Services",
|
||||
"description": "Provide the information necessary for Holos to manage AWS resources to provide the platform."
|
||||
},
|
||||
"expressions": {
|
||||
"hide": "!formState.model.cloud?.providers?.includes(\"aws\")"
|
||||
},
|
||||
"resetOnHide": true,
|
||||
"fieldGroup": [
|
||||
{
|
||||
"key": "didAgree",
|
||||
"type": "checkbox",
|
||||
"key": "primaryRoleARN",
|
||||
"type": "input",
|
||||
"props": {
|
||||
"label": "Accept terms",
|
||||
"description": "In order to proceed, please accept terms",
|
||||
"pattern": "true",
|
||||
"label": "Holos Admin Role ARN",
|
||||
"description": "Enter the AWS Role ARN Holos will use to bootstrap resources. For example, arn:aws:iam::123456789012:role/HolosAdminAccess",
|
||||
"pattern": "^arn:.*",
|
||||
"minLength": 4,
|
||||
"required": true
|
||||
},
|
||||
"validation": {
|
||||
"messages": {
|
||||
"pattern": "Please accept the terms"
|
||||
"pattern": "Must be a valid ARN. Refer to https://docs.aws.amazon.com/IAM/latest/UserGuide/reference-arns.html"
|
||||
}
|
||||
},
|
||||
"resetOnHide": true
|
||||
},
|
||||
{
|
||||
"key": "regions",
|
||||
"type": "select",
|
||||
"props": {
|
||||
"label": "Select Regions",
|
||||
"description": "Select the AWS regions this platform operates in.",
|
||||
"multiple": true,
|
||||
"required": true,
|
||||
"selectAllOption": "Select All",
|
||||
"options": [
|
||||
{
|
||||
"value": "us-east-1",
|
||||
"label": "N. Virginia (us-east-1)"
|
||||
},
|
||||
{
|
||||
"value": "us-east-2",
|
||||
"label": "Ohio (us-east-2)"
|
||||
},
|
||||
{
|
||||
"value": "us-west-1",
|
||||
"label": "N. California (us-west-1)"
|
||||
},
|
||||
{
|
||||
"value": "us-west-2",
|
||||
"label": "Oregon (us-west-2)"
|
||||
},
|
||||
{
|
||||
"value": "us-gov-west1",
|
||||
"label": "US GovCloud West (us-gov-west1)"
|
||||
},
|
||||
{
|
||||
"value": "us-gov-east1",
|
||||
"label": "US GovCloud East (us-gov-east1)"
|
||||
},
|
||||
{
|
||||
"value": "ca-central-1",
|
||||
"label": "Canada (ca-central-1)"
|
||||
},
|
||||
{
|
||||
"value": "eu-north-1",
|
||||
"label": "Stockholm (eu-north-1)"
|
||||
},
|
||||
{
|
||||
"value": "eu-west-1",
|
||||
"label": "Ireland (eu-west-1)"
|
||||
},
|
||||
{
|
||||
"value": "eu-west-2",
|
||||
"label": "London (eu-west-2)"
|
||||
},
|
||||
{
|
||||
"value": "eu-west-3",
|
||||
"label": "Paris (eu-west-3)"
|
||||
},
|
||||
{
|
||||
"value": "eu-central-1",
|
||||
"label": "Frankfurt (eu-central-1)"
|
||||
},
|
||||
{
|
||||
"value": "eu-south-1",
|
||||
"label": "Milan (eu-south-1)"
|
||||
},
|
||||
{
|
||||
"value": "af-south-1",
|
||||
"label": "Cape Town (af-south-1)"
|
||||
},
|
||||
{
|
||||
"value": "ap-northeast-1",
|
||||
"label": "Tokyo (ap-northeast-1)"
|
||||
},
|
||||
{
|
||||
"value": "ap-northeast-2",
|
||||
"label": "Seoul (ap-northeast-2)"
|
||||
},
|
||||
{
|
||||
"value": "ap-northeast-3",
|
||||
"label": "Osaka (ap-northeast-3)"
|
||||
},
|
||||
{
|
||||
"value": "ap-southeast-1",
|
||||
"label": "Singapore (ap-southeast-1)"
|
||||
},
|
||||
{
|
||||
"value": "ap-southeast-2",
|
||||
"label": "Sydney (ap-southeast-2)"
|
||||
},
|
||||
{
|
||||
"value": "ap-east-1",
|
||||
"label": "Hong Kong (ap-east-1)"
|
||||
},
|
||||
{
|
||||
"value": "ap-south-1",
|
||||
"label": "Mumbai (ap-south-1)"
|
||||
},
|
||||
{
|
||||
"value": "me-south-1",
|
||||
"label": "Bahrain (me-south-1)"
|
||||
},
|
||||
{
|
||||
"value": "sa-east-1",
|
||||
"label": "São Paulo (sa-east-1)"
|
||||
},
|
||||
{
|
||||
"value": "cn-north-1",
|
||||
"label": "Bejing (cn-north-1)"
|
||||
},
|
||||
{
|
||||
"value": "cn-northwest-1",
|
||||
"label": "Ningxia (cn-northwest-1)"
|
||||
},
|
||||
{
|
||||
"value": "ap-southeast-3",
|
||||
"label": "Jakarta (ap-southeast-3)"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resetOnHide": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "gcp",
|
||||
"wrappers": [
|
||||
"holos-panel"
|
||||
],
|
||||
"props": {
|
||||
"label": "Google Cloud Platform",
|
||||
"description": "Use this form to configure platform level GCP settings."
|
||||
},
|
||||
"expressions": {
|
||||
"hide": "!formState.model.cloud?.providers?.includes(\"gcp\")"
|
||||
},
|
||||
"resetOnHide": true,
|
||||
"fieldGroup": [
|
||||
{
|
||||
"key": "regions",
|
||||
"type": "select",
|
||||
"props": {
|
||||
"label": "Select Regions",
|
||||
"description": "Select the GCP regions this platform operates in.",
|
||||
"multiple": true,
|
||||
"selectAllOption": "Select All",
|
||||
"options": [
|
||||
{
|
||||
"value": "africa-south1",
|
||||
"label": "africa-south1"
|
||||
},
|
||||
{
|
||||
"value": "asia-east1",
|
||||
"label": "asia-east1"
|
||||
},
|
||||
{
|
||||
"value": "asia-east2",
|
||||
"label": "asia-east2"
|
||||
},
|
||||
{
|
||||
"value": "asia-northeast1",
|
||||
"label": "asia-northeast1"
|
||||
},
|
||||
{
|
||||
"value": "asia-northeast2",
|
||||
"label": "asia-northeast2"
|
||||
},
|
||||
{
|
||||
"value": "asia-northeast3",
|
||||
"label": "asia-northeast3"
|
||||
},
|
||||
{
|
||||
"value": "asia-south1",
|
||||
"label": "asia-south1"
|
||||
},
|
||||
{
|
||||
"value": "asia-south2",
|
||||
"label": "asia-south2"
|
||||
},
|
||||
{
|
||||
"value": "asia-southeast1",
|
||||
"label": "asia-southeast1"
|
||||
},
|
||||
{
|
||||
"value": "asia-southeast2",
|
||||
"label": "asia-southeast2"
|
||||
},
|
||||
{
|
||||
"value": "australia-southeast1",
|
||||
"label": "australia-southeast1"
|
||||
},
|
||||
{
|
||||
"value": "australia-southeast2",
|
||||
"label": "australia-southeast2"
|
||||
},
|
||||
{
|
||||
"value": "europe-central2",
|
||||
"label": "europe-central2"
|
||||
},
|
||||
{
|
||||
"value": "europe-north1",
|
||||
"label": "europe-north1"
|
||||
},
|
||||
{
|
||||
"value": "europe-southwest1",
|
||||
"label": "europe-southwest1"
|
||||
},
|
||||
{
|
||||
"value": "europe-west1",
|
||||
"label": "europe-west1"
|
||||
},
|
||||
{
|
||||
"value": "europe-west10",
|
||||
"label": "europe-west10"
|
||||
},
|
||||
{
|
||||
"value": "europe-west12",
|
||||
"label": "europe-west12"
|
||||
},
|
||||
{
|
||||
"value": "europe-west2",
|
||||
"label": "europe-west2"
|
||||
},
|
||||
{
|
||||
"value": "europe-west3",
|
||||
"label": "europe-west3"
|
||||
},
|
||||
{
|
||||
"value": "europe-west4",
|
||||
"label": "europe-west4"
|
||||
},
|
||||
{
|
||||
"value": "europe-west6",
|
||||
"label": "europe-west6"
|
||||
},
|
||||
{
|
||||
"value": "europe-west8",
|
||||
"label": "europe-west8"
|
||||
},
|
||||
{
|
||||
"value": "europe-west9",
|
||||
"label": "europe-west9"
|
||||
},
|
||||
{
|
||||
"value": "me-central1",
|
||||
"label": "me-central1"
|
||||
},
|
||||
{
|
||||
"value": "me-central2",
|
||||
"label": "me-central2"
|
||||
},
|
||||
{
|
||||
"value": "me-west1",
|
||||
"label": "me-west1"
|
||||
},
|
||||
{
|
||||
"value": "northamerica-northeast1",
|
||||
"label": "northamerica-northeast1"
|
||||
},
|
||||
{
|
||||
"value": "northamerica-northeast2",
|
||||
"label": "northamerica-northeast2"
|
||||
},
|
||||
{
|
||||
"value": "southamerica-east1",
|
||||
"label": "southamerica-east1"
|
||||
},
|
||||
{
|
||||
"value": "southamerica-west1",
|
||||
"label": "southamerica-west1"
|
||||
},
|
||||
{
|
||||
"value": "us-central1",
|
||||
"label": "us-central1"
|
||||
},
|
||||
{
|
||||
"value": "us-east1",
|
||||
"label": "us-east1"
|
||||
},
|
||||
{
|
||||
"value": "us-east4",
|
||||
"label": "us-east4"
|
||||
},
|
||||
{
|
||||
"value": "us-east5",
|
||||
"label": "us-east5"
|
||||
},
|
||||
{
|
||||
"value": "us-south1",
|
||||
"label": "us-south1"
|
||||
},
|
||||
{
|
||||
"value": "us-west1",
|
||||
"label": "us-west1"
|
||||
},
|
||||
{
|
||||
"value": "us-west2",
|
||||
"label": "us-west2"
|
||||
},
|
||||
{
|
||||
"value": "us-west3",
|
||||
"label": "us-west3"
|
||||
},
|
||||
{
|
||||
"value": "us-west4",
|
||||
"label": "us-west4"
|
||||
}
|
||||
]
|
||||
},
|
||||
"resetOnHide": true
|
||||
},
|
||||
{
|
||||
"key": "gcpProjectID",
|
||||
"type": "input",
|
||||
"props": {
|
||||
"label": "Project ID",
|
||||
"description": "Enter the project id where the provisioner cluster resides.",
|
||||
"pattern": "^[a-z]([0-9a-z]|-){1,28}[0-9a-z]$",
|
||||
"minLength": 6,
|
||||
"maxLength": 30,
|
||||
"required": true
|
||||
},
|
||||
"validation": {
|
||||
"messages": {
|
||||
"pattern": "It must be 3 to 30 lowercase letters, digits, or hyphens. It must start with a letter. Trailing hyphens are prohibited."
|
||||
}
|
||||
},
|
||||
"resetOnHide": true
|
||||
},
|
||||
{
|
||||
"key": "gcpProjectNumber",
|
||||
"type": "input",
|
||||
"props": {
|
||||
"label": "Project Number",
|
||||
"type": "number",
|
||||
"description": "Enter the project number where the provisioner cluster resides.",
|
||||
"pattern": "^[0-9]+$",
|
||||
"required": true
|
||||
},
|
||||
"validation": {
|
||||
"messages": {
|
||||
"pattern": "Must be a valid project number."
|
||||
}
|
||||
},
|
||||
"resetOnHide": true
|
||||
},
|
||||
{
|
||||
"key": "provisionerCABundle",
|
||||
"type": "input",
|
||||
"props": {
|
||||
"label": "Provisioner CA Bundle",
|
||||
"description": "Enter the provisioner cluster ca bundle. kubectl config view --minify --flatten -ojsonpath='{.clusters[0].cluster.certificate-authority-data}'",
|
||||
"pattern": "^[0-9a-zA-Z]+=*$",
|
||||
"required": true
|
||||
},
|
||||
"validation": {
|
||||
"messages": {
|
||||
"pattern": "Must be a base64 encoded pem encoded certificate bundle."
|
||||
}
|
||||
},
|
||||
"resetOnHide": true
|
||||
},
|
||||
{
|
||||
"key": "provisionerURL",
|
||||
"type": "input",
|
||||
"props": {
|
||||
"label": "Provisioner URL",
|
||||
"description": "Enter the URL of the provisioner cluster API endpoint. kubectl config view --minify --flatten -ojsonpath='{.clusters[0].cluster.server}'",
|
||||
"pattern": "^https://.*$",
|
||||
"required": true
|
||||
},
|
||||
"validation": {
|
||||
"messages": {
|
||||
"pattern": "Must be a https:// URL."
|
||||
}
|
||||
},
|
||||
"resetOnHide": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "cloudflare",
|
||||
"wrappers": [
|
||||
"holos-panel"
|
||||
],
|
||||
"props": {
|
||||
"label": "Cloudflare",
|
||||
"description": "Cloudflare is primarily used for DNS automation."
|
||||
},
|
||||
"expressions": {
|
||||
"hide": "!formState.model.cloud?.providers?.includes(\"cloudflare\")"
|
||||
},
|
||||
"resetOnHide": true,
|
||||
"fieldGroup": [
|
||||
{
|
||||
"key": "email",
|
||||
"type": "input",
|
||||
"props": {
|
||||
"label": "Account Email",
|
||||
"description": "Enter the Cloudflare email address to manage DNS",
|
||||
"minLength": 3,
|
||||
"required": true
|
||||
},
|
||||
"resetOnHide": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "github",
|
||||
"wrappers": [
|
||||
"holos-panel"
|
||||
],
|
||||
"props": {
|
||||
"label": "GitHub",
|
||||
"description": "GitHub is primarily used to host Git repositories and execute Actions workflows."
|
||||
},
|
||||
"expressions": {
|
||||
"hide": "!formState.model.cloud?.providers?.includes(\"github\")"
|
||||
},
|
||||
"resetOnHide": true,
|
||||
"fieldGroup": [
|
||||
{
|
||||
"key": "primaryOrg",
|
||||
"type": "input",
|
||||
"props": {
|
||||
"label": "Organization",
|
||||
"description": "Enter the primary GitHub organization associed with the platform.",
|
||||
"pattern": "^(?!-)(?!.*--)([a-zA-Z0-9]|-){1,39}$",
|
||||
"minLength": 1,
|
||||
"maxLength": 39,
|
||||
"required": true
|
||||
},
|
||||
"validation": {
|
||||
"messages": {
|
||||
"pattern": "All characters must be either a hyphen or alphanumeric. Cannot start with a hyphen. Cannot include consecutive hyphens."
|
||||
}
|
||||
},
|
||||
"resetOnHide": true
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "backups",
|
||||
"wrappers": [
|
||||
"holos-panel"
|
||||
],
|
||||
"props": {
|
||||
"label": "Backups",
|
||||
"description": "Configure platform level data backup settings. Requires AWS."
|
||||
},
|
||||
"resetOnHide": true,
|
||||
"fieldGroup": [
|
||||
{
|
||||
"key": "s3bucket",
|
||||
"type": "select",
|
||||
"props": {
|
||||
"label": "S3 Bucket Region",
|
||||
"description": "Select the S3 Bucket Region.",
|
||||
"multiple": true,
|
||||
"options": [
|
||||
{
|
||||
"value": "us-east-1",
|
||||
"label": "N. Virginia (us-east-1)"
|
||||
},
|
||||
{
|
||||
"value": "us-east-2",
|
||||
"label": "Ohio (us-east-2)"
|
||||
},
|
||||
{
|
||||
"value": "us-west-1",
|
||||
"label": "N. California (us-west-1)"
|
||||
},
|
||||
{
|
||||
"value": "us-west-2",
|
||||
"label": "Oregon (us-west-2)"
|
||||
},
|
||||
{
|
||||
"value": "us-gov-west1",
|
||||
"label": "US GovCloud West (us-gov-west1)"
|
||||
},
|
||||
{
|
||||
"value": "us-gov-east1",
|
||||
"label": "US GovCloud East (us-gov-east1)"
|
||||
},
|
||||
{
|
||||
"value": "ca-central-1",
|
||||
"label": "Canada (ca-central-1)"
|
||||
},
|
||||
{
|
||||
"value": "eu-north-1",
|
||||
"label": "Stockholm (eu-north-1)"
|
||||
},
|
||||
{
|
||||
"value": "eu-west-1",
|
||||
"label": "Ireland (eu-west-1)"
|
||||
},
|
||||
{
|
||||
"value": "eu-west-2",
|
||||
"label": "London (eu-west-2)"
|
||||
},
|
||||
{
|
||||
"value": "eu-west-3",
|
||||
"label": "Paris (eu-west-3)"
|
||||
},
|
||||
{
|
||||
"value": "eu-central-1",
|
||||
"label": "Frankfurt (eu-central-1)"
|
||||
},
|
||||
{
|
||||
"value": "eu-south-1",
|
||||
"label": "Milan (eu-south-1)"
|
||||
},
|
||||
{
|
||||
"value": "af-south-1",
|
||||
"label": "Cape Town (af-south-1)"
|
||||
},
|
||||
{
|
||||
"value": "ap-northeast-1",
|
||||
"label": "Tokyo (ap-northeast-1)"
|
||||
},
|
||||
{
|
||||
"value": "ap-northeast-2",
|
||||
"label": "Seoul (ap-northeast-2)"
|
||||
},
|
||||
{
|
||||
"value": "ap-northeast-3",
|
||||
"label": "Osaka (ap-northeast-3)"
|
||||
},
|
||||
{
|
||||
"value": "ap-southeast-1",
|
||||
"label": "Singapore (ap-southeast-1)"
|
||||
},
|
||||
{
|
||||
"value": "ap-southeast-2",
|
||||
"label": "Sydney (ap-southeast-2)"
|
||||
},
|
||||
{
|
||||
"value": "ap-east-1",
|
||||
"label": "Hong Kong (ap-east-1)"
|
||||
},
|
||||
{
|
||||
"value": "ap-south-1",
|
||||
"label": "Mumbai (ap-south-1)"
|
||||
},
|
||||
{
|
||||
"value": "me-south-1",
|
||||
"label": "Bahrain (me-south-1)"
|
||||
},
|
||||
{
|
||||
"value": "sa-east-1",
|
||||
"label": "São Paulo (sa-east-1)"
|
||||
},
|
||||
{
|
||||
"value": "cn-north-1",
|
||||
"label": "Bejing (cn-north-1)"
|
||||
},
|
||||
{
|
||||
"value": "cn-northwest-1",
|
||||
"label": "Ningxia (cn-northwest-1)"
|
||||
},
|
||||
{
|
||||
"value": "ap-southeast-3",
|
||||
"label": "Jakarta (ap-southeast-3)"
|
||||
}
|
||||
]
|
||||
},
|
||||
"expressions": {
|
||||
"props.disabled": "!formState.model.cloud?.providers?.includes(\"aws\")",
|
||||
"props.required": "formState.model.cloud?.providers?.includes(\"aws\")",
|
||||
"props.description": "formState.model.cloud?.providers?.includes(\"aws\") ? 'Select the S3 Bucket Region.' : 'Enable AWS in the Cloud Provider section to configure backups.'"
|
||||
},
|
||||
"resetOnHide": true
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
0
|
||||
1
|
||||
|
||||
Reference in New Issue
Block a user