Compare commits

..

9 Commits

Author SHA1 Message Date
Jeff McCune
b2ce455aa2 generate/platform: use platform metadata as source of truth (#200)
This patch addresses Nate's feedback that it's difficult to know what
platform is being operated on.

Previously it wasn't clear where the platform id used for push and pull
comes from.  The source of truth is the platform.metadata.json file
created when the platform is first generated using `holos generate
platform k3d`.

This patch removes the platformId field from the platform.config.json
file, renames the platform.config.json file to platform.model.json and
renames the internal symbols to match the domain language of "Platform
Model" instead of the less clear "config"

This patch also changes the API between holos and CUE to use the proto
json imported from the proto file instead of generated from the go code
generated from the proto file.  The purpose is to ensure protojson
encoding is used end to end.

Default log handler:

The patch also changes the default log output to print only the message
to stderr.  This addresses similar feedback from both Gary and Nate that
the output is skipped over because it feels like internal debug logs.

We still want 100% of output to go through the logger so we can ensure
each line can be made into valid json.  Info messages however are meant
for the user and all other attributes can be stripped off by default.
If additional source location is necessary, enable the text or json
output format.

Protobuf JSON:

This patch modifies the API contract between holos and CUE to ensure
data is exchanged exclusively using protojson.  This is necessary
because protobuf has a canonical json format which is not compatible
with the go json package struct tags.  When Holos handles a protobuf
message, it must marshal and unmarshal it using the protojson package.

Similarly, when importing protobuf messages into CUE, we must use `cue
import` instead of `cue go get` so that the canonical format is used
instead of the invalid go json struct tags.

Finally, when a Go struct like v1alpha1.Form is used to represent data
defined in cue which contains a nested protobuf message, Holos should
use a cue.Value to lookup the nested path, marshal it into json bytes,
then unmarshal it again using protojson.
2024-07-21 09:31:09 -07:00
Jeff McCune
90629b84b5 cli/delete: delete platform by uuid (#200)
Previously there was no way to delete a platform.  This patch adds a
basic delete subcommand which deletes platforms by their id using the
rpc api.

    ❯ holos get platform
    NAME         DESCRIPTION        AGE    ID
    k3d          Holos Local k3d    20h    0190c78a-4027-7a7e-82d0-0b9f400f4bc9
    k3d2         Holos Local k3d    20h    0190c7b3-382b-7212-81d6-ffcfc4a3fe7e
    k3dasdf      Holos Local k3d    20h    0190c7b3-728a-7212-b56d-2d2edf389003
    k3d9         Holos Local k3d    20h    0190c7b8-4c4e-7cea-9d3d-a6b9434ae438
    k3d-8581     Holos Local k3d    20h    0190c7ba-1de9-7cea-bff8-f15b51a56bdd
    k3d-13974    Holos Local k3d    20h    0190c7ba-5833-7cea-b863-8e5ffb926810
    k3d-20760    Holos Local k3d    19h    0190c7ba-7a12-7cea-a350-d55b4817d8bc

    ❯ holos delete platform 0190c7ba-1de9-7cea-bff8-f15b51a56bdd 0190c7ba-5833-7cea-b863-8e5ffb926810 0190c7ba-7a12-7cea-a350-d55b4817d8bc
    deleted platform k3d-8581
    deleted platform k3d-13974
    deleted platform k3d-20760
2024-07-19 09:54:48 -07:00
Jeff McCune
7f077f5347 cli/get: list platforms (#200)
Previously there was no way to get/list platforms.  This patch adds a
basic get subcommand with list as an alias to get the platforms
currently defined in the organization.

    ❯ holos get platform
    NAME         DESCRIPTION        AGE    ID
    k3d          Holos Local k3d    18h    0190c78a-4027-7a7e-82d0-0b9f400f4bc9
    k3d2         Holos Local k3d    17h    0190c7b3-382b-7212-81d6-ffcfc4a3fe7e
    k3dasdf      Holos Local k3d    17h    0190c7b3-728a-7212-b56d-2d2edf389003
    k3d9         Holos Local k3d    17h    0190c7b8-4c4e-7cea-9d3d-a6b9434ae438
    k3d-8581     Holos Local k3d    17h    0190c7ba-1de9-7cea-bff8-f15b51a56bdd
    k3d-13974    Holos Local k3d    17h    0190c7ba-5833-7cea-b863-8e5ffb926810
    k3d-20760    Holos Local k3d    17h    0190c7ba-7a12-7cea-a350-d55b4817d8bc
    k3d-13916    Holos Local k3d    17h    0190c7ba-8313-7cea-be37-41491c95ae79
    k3d-26154    Holos Local k3d    17h    0190c7ba-a117-7cea-8229-ce27da84135e

    ❯ holos get platform foo
    7:16AM ERR could not execute version=0.89.1 code=unknown err="not found"

    ❯ holos get platform foo k3d
    NAME    DESCRIPTION        AGE    ID
    k3d     Holos Local k3d    18h    0190c78a-4027-7a7e-82d0-0b9f400f4bc9
2024-07-19 07:16:43 -07:00
Jeff McCune
327193215b version: 0.89.1 2024-07-18 14:42:24 -07:00
Jeff McCune
b98b5cae3f PlatformService: do nothing when platform already exists
Previously the CreatePlatform rpc wrote over all fields when the
platform already exists.  This is surprising and basically the
UpdatePlatform rpc.

This patch changes the behavior to do nothing except set the
already_exists flag in the response message.

Users who have the use case of needing to know if the creation actually
created a new resource should use the API to check the already_exists
flag.  The CLI has no affordance for this other than parsing the log
messages.
2024-07-18 14:27:03 -07:00
Jeff McCune
ddba69517f version 0.89.0 2024-07-18 12:00:49 -07:00
Jeff McCune
e28642bca7 platform service: make (#205) create platform should be idempotent
Previously holos.platform.v1alpha1.PlatformService.CreatePlatform
returns an error for a request to create a platform of the same name as
an existing platform.

    holos create platform --name k3d --display-name "Try Holos Locally"

    8:00AM ERR could not execute version=0.87.2 code=failed_precondition
    err="failed_precondition: platform.go:55: ent: constraint failed:
    ERROR: duplicate key value violates unique constraint
    \"platform_org_id_name\" (SQLSTATE 23505)" loc=client.go:138

This patch makes the CreatePlatform rpc idempotent using the upsert API.
The already_exists bool field is added to CreatePlatformResponse
response to indicate to the client if the platform already exists or
not.

Result:

    holos create platform --display-name "Holos Local" --name k3d10

    11:53AM INF create.go:56 created platform k3d10 version=0.87.2
    name=k3d10 id=0190c731-1808-7e7d-9ccb-3d17434d0055
    org=0190c6d6-4974-7733-9f7b-5d759a3e60e7 exists=false

    holos create platform --display-name "Holos Local" --name k3d10

    11:53AM INF create.go:56 updated platform k3d10 version=0.87.2
    name=k3d10 id=0190c731-1808-7e7d-9ccb-3d17434d0055
    org=0190c6d6-4974-7733-9f7b-5d759a3e60e7 exists=true
2024-07-18 11:53:51 -07:00
Jeff McCune
dceb37b7ab tilt: run holos server locally in k3d (#205)
Previously I developed holos server in the dev-holos namespace of a
remote cluster.  This patch updates the Tilt configs to develop locally
against k3d quickly and easily.

The database is a CNPG database which replaces PGO.  This is simpler and
ligher weight, one container in one pod.  CNPG has no repo host like PGO
has.
2024-07-18 10:24:45 -07:00
Jeff McCune
f6340ea4fe runbooks: recover zitadel with cnpg
Replaces the previous PGO runbook, we no longer use PGO and use CNPG
instead.
2024-07-18 07:58:58 -07:00
59 changed files with 3610 additions and 764 deletions

View File

@@ -17,13 +17,20 @@
"coredns",
"crds",
"crossplane",
"cuecontext",
"cuelang",
"dnsmasq",
"dscacheutil",
"entgo",
"errgroup",
"fieldmaskpb",
"flushcache",
"gitops",
"grpcreflect",
"holos",
"httpbin",
"Infima",
"isatty",
"istiod",
"jetstack",
"killall",
@@ -32,21 +39,35 @@
"kustomize",
"libnss",
"loadbalancer",
"mattn",
"mxcl",
"myhostname",
"nameserver",
"organizationconnect",
"orgid",
"otelconnect",
"Parentspanid",
"platformconnect",
"promhttp",
"protojson",
"putenv",
"quickstart",
"retryable",
"spanid",
"spiffe",
"startupapicheck",
"structpb",
"systemconnect",
"tablewriter",
"Tiltfile",
"timestamppb",
"Traceid",
"traefik",
"uibutton",
"Upsert",
"urandom",
"userconnect",
"zerolog",
"zitadel"
]
}

1
.gitignore vendored
View File

@@ -7,6 +7,7 @@ coverage.out
/deploy/
.vscode/
tmp/
.DS_*
# In case we run through the tutorial in this directory.
/holos-k3d/

View File

@@ -9,7 +9,7 @@ if os.getenv('TILT_WRAPPER') != '1':
fail("could not run, ./hack/tilt/bin/tilt was not used to start tilt")
# Resource ids
holos_backend = 'Holos Backend'
holos_backend = 'Holos Server'
compile_id = 'Go Build'
# Default Registry.
@@ -61,8 +61,10 @@ docker_build_with_restart(
entrypoint=[
'/app/bin/holos.linux',
'server',
'--log-format=text',
'--oidc-issuer=https://login.holos.run',
'--oidc-audience=275571128859132936',
'--oidc-audience=275804490387516853@holos_quickstart', # auth proxy
'--oidc-audience=270319630705329162@holos_platform', # holos cli
],
dockerfile='./Dockerfile',
only=['./bin'],

View File

@@ -1 +0,0 @@
module: "github.com/holos-run/holos"

View File

@@ -104,13 +104,6 @@ git commit -m "holos generate platform k3d - $(holos --version)"
## Push the Platform Form
TODO: Describe what the Platform Form is. Why is it needed? To get a value
that varies which ArgoCD needs to make you an admin user.
GREAT IDEA: Add a --open to open the URL in the default browser when pushing so it's an obvious call to action.
Gary wasn't sure what to do with the SUB value... More call to action.
Push the Platform Form to the web service to provide top-level configuration
values from which the platform components derive their final configuration.
@@ -118,14 +111,8 @@ values from which the platform components derive their final configuration.
holos push platform form .
```
:::important
Visit the printed URL to view the Platform Form.
:::
![Platform Form](./platform-form.png)
:::tip
You have complete control over the form fields and validation rules.
@@ -147,8 +134,6 @@ holos login --print-claims | jq -r .sub
For the ArgoCD Git repository URL, enter the url of a public repository where
you will push your local `holos-k3d` repository.
TODO: Make it clear the repo needs to be created.
```bash
git remote add origin https://github.com/example/holos-k3d
git push origin HEAD:main
@@ -174,11 +159,14 @@ git add platform.config.json
git commit -m "Add platform model"
```
TODO: Do not warn people about storing secrets until the advanced doc about customizing the platform form.jj
:::danger
TODO: Pull out commentary about the reference platform. Only mention the reference platform at the beginning and end.
Do not store secrets in the Platform Model.
NATE: Secret Sauce is going from minimal input into a fully rendered platform. Not Zero Trust, not external secrets. Mention the value of deriving the entire unified platform from a simple customizable input form at the beginning and the end.
:::
Holos uses ExternalSecret resources to securely sync with a SecretStore and
ensure Secrets are never stored in version control.
## Render the Platform

Binary file not shown.

Before

Width:  |  Height:  |  Size: 558 KiB

View File

@@ -1,97 +1,10 @@
# PostgresCluster Backups
# ZITADEL Backups
This document describes how the S3 bucket for `PostgresCluster` backups is configured. These buckets are configured both for ZITADEL and for Holos
Server and are applicable to any service in Holos that stores data in a pgo `PostgresCluster` resource.
Refer to [Schedule backups](https://cloudnative-pg.io/documentation/1.23/backup/#scheduled-backups)
## Create the Bucket
Name: `holos-zitadel-backups` for `zitadel`
Name: `holos-server-backups` for `holos server`
> [!NOTE]
> The settings below match the default settings recommended by AWS.
By default ZITADEL is backed up daily to S3. When restoring into a new cluster
of the same name, increment the revision variable to create a new blank folder
for the new cluster WAL. The cluster will not initialize unless the WAL
directory is empty.
Object Ownership: `ACLs disabled` (recommended) Checked.
Block Public Access settings for this bucket: **`Block all public access`** Checked.
Bucket Versioning: `Disable`
Default encryption: `Server-side encryption with Amazon S3 managed keys (SSE-S3)`
Bucket Key: `Enable`
Object Lock: `Disable`
## Create an IAM Policy
Create one IAM Policy for each bucket to grant full access to the bucket. Replace the resource with each bucket name.
Name: `holos-zitadel-backups` for `zitadel`
Name: `holos-server-backups` for `holos server`
Description: `Read and write access to a specific bucket for pgrest operating within a pgo PostgresCluster.`
Policy JSON:
```json
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation",
"s3:ListAllMyBuckets"
],
"Resource": "arn:aws:s3:::*"
},
{
"Effect": "Allow",
"Action": "s3:*",
"Resource": [
"arn:aws:s3:::holos-zitadel-backups",
"arn:aws:s3:::holos-zitadel-backups/*"
]
}
]
}
```
## Create an IAM Group
Create an IAM Group to attach the policy granting access to the bucket.
Name: `holos-zitadel-backups` for `zitadel`
Attach permission policies: `holos-zitadel-backups`
Name: `holos-server-backups` for `holos server`
Attach permission policies: `holos-server-backups`
## Create the IAM User
Create an IAM User entity for each PostgresCluster. Do not provide user access to the AWS Management Console.
Name: `holos-zitadel-backups` for `zitadel`
Group: `holos-zitadel-backups`
Name: `holos-server-backups` for `holos server`
Group: `holos-server-backups`
## Create an Access Key
Create an access key for `pgbackrest` associated with the `PostgresCluster`.
Description:
> Used by pgbackrest associated with the PostgresCluster resource. Refer to the PostgresCluster resource pgbackrest.cofiguration.secret.name for the stored location of the access key. Synced from the Management Cluster using an ExternalSecret.
## Create the Secret
Create a `Secret` in the holos management cluster usable by pgbackrest. This is a secret with a single key, `s3.conf` with the following format:
```
[global]
repo2-cipher-pass=
repo2-s3-key=
repo2-s3-key-secret=
repo3-cipher-pass=
repo3-s3-key=
repo3-s3-key-secret=
```
> [!NOTE]
> Use the same values for repo2 and repo3. The purpose is to make space for migrating if need be in the future.
Generate the cipher pass using. This password is used to encrypt all backups using client side before the backup is written to the bucket.
```
tr -dc A-Za-z0-9 </dev/urandom | head -c 64
```
Store the secret into the management cluster:
```
holos create secret --namespace zitadel holos-zitadel-backups \
--append-hash=false --from-file .
```
```
holos create secret --namespace holos holos-server-backups \
--append-hash=false --from-file .
```
The cluster will recovery from the previous rev.

View File

@@ -1,150 +1,3 @@
# Postgres Full Backup
Suppose you delete all objects in the S3 bucket hosting all postgres backups. You want to take a full backup ASAP of an existing PostgreSQL database.
The normal method of annotating the `postgrescluster` resource will not work because the job will error:
```
kubectl annotate postgrescluster zitadel postgres-operator.crunchydata.com/pgbackrest-backup="$(date)" --overwrite
postgrescluster.postgres-operator.crunchydata.com/zitadel annotated
```
Backup fails:
```
k get pods
NAME READY STATUS RESTARTS AGE
zitadel-backup-hk7w-76bfk 0/1 Error 0 65s
zitadel-backup-hk7w-d55v6 0/1 Error 0 44s
zitadel-backup-hk7w-l9dwm 0/1 Error 0 76s
zitadel-backup-hk7w-zcg69 0/1 Error 0 3s
zitadel-pgbouncer-d9f8cffc-nx8lq 2/2 Running 0 49m
zitadel-pgbouncer-d9f8cffc-s7g7x 2/2 Running 0 49m
zitadel-pgha1-2xv2-0 5/5 Running 0 48m
zitadel-pgha1-78f4-0 5/5 Running 0 49m
zitadel-repo-host-0 2/2 Running 0 49m
```
Error is: `FileMissingError: unable to open missing file '/pgbackrest/prod-iam/zitadel/repo2/backup/db/backup.info.copy' for read`
```
time="2024-04-08T00:02:11Z" level=info msg="crunchy-pgbackrest starts"
time="2024-04-08T00:02:11Z" level=info msg="debug flag set to false"
time="2024-04-08T00:02:12Z" level=info msg="backrest backup command requested"
time="2024-04-08T00:02:12Z" level=info msg="command to execute is [pgbackrest backup --stanza=db --repo=2 --type=full]"
time="2024-04-08T00:02:12Z" level=info msg="output=[]"
time="2024-04-08T00:02:12Z" level=info msg="stderr=[ERROR: [055]: unable to load info file '/pgbackrest/prod-iam/zitadel/repo2/backup/db/backup.info' or '/pgbackrest/prod-iam/zitadel/repo2/backup/db/backup.info.copy':\n FileMissingError: unable to open missing file '/pgbackrest/prod-iam/zitadel/repo2/backup/db/backup.info' for read\n FileMissingError: unable to open missing file '/pgbackrest/prod-iam/zitadel/repo2/backup/db/backup.info.copy' for read\n HINT: backup.info cannot be opened and is required to perform a backup.\n HINT: has a stanza-create been performed?\n]"
time="2024-04-08T00:02:12Z" level=fatal msg="command terminated with exit code 55"
```
## Fix Process
We need to edit the postgrescluster. We're going to have the controller re-initialize the backup repository from scratch by removing it and re-adding it.
First, suspend flux:
```
flux suspend ks prod-iam-zitadel prod-iam-postgres
```
Save the config to two files:
```
kubectl get postgresclusters.postgres-operator.crunchydata.com zitadel -o yaml > orig.yaml
cp orig.yaml new.yaml
```
Remove the follow fields and re-apply the cluster. This will leave the cluster running and available while the controller reconciles the repo configuration:
```diff
--- orig.yaml 2024-04-07 17:08:26.834715820 -0700
+++ new.yaml 2024-04-07 17:08:57.418546067 -0700
@@ -4,6 +4,4 @@
annotations:
holos.run/description: ""
- postgres-operator.crunchydata.com/pgbackrest-backup: Sun 07 Apr 2024 05:01:35
- PM PDT
creationTimestamp: "2024-04-07T23:10:44Z"
finalizers:
@@ -26,12 +24,5 @@
repo1-retention-full: "1"
repo2-cipher-type: aes-256-cbc
- repo2-path: /pgbackrest/prod-iam/zitadel/repo2
- repo2-retention-full: "14"
- repo2-retention-full-type: time
image: registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:ubi8-2.49-0
- manual:
- options:
- - --type=full
- repoName: repo2
repos:
- name: repo1
@@ -43,12 +34,4 @@
requests:
storage: 4Gi
- - name: repo2
- s3:
- bucket: ois-zitadel-backups
- endpoint: s3.dualstack.us-east-2.amazonaws.com
- region: us-east-2
- schedules:
- differential: 0 1 * * 1-6
- full: 0 1 * * 0
restore:
enabled: true
```
Apply the config and wait for the controller to reconcile:
```
k apply --server-side=true -f new.yaml --force-conflicts
```
Check for reconciliation:
```
kubectl -n postgres-operator logs -l app.kubernetes.io/name=pgo | tail -1
```
```
time="2024-04-08T00:10:03Z" level=debug msg="reconciled cluster" controller=postgrescluster controllerGroup=postgres-operator.crunchydata.com controllerKind=PostgresCluster name=zitadel namespace=prod-iam postgresCluster=prod-iam/zitadel reconcileID=cc8c8eb7-9787-4504-8ecd-a04ec84fbc0b version=5.5.1-0-amd64
```
Re-add the repo host configuration
```
grep -v 'resourceVersion:' orig.yaml | k apply --server-side=true --force-conflicts -f-
```
```
postgrescluster.postgres-operator.crunchydata.com/zitadel serverside-applied
```
The full backup should be running and writing to S3 now:
```
kubectl logs -l postgres-operator.crunchydata.com/pgbackrest-backup=manual
```
```
time="2024-04-08T00:12:54Z" level=info msg="crunchy-pgbackrest starts"
time="2024-04-08T00:12:54Z" level=info msg="debug flag set to false"
time="2024-04-08T00:12:54Z" level=info msg="backrest backup command requested"
time="2024-04-08T00:12:54Z" level=info msg="command to execute is [pgbackrest backup --stanza=db --repo=2 --type=full]"
time="2024-04-08T00:16:02Z" level=info msg="output=[]"
time="2024-04-08T00:16:02Z" level=info msg="stderr=[]"
time="2024-04-08T00:16:02Z" level=info msg="crunchy-pgbackrest ends"
```
Finally, resume flux:
```
flux resume ks prod-iam-postgres prod-iam-zitadel
```
```
► resuming kustomization prod-iam-postgres in flux-system namespace
✔ kustomization resumed
► resuming kustomization prod-iam-zitadel in flux-system namespace
✔ kustomization resumed
```
Refer to [On-demand backups](https://cloudnative-pg.io/documentation/1.23/backup/#on-demand-backups)

View File

@@ -0,0 +1,2 @@
resources:
- https://raw.githubusercontent.com/cloudnative-pg/cloudnative-pg/release-1.23/releases/cnpg-1.23.2.yaml

View File

@@ -48,7 +48,7 @@ spec:
valueFrom:
secretKeyRef:
key: uri
name: holos-pguser-holos
name: holos-app
ports:
- containerPort: 3000
name: http

View File

@@ -0,0 +1,15 @@
---
# Source: CUE apiObjects.Cluster.holos
apiVersion: postgresql.cnpg.io/v1
kind: Cluster
metadata:
name: holos
namespace: dev-holos
labels:
app.holos.run/environment: dev
app.holos.run/name: holos
app.holos.run/component: database
spec:
instances: 1
storage:
size: 1Gi

View File

@@ -1,56 +0,0 @@
---
# Source: CUE apiObjects.PostgresCluster.holos
apiVersion: postgres-operator.crunchydata.com/v1beta1
kind: PostgresCluster
metadata:
name: holos
namespace: dev-holos
labels:
app.holos.run/environment: dev
app.holos.run/name: holos
app.holos.run/component: infra
render.holos.run/component: dev-holos-infra
annotations: {}
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: topology.kubernetes.io/zone
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

View File

@@ -0,0 +1,50 @@
---
# Source: CUE apiObjects.Job.holos
apiVersion: batch/v1
kind: Job
metadata:
name: holos-init
namespace: dev-holos
annotations:
helm.sh/hook: pre-install,pre-upgrade
helm.sh/hook-delete-policy: before-hook-creation
helm.sh/hook-weight: "2"
spec:
activeDeadlineSeconds: 300
backoffLimit: 5
template:
spec:
containers:
- name: holos
image: quay.io/holos-run/holos:v0.87.2-26-g3845174
imagePullPolicy: IfNotPresent
command:
- /app/bin/holos
- server
- init
- --log-level=debug
- --log-format=json
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
key: uri
name: holos-app
securityContext:
capabilities:
drop:
- ALL
runAsNonRoot: true
allowPrivilegeEscalation: false
resources:
limits:
cpu: "0.5"
memory: 512Mi
requests:
cpu: "0.5"
memory: 512Mi
restartPolicy: OnFailure
serviceAccountName: holos
securityContext:
seccompProfile:
type: RuntimeDefault

View File

@@ -17,6 +17,7 @@ import (
"cuelang.org/go/cue/load"
"github.com/holos-run/holos/api/core/v1alpha2"
"github.com/holos-run/holos/api/v1alpha1"
"google.golang.org/protobuf/encoding/protojson"
"github.com/holos-run/holos"
"github.com/holos-run/holos/internal/client"
@@ -123,12 +124,15 @@ func (b *Builder) Instances(ctx context.Context, cfg *client.Config) ([]*build.I
cueConfig := load.Config{Dir: dir}
// Get the platform model from the PlatformConfig
// Get the platform model.
pc, err := client.LoadPlatformConfig(ctx, dir)
if err != nil {
return nil, errors.Wrap(err)
}
data, err := json.Marshal(pc)
// Note proto format json relies on importing the proto file into CUE using
// cue import object.proto. Refer to internal/generate/platform/generate.go
// Importing the go generated from the proto gives incorrect field names.
data, err := protojson.Marshal(pc)
if err != nil {
return nil, errors.Wrap(err)
}

View File

@@ -12,6 +12,7 @@ type RunFunc func(c *cobra.Command, args []string) error
func New(name string) *cobra.Command {
cmd := &cobra.Command{
Use: name,
Short: name,
Version: version.Version,
Args: cobra.NoArgs,
CompletionOptions: cobra.CompletionOptions{

View File

@@ -1,6 +1,8 @@
package create
import (
"fmt"
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/cli/secret"
"github.com/holos-run/holos/internal/client"
@@ -41,12 +43,19 @@ func NewPlatform(cfg *client.Config) *cobra.Command {
cmd.RunE = func(cmd *cobra.Command, args []string) error {
ctx := cmd.Root().Context()
client := client.New(cfg)
pf, err := client.CreatePlatform(ctx, pm)
resp, err := client.CreatePlatform(ctx, pm)
if err != nil {
return err
}
log := logger.FromContext(ctx)
log.InfoContext(ctx, "created platform", "name", pf.GetName(), "id", pf.GetId(), "org", pf.GetOwner().GetOrgId())
action := "created"
if resp.GetAlreadyExists() {
action = "already exists"
}
pf := resp.GetPlatform()
name := pf.GetName()
log.InfoContext(ctx, fmt.Sprintf("platform %s %s", name, action), "name", name, "id", pf.GetId(), "org", pf.GetOwner().GetOrgId(), "exists", resp.GetAlreadyExists())
return nil
}

View File

@@ -0,0 +1,51 @@
package destroy
import (
"fmt"
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/client"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/holos"
"github.com/spf13/cobra"
)
// New returns the command for the cli
func New(cfg *holos.Config) *cobra.Command {
cmd := command.New("delete")
cmd.Aliases = []string{"destroy"}
cmd.Short = "delete resources"
cmd.Flags().SortFlags = false
cmd.RunE = func(c *cobra.Command, args []string) error {
return c.Usage()
}
// api client config
config := client.NewConfig(cfg)
// flags
cmd.PersistentFlags().SortFlags = false
// commands
cmd.AddCommand(NewPlatform(config))
return cmd
}
func NewPlatform(cfg *client.Config) *cobra.Command {
cmd := command.New("platform")
cmd.Args = cobra.MinimumNArgs(1)
cmd.RunE = func(cmd *cobra.Command, args []string) error {
ctx := cmd.Root().Context()
rpc := client.New(cfg)
for _, platformID := range args {
msg, err := rpc.DeletePlatform(ctx, platformID)
if err != nil {
return errors.Wrap(err)
}
fmt.Fprintln(cmd.OutOrStdout(), "deleted platform", msg.GetPlatform().GetName())
}
return nil
}
return cmd
}

View File

@@ -1,23 +1,79 @@
package get
import (
"errors"
"fmt"
"strings"
"text/tabwriter"
"time"
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/cli/secret"
"github.com/holos-run/holos/internal/client"
"github.com/holos-run/holos/internal/holos"
"github.com/spf13/cobra"
"k8s.io/kubectl/pkg/util/slice"
)
// New returns the get command for the cli.
func New(hc *holos.Config) *cobra.Command {
cmd := command.New("get")
cmd.Short = "get resources"
cmd.Aliases = []string{"list"}
cmd.Flags().SortFlags = false
cmd.RunE = func(c *cobra.Command, args []string) error {
return c.Usage()
}
// flags
cmd.PersistentFlags().SortFlags = false
// commands
cmd.AddCommand(secret.NewGetCmd(hc))
cmd.AddCommand(NewPlatform(hc))
return cmd
}
func NewPlatform(hc *holos.Config) *cobra.Command {
cmd := command.New("platform")
cmd.Aliases = []string{"platforms"}
cmd.Args = cobra.MinimumNArgs(0)
cmd.RunE = func(cmd *cobra.Command, args []string) error {
ctx := cmd.Root().Context()
clientContext := holos.NewClientContext(ctx)
rpc := client.New(client.NewConfig(hc))
msgs, err := rpc.Platforms(ctx, clientContext.OrgID)
if err != nil {
return err
}
now := time.Now()
rows := make([][]string, 0, len(msgs))
for _, msg := range msgs {
name := msg.GetName()
if len(args) > 0 && !slice.ContainsString(args, name, nil) {
continue
}
age := now.Sub(msg.GetDetail().GetCreatedAt().AsTime())
rows = append(rows, []string{
name,
msg.GetDisplayName(),
holos.RoundDuration(age),
msg.GetId(),
})
}
w := tabwriter.NewWriter(cmd.OutOrStdout(), 0, 0, 4, ' ', 0)
if len(rows) == 0 {
return errors.New("not found")
}
fmt.Fprintln(w, "NAME\tDESCRIPTION\tAGE\tID")
for _, row := range rows {
fmt.Fprintln(w, strings.Join(row, "\t"))
}
return w.Flush()
}
return cmd
}

View File

@@ -3,6 +3,8 @@
package pull
import (
"fmt"
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/client"
"github.com/holos-run/holos/internal/errors"
@@ -52,28 +54,25 @@ func NewPlatformConfig(cfg *client.Config) *cobra.Command {
rpc := client.New(cfg)
for _, name := range args {
// Get the platform metadata for the platform id.
pmd, err := client.LoadPlatform(ctx, name)
pmd, err := client.LoadPlatformMetadata(ctx, name)
if err != nil {
return errors.Wrap(err)
}
log := logger.FromContext(ctx).With("platform_id", pmd.GetId())
log := logger.FromContext(ctx).With("platform_name", pmd.GetName(), "platform_id", pmd.GetId())
// Get the platform model
model, err := rpc.PlatformModel(ctx, pmd.GetId())
if err != nil {
return errors.Wrap(err)
}
log.Info("pulled platform model")
log.DebugContext(ctx, "pulled platform "+pmd.GetName()+" model")
// Build the PlatformConfig
pc := &object.PlatformConfig{
PlatformId: pmd.GetId(),
PlatformModel: model,
}
pc := &object.PlatformConfig{PlatformModel: model}
// Save the PlatformConfig
path, err := client.SavePlatformConfig(ctx, name, pc)
if err != nil {
return errors.Wrap(err)
}
log.Info("saved platform config", "path", path)
log.DebugContext(ctx, fmt.Sprintf("wrote: %s for platform %s", path, pmd.GetName()), "path", path)
}
return nil
}

View File

@@ -54,7 +54,7 @@ func NewPlatformForm(cfg *client.Config) *cobra.Command {
rpc := client.New(cfg)
for _, name := range args {
// Get the platform metadata for the platform id.
p, err := client.LoadPlatform(ctx, name)
p, err := client.LoadPlatformMetadata(ctx, name)
if err != nil {
return errors.Wrap(err)
}
@@ -67,7 +67,7 @@ func NewPlatformForm(cfg *client.Config) *cobra.Command {
if err := rpc.UpdateForm(ctx, p.GetId(), form); err != nil {
return errors.Wrap(err)
}
slog.Default().InfoContext(ctx, fmt.Sprintf("pushed: %s/ui/platform/%s", cfg.Client().Server(), p.GetId()))
slog.Default().InfoContext(ctx, fmt.Sprintf("browse to form url: %s/ui/platform/%s", cfg.Client().Server(), p.GetId()))
}
return nil
}
@@ -88,17 +88,23 @@ func NewPlatformModel(cfg *client.Config) *cobra.Command {
ctx = logger.NewContext(ctx, logger.FromContext(ctx).With("server", cfg.Client().Server()))
rpc := client.New(cfg)
for _, name := range args {
// Get the platform config for the platform id.
p, err := client.LoadPlatformConfig(ctx, name)
// Get the platform metadata for the platform id.
pl, err := client.LoadPlatformMetadata(ctx, name)
if err != nil {
return errors.Wrap(err)
}
// Get the platform model
pm, err := client.LoadPlatformConfig(ctx, name)
if err != nil {
return errors.Wrap(err)
}
// Make the rpc call to update the platform form.
if err := rpc.UpdatePlatformModel(ctx, p.PlatformId, p.PlatformModel); err != nil {
if err := rpc.UpdatePlatformModel(ctx, pl.GetId(), pm.GetPlatformModel()); err != nil {
return errors.Wrap(err)
}
slog.Default().InfoContext(ctx, fmt.Sprintf("pushed: %s/ui/platform/%s", cfg.Client().Server(), p.PlatformId))
slog.Default().InfoContext(ctx, fmt.Sprintf("pushed: %s/ui/platform/%s", cfg.Client().Server(), pl.GetId()))
}
return nil
}

View File

@@ -17,6 +17,7 @@ import (
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/cli/controller"
"github.com/holos-run/holos/internal/cli/create"
"github.com/holos-run/holos/internal/cli/destroy"
"github.com/holos-run/holos/internal/cli/generate"
"github.com/holos-run/holos/internal/cli/get"
"github.com/holos-run/holos/internal/cli/kv"
@@ -72,6 +73,7 @@ func New(cfg *holos.Config) *cobra.Command {
rootCmd.AddCommand(render.New(cfg))
rootCmd.AddCommand(get.New(cfg))
rootCmd.AddCommand(create.New(cfg))
rootCmd.AddCommand(destroy.New(cfg))
rootCmd.AddCommand(preflight.New(cfg))
rootCmd.AddCommand(login.New(cfg))
rootCmd.AddCommand(logout.New(cfg))

View File

@@ -65,7 +65,7 @@ func (c *Client) Platforms(ctx context.Context, orgID string) ([]*platform.Platf
req := &platform.ListPlatformsRequest{
OrgId: orgID,
FieldMask: &fieldmaskpb.FieldMask{
Paths: []string{"id", "name", "displayName"},
Paths: []string{"id", "name", "displayName", "detail"},
},
}
resp, err := c.pltSvc.ListPlatforms(ctx, connect.NewRequest(req))
@@ -123,7 +123,7 @@ func (c *Client) PlatformModel(ctx context.Context, platformID string) (*structp
return pf.Msg.GetPlatform().GetSpec().GetModel(), nil
}
func (c *Client) CreatePlatform(ctx context.Context, pm PlatformMutation) (*platform.Platform, error) {
func (c *Client) CreatePlatform(ctx context.Context, pm PlatformMutation) (*platform.CreatePlatformResponse, error) {
log := logger.FromContext(ctx).With("platform", pm.Name)
start := time.Now()
req := &platform.CreatePlatformRequest{
@@ -139,5 +139,18 @@ func (c *Client) CreatePlatform(ctx context.Context, pm PlatformMutation) (*plat
}
log = log.With("platform_id", pf.Msg.GetPlatform().GetId())
log.DebugContext(ctx, "create platform", "duration", time.Since(start))
return pf.Msg.GetPlatform(), nil
return pf.Msg, nil
}
func (c *Client) DeletePlatform(ctx context.Context, platformID string) (*platform.DeletePlatformResponse, error) {
log := logger.FromContext(ctx).With("platform_id", platformID)
start := time.Now()
req := &platform.DeletePlatformRequest{PlatformId: platformID}
resp, err := c.pltSvc.DeletePlatform(ctx, connect.NewRequest(req))
if err != nil {
return nil, errors.Wrap(err)
}
name := resp.Msg.GetPlatform().GetName()
log.DebugContext(ctx, "deleted platform "+name, "name", name, "duration", time.Since(start))
return resp.Msg, nil
}

View File

@@ -12,18 +12,19 @@ import (
"google.golang.org/protobuf/encoding/protojson"
)
// PlatformMetadataFile is the platform metadata json file name located in the root
// of a platform directory.
// PlatformMetadataFile is the platform metadata json file name located in the
// root of a platform directory. This file is the authoritative source of truth
// for the PlatformID used in rpc calls to the PlatformService.
const PlatformMetadataFile = "platform.metadata.json"
// PlatformConfigFile is the marshaled json representation of the PlatformConfig
// DTO used to cache the data holos passes from the PlatformService to CUE when
// rendering platform components.
// PlatformConfigFile represents the marshaled json representation of the
// PlatformConfig DTO used to persist the inputs to the CUE platform code.
const PlatformConfigFile = "platform.config.json"
// LoadPlatform loads the platform.metadata.json file from a named path. Useful
// to obtain a platform id for PlatformService rpc methods.
func LoadPlatform(ctx context.Context, name string) (*platform.Platform, error) {
// LoadPlatformMetadata loads the platform.metadata.json file from a named path.
// Used as the authoritative source of truth to obtain a platform id for
// PlatformService rpc methods.
func LoadPlatformMetadata(ctx context.Context, name string) (*platform.Platform, error) {
data, err := os.ReadFile(filepath.Join(name, PlatformMetadataFile))
if err != nil {
return nil, fmt.Errorf("could not load platform metadata: %w", err)
@@ -32,6 +33,8 @@ func LoadPlatform(ctx context.Context, name string) (*platform.Platform, error)
if err := protojson.Unmarshal(data, p); err != nil {
return nil, fmt.Errorf("could not load platform metadata: %w", err)
}
log := logger.FromContext(ctx)
log.DebugContext(ctx, "loaded: "+p.GetName(), "path", PlatformMetadataFile, "name", p.GetName(), "display_name", p.GetDisplayName(), "id", p.GetId())
return p, nil
}
@@ -41,13 +44,13 @@ func LoadPlatform(ctx context.Context, name string) (*platform.Platform, error)
func LoadPlatformConfig(ctx context.Context, name string) (*object.PlatformConfig, error) {
data, err := os.ReadFile(filepath.Join(name, PlatformConfigFile))
if err != nil {
return nil, fmt.Errorf("could not load platform config: %w", err)
return nil, fmt.Errorf("could not load platform model: %w", err)
}
pc := &object.PlatformConfig{}
if err := protojson.Unmarshal(data, pc); err != nil {
return nil, fmt.Errorf("could not load platform config: %w", err)
p := &object.PlatformConfig{}
if err := protojson.Unmarshal(data, p); err != nil {
return nil, fmt.Errorf("could not load platform model: %w", err)
}
return pc, nil
return p, nil
}
// SavePlatformConfig writes pc to the platform root directory path identified by name.

View File

@@ -0,0 +1,49 @@
package console
import (
"context"
"fmt"
"io"
"log/slog"
"sync"
)
func NewHandler(out io.Writer, opts *Options) slog.Handler {
h := &ConsoleHandler{out: out, mu: &sync.Mutex{}}
if opts != nil {
h.opts = *opts
}
if h.opts.Level == nil {
h.opts.Level = slog.LevelInfo
}
return h
}
type Options struct {
Level slog.Leveler
}
type ConsoleHandler struct {
opts Options
mu *sync.Mutex
out io.Writer
}
func (h *ConsoleHandler) Enabled(ctx context.Context, level slog.Level) bool {
return level >= h.opts.Level.Level()
}
func (h *ConsoleHandler) Handle(ctx context.Context, r slog.Record) error {
h.mu.Lock()
defer h.mu.Unlock()
_, err := fmt.Fprintln(h.out, r.Message)
return err
}
func (h *ConsoleHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
return h
}
func (h *ConsoleHandler) WithGroup(name string) slog.Handler {
return h
}

View File

@@ -12,5 +12,5 @@
</style><link rel="stylesheet" href="styles-IHLR3ZBD.css" media="print" onload="this.media='all'"><noscript><link rel="stylesheet" href="styles-IHLR3ZBD.css"></noscript><link rel="modulepreload" href="chunk-EYHLAWIE.js"></head>
<body class="mat-typography">
<app-root></app-root>
<script src="polyfills-A7MJM4D4.js" type="module"></script><script src="main-PZVU2IPA.js" type="module"></script></body>
<script src="polyfills-A7MJM4D4.js" type="module"></script><script src="main-6TNXO3ZY.js" type="module"></script></body>
</html>

View File

@@ -332,8 +332,8 @@ export class ResourceOwner extends Message<ResourceOwner> {
*/
export class Form extends Message<Form> {
/**
* fields represents FormlyFieldConfig[] encoded as an array of JSON objects
* organized by section.
* field_configs represents FormlyFieldConfig[] encoded as an array of JSON
* objects organized by section.
*
* @generated from field: repeated google.protobuf.Struct field_configs = 1;
*/
@@ -369,22 +369,20 @@ export class Form extends Message<Form> {
/**
* PlatformConfig represents the data passed from the holos cli to CUE when
* rendering configuration.
* rendering configuration. At present it contains only the platform model from
* the PlatformService, but it is expected to carry additional fields from
* additional data sources. For this reason, there is a distinction in domain
* language between the "Platform Config" and the "Platform Model" The config
* is a data transfer object that carries at least the model. The model
* represents the form values from the PlatformService.
*
* @generated from message holos.object.v1alpha1.PlatformConfig
*/
export class PlatformConfig extends Message<PlatformConfig> {
/**
* Platform UUID.
* platform_model represents the form values from the PlatformService.
*
* @generated from field: string platform_id = 1;
*/
platformId = "";
/**
* Platform Model.
*
* @generated from field: google.protobuf.Struct platform_model = 2;
* @generated from field: google.protobuf.Struct platform_model = 1;
*/
platformModel?: Struct;
@@ -396,8 +394,7 @@ export class PlatformConfig extends Message<PlatformConfig> {
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.object.v1alpha1.PlatformConfig";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "platform_id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 2, name: "platform_model", kind: "message", T: Struct },
{ no: 1, name: "platform_model", kind: "message", T: Struct },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): PlatformConfig {

View File

@@ -3,7 +3,7 @@
/* eslint-disable */
// @ts-nocheck
import { CreatePlatformRequest, CreatePlatformResponse, GetPlatformRequest, GetPlatformResponse, ListPlatformsRequest, ListPlatformsResponse, UpdatePlatformRequest, UpdatePlatformResponse } from "./platform_service_pb.js";
import { CreatePlatformRequest, CreatePlatformResponse, DeletePlatformRequest, DeletePlatformResponse, GetPlatformRequest, GetPlatformResponse, ListPlatformsRequest, ListPlatformsResponse, UpdatePlatformRequest, UpdatePlatformResponse } from "./platform_service_pb.js";
import { MethodKind } from "@bufbuild/protobuf";
/**
@@ -48,6 +48,15 @@ export const PlatformService = {
O: ListPlatformsResponse,
kind: MethodKind.Unary,
},
/**
* @generated from rpc holos.platform.v1alpha1.PlatformService.DeletePlatform
*/
deletePlatform: {
name: "DeletePlatform",
I: DeletePlatformRequest,
O: DeletePlatformResponse,
kind: MethodKind.Unary,
},
}
} as const;

View File

@@ -60,6 +60,11 @@ export class CreatePlatformResponse extends Message<CreatePlatformResponse> {
*/
platform?: Platform;
/**
* @generated from field: bool already_exists = 2;
*/
alreadyExists = false;
constructor(data?: PartialMessage<CreatePlatformResponse>) {
super();
proto3.util.initPartial(data, this);
@@ -69,6 +74,7 @@ export class CreatePlatformResponse extends Message<CreatePlatformResponse> {
static readonly typeName = "holos.platform.v1alpha1.CreatePlatformResponse";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "platform", kind: "message", T: Platform },
{ no: 2, name: "already_exists", kind: "scalar", T: 8 /* ScalarType.BOOL */ },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): CreatePlatformResponse {
@@ -412,3 +418,77 @@ export class PlatformMutation extends Message<PlatformMutation> {
}
}
/**
* @generated from message holos.platform.v1alpha1.DeletePlatformRequest
*/
export class DeletePlatformRequest extends Message<DeletePlatformRequest> {
/**
* @generated from field: string platform_id = 1;
*/
platformId = "";
constructor(data?: PartialMessage<DeletePlatformRequest>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.platform.v1alpha1.DeletePlatformRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "platform_id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): DeletePlatformRequest {
return new DeletePlatformRequest().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): DeletePlatformRequest {
return new DeletePlatformRequest().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): DeletePlatformRequest {
return new DeletePlatformRequest().fromJsonString(jsonString, options);
}
static equals(a: DeletePlatformRequest | PlainMessage<DeletePlatformRequest> | undefined, b: DeletePlatformRequest | PlainMessage<DeletePlatformRequest> | undefined): boolean {
return proto3.util.equals(DeletePlatformRequest, a, b);
}
}
/**
* @generated from message holos.platform.v1alpha1.DeletePlatformResponse
*/
export class DeletePlatformResponse extends Message<DeletePlatformResponse> {
/**
* @generated from field: holos.platform.v1alpha1.Platform platform = 1;
*/
platform?: Platform;
constructor(data?: PartialMessage<DeletePlatformResponse>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.platform.v1alpha1.DeletePlatformResponse";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "platform", kind: "message", T: Platform },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): DeletePlatformResponse {
return new DeletePlatformResponse().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): DeletePlatformResponse {
return new DeletePlatformResponse().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): DeletePlatformResponse {
return new DeletePlatformResponse().fromJsonString(jsonString, options);
}
static equals(a: DeletePlatformResponse | PlainMessage<DeletePlatformResponse> | undefined, b: DeletePlatformResponse | PlainMessage<DeletePlatformResponse> | undefined): boolean {
return proto3.util.equals(DeletePlatformResponse, a, b);
}
}

View File

@@ -4,7 +4,6 @@ import (
"bytes"
"context"
"embed"
"encoding/json"
"fmt"
"io/fs"
"os"
@@ -14,6 +13,7 @@ import (
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/logger"
platform "github.com/holos-run/holos/service/gen/holos/platform/v1alpha1"
"google.golang.org/protobuf/encoding/protojson"
)
//go:embed all:platforms
@@ -66,7 +66,8 @@ func GeneratePlatform(ctx context.Context, rpc *client.Client, orgID string, nam
}
// Write the platform data.
data, err := json.MarshalIndent(rpcPlatform, "", " ")
encoder := protojson.MarshalOptions{Indent: " "}
data, err := encoder.Marshal(rpcPlatform)
if err != nil {
return errors.Wrap(err)
}
@@ -77,7 +78,7 @@ func GeneratePlatform(ctx context.Context, rpc *client.Client, orgID string, nam
if err := os.WriteFile(client.PlatformMetadataFile, data, 0644); err != nil {
return errors.Wrap(fmt.Errorf("could not write platform metadata: %w", err))
}
log.InfoContext(ctx, "wrote "+client.PlatformMetadataFile, "path", filepath.Join(getCwd(ctx), client.PlatformMetadataFile))
log.DebugContext(ctx, "wrote "+client.PlatformMetadataFile, "path", filepath.Join(getCwd(ctx), client.PlatformMetadataFile))
// Copy the cue.mod directory
if err := copyEmbedFS(ctx, platforms, filepath.Join(platformsRoot, "cue.mod"), "cue.mod", bytes.NewBuffer); err != nil {
@@ -89,7 +90,7 @@ func GeneratePlatform(ctx context.Context, rpc *client.Client, orgID string, nam
return errors.Wrap(err)
}
log.InfoContext(ctx, "generated platform "+name, "path", getCwd(ctx))
log.DebugContext(ctx, "generated platform "+name, "path", getCwd(ctx))
return nil
}

View File

@@ -1,126 +0,0 @@
// Code generated by cue get go. DO NOT EDIT.
//cue:generate cue get go github.com/holos-run/holos/service/gen/holos/object/v1alpha1
package object
import (
"google.golang.org/protobuf/types/known/timestamppb"
"google.golang.org/protobuf/types/known/structpb"
)
#Detail: {
// Created by entity
created_by?: null | #ResourceEditor @go(CreatedBy,*ResourceEditor) @protobuf(1,bytes,opt,json=createdBy,proto3,oneof)
// Created at timestamp
created_at?: null | timestamppb.#Timestamp @go(CreatedAt,*timestamppb.Timestamp) @protobuf(2,bytes,opt,json=createdAt,proto3)
// Updated by entity
updated_by?: null | #ResourceEditor @go(UpdatedBy,*ResourceEditor) @protobuf(3,bytes,opt,json=updatedBy,proto3,oneof)
// Updated at timestamp
updated_at?: null | timestamppb.#Timestamp @go(UpdatedAt,*timestamppb.Timestamp) @protobuf(4,bytes,opt,json=updatedAt,proto3)
}
// Subject represents the oidc iss and sub claims which uniquely identify a subject.
#Subject: {
// iss represents the oidc id token iss claim. Limits defined at
// https://openid.net/specs/openid-authentication-1_1.html#limits
iss?: string @go(Iss) @protobuf(1,bytes,opt,proto3)
// sub represents the oidc id token sub claim.
sub?: string @go(Sub) @protobuf(2,bytes,opt,proto3)
}
// UserRef refers to a User by uuid, email, or by the oidc iss and sub claims.
#UserRef: {
// Types that are assignable to User:
//
// *UserRef_UserId
// *UserRef_Email
// *UserRef_Subject
User: _#isUserRef_User
}
_#isUserRef_User: _
#UserRef_UserId: {
UserId: string @protobuf(1,bytes,opt,name=user_id,json=userId,proto3,oneof)
}
#UserRef_Email: {
Email: string @protobuf(2,bytes,opt,name=email,proto3,oneof)
}
#UserRef_Subject: {
Subject?: null | #Subject @go(,*Subject) @protobuf(3,bytes,opt,name=subject,proto3,oneof)
}
// Organization represents the ways in which a organization may be uniquely identified in the system.
#OrganizationRef: {
// Types that are assignable to Org:
//
// *OrganizationRef_OrgId
// *OrganizationRef_OrgName
Org: _#isOrganizationRef_Org
}
_#isOrganizationRef_Org: _
#OrganizationRef_OrgId: {
OrgId: string @protobuf(1,bytes,opt,name=org_id,json=orgId,proto3,oneof)
}
#OrganizationRef_OrgName: {
OrgName: string @protobuf(2,bytes,opt,name=org_name,json=orgName,proto3,oneof)
}
// ResourceEditor represents the entity that most recently created or edited a resource.
#ResourceEditor: {
// Types that are assignable to Editor:
//
// *ResourceEditor_UserId
Editor: _#isResourceEditor_Editor
}
_#isResourceEditor_Editor: _
#ResourceEditor_UserId: {
UserId: string @protobuf(1,bytes,opt,name=user_id,json=userId,proto3,oneof)
}
#ResourceOwner: {
// Types that are assignable to ResourceOwner:
//
// *ResourceOwner_OrgId
// *ResourceOwner_UserId
ResourceOwner: _#isResourceOwner_ResourceOwner
}
_#isResourceOwner_ResourceOwner: _
#ResourceOwner_OrgId: {
OrgId: string @protobuf(1,bytes,opt,name=org_id,json=orgId,proto3,oneof)
}
#ResourceOwner_UserId: {
UserId: string @protobuf(2,bytes,opt,name=user_id,json=userId,proto3,oneof)
}
// Form represents a Formly json powered form.
#Form: {
// fields represents FormlyFieldConfig[] encoded as an array of JSON objects
// organized by section.
field_configs?: [...null | structpb.#Struct] @go(FieldConfigs,[]*structpb.Struct) @protobuf(1,bytes,rep,json=fieldConfigs,proto3)
}
// PlatformConfig represents the data passed from the holos cli to CUE when
// rendering configuration.
#PlatformConfig: {
// Platform UUID.
platform_id?: string @go(PlatformId) @protobuf(1,bytes,opt,json=platformId,proto3)
// Platform Model.
platform_model?: null | structpb.#Struct @go(PlatformModel,*structpb.Struct) @protobuf(2,bytes,opt,json=platformModel,proto3)
}

View File

@@ -0,0 +1,90 @@
// For validation, see the [Standard constraints](https://github.com/bufbuild/protovalidate/blob/main/docs/standard-constraints.md)
package object
import "time"
#Detail: {
// Created by entity
createdBy?: #ResourceEditor @protobuf(1,ResourceEditor,name=created_by)
// Created at timestamp
createdAt?: time.Time @protobuf(2,google.protobuf.Timestamp,name=created_at,"(buf.validate.field).timestamp.lt_now")
// Updated by entity
updatedBy?: #ResourceEditor @protobuf(3,ResourceEditor,name=updated_by)
// Updated at timestamp
updatedAt?: time.Time @protobuf(4,google.protobuf.Timestamp,name=updated_at,"(buf.validate.field).timestamp.lt_now")
}
// Subject represents the oidc iss and sub claims which uniquely identify a subject.
#Subject: {
// iss represents the oidc id token iss claim. Limits defined at
// https://openid.net/specs/openid-authentication-1_1.html#limits
iss?: string @protobuf(1,string,"(buf.validate.field).string=")
// sub represents the oidc id token sub claim.
sub?: string @protobuf(2,string,"(buf.validate.field).string=")
}
// UserRef refers to a User by uuid, email, or by the oidc iss and sub claims.
#UserRef: {
{} | {
@protobuf(option (buf.validate.oneof).required=true)
} | {
userId: string @protobuf(1,string,name=user_id,"(buf.validate.field).string.uuid")
} | {
email: string @protobuf(2,string,"(buf.validate.field).string.email")
} | {
subject: #Subject @protobuf(3,Subject)
}
}
// Organization represents the ways in which a organization may be uniquely identified in the system.
#OrganizationRef: {
{} | {
@protobuf(option (buf.validate.oneof).required=true)
} | {
orgId: string @protobuf(1,string,name=org_id,"(buf.validate.field).string.uuid")
} | {
orgName: string @protobuf(2,string,name=org_name,"(buf.validate.field).cel=")
}
}
// ResourceEditor represents the entity that most recently created or edited a resource.
#ResourceEditor: {
{} | {
@protobuf(option (buf.validate.oneof).required=true)
} | {
userId: string @protobuf(1,string,name=user_id,"(buf.validate.field).string.uuid")
}
}
#ResourceOwner: {
{} | {
@protobuf(option (buf.validate.oneof).required=true)
} | {
orgId: string @protobuf(1,string,name=org_id,"(buf.validate.field).string.uuid")
} | {
userId: string @protobuf(2,string,name=user_id,"(buf.validate.field).string.uuid")
}
}
// Form represents a Formly json powered form.
#Form: {
// field_configs represents FormlyFieldConfig[] encoded as an array of JSON
// objects organized by section.
fieldConfigs?: [...{}] @protobuf(1,google.protobuf.Struct,name=field_configs)
}
// PlatformConfig represents the data passed from the holos cli to CUE when
// rendering configuration. At present it contains only the platform model from
// the PlatformService, but it is expected to carry additional fields from
// additional data sources. For this reason, there is a distinction in domain
// language between the "Platform Config" and the "Platform Model" The config
// is a data transfer object that carries at least the model. The model
// represents the form values from the PlatformService.
#PlatformConfig: {
// platform_model represents the form values from the PlatformService.
platformModel?: {} @protobuf(1,google.protobuf.Struct,name=platform_model)
}

View File

@@ -12,7 +12,7 @@ package v1alpha1
Sections: {[NAME=string]: #FormSection & {name: NAME}}
Output: #Form & {
spec: form: field_configs: [for s in Sections {s.wrapper}]
spec: form: fieldConfigs: [for s in Sections {s.wrapper}]
}
}

View File

@@ -0,0 +1,10 @@
// For validation, see the [Standard constraints](https://github.com/bufbuild/protovalidate/blob/main/docs/standard-constraints.md)
package object
#PlatformConfig: {
platformModel: {...} @protobuf(1,google.protobuf.Struct,name=platform_model)
}
#Form: {
fieldConfigs: [...{...}]
}

View File

@@ -9,4 +9,8 @@ package platforms
//go generate rm -rf cue.mod/gen/github.com/holos-run/holos/api/meta
//go:generate cue get go github.com/holos-run/holos/api/meta/...
//go generate rm -rf cue.mod/gen/github.com/holos-run/holos/service/gen/holos/object
//go:generate cue import ../../../service/holos/object/v1alpha1/object.proto -o cue.mod/gen/github.com/holos-run/holos/service/gen/holos/object/v1alpha1/object.proto_gen.cue -I ../../../proto -f
//go:generate rm -f cue.mod/gen/github.com/holos-run/holos/service/gen/holos/object/v1alpha1/object.pb_go_gen.cue
//go:generate touch ../platform.go

View File

@@ -43,7 +43,7 @@ _Fleets: #Fleets
// _Platform represents and provides a platform to holos for rendering.
_Platform: #Platform & {
Name: string @tag(platform_name, type=string)
Model: _PlatformConfig.platform_model
Model: _PlatformConfig.platformModel
}
// #Platform defines the shape of _Platform.
#Platform: {
@@ -53,7 +53,7 @@ _Platform: #Platform & {
Components: [string]: core.#PlatformSpecComponent
// Model represents the platform model from the web app form.
Model: dto.#PlatformConfig.platform_model
Model: dto.#PlatformConfig.platformModel
Output: core.#Platform & {
metadata: name: Name

View File

@@ -0,0 +1,26 @@
package holos
import (
"fmt"
"math"
"time"
)
// RoundDuration rounds a duration to the nearest unit based on its length.
func RoundDuration(duration time.Duration) string {
seconds := duration.Seconds()
switch {
case seconds < 60:
return fmt.Sprintf("%ds", int(math.Round(seconds)))
case seconds < 3600:
minutes := seconds / 60
return fmt.Sprintf("%dm", int(math.Round(minutes)))
case seconds < 86400:
hours := seconds / 3600
return fmt.Sprintf("%dh", int(math.Round(hours)))
default:
days := seconds / 86400
return fmt.Sprintf("%dd", int(math.Round(days)))
}
}

View File

@@ -13,6 +13,7 @@ import (
"strings"
"time"
"github.com/holos-run/holos/internal/console"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/tint"
"github.com/holos-run/holos/version"
@@ -23,7 +24,7 @@ import (
const ErrKey = "err"
var validLogLevels = []string{"debug", "info", "warn", "error"}
var validLogFormats = []string{"text", "json"}
var validLogFormats = []string{"text", "json", "console"}
// stringSlice is a comma separated list of string values
type stringSlice []string
@@ -42,7 +43,7 @@ func (s *stringSlice) Set(value string) error {
type key int
// https://cs.opensource.google/go/go/+/refs/tags/go1.21.1:src/context/context.go;l=140-158
// loggerKey is the key for *slog.Logs values in Contexts. It us unexported;
// loggerKey is the key for *slog.Logs values in Contexts. It is not exported;
// clients use NewContext and FromContext instead of this key directly.
var loggerKey key
@@ -159,7 +160,9 @@ func (c *Config) NewTopLevelLogger(w io.Writer) *slog.Logger {
func (c *Config) NewLogger(w io.Writer) *slog.Logger {
level := c.GetLogLevel()
var handler slog.Handler
if c.format == "text" {
switch c.format {
case "text":
noColor := true
if file, ok := w.(*os.File); ok {
noColor = !isatty.IsTerminal(file.Fd())
@@ -171,7 +174,9 @@ func (c *Config) NewLogger(w io.Writer) *slog.Logger {
ReplaceAttr: c.ReplaceAttr,
NoColor: noColor,
})
} else {
case "console":
handler = console.NewHandler(w, &console.Options{Level: level})
default:
handler = slog.NewJSONHandler(w, &slog.HandlerOptions{
Level: level,
AddSource: true,
@@ -187,7 +192,7 @@ func NewConfig() *Config {
f := flag.NewFlagSet("", flag.ContinueOnError)
c := &Config{flagSet: f}
f.StringVar(&c.level, "log-level", getenv("HOLOS_LOG_LEVEL", "info"), fmt.Sprintf("log level (%s)", strings.Join(validLogLevels, "|")))
f.StringVar(&c.format, "log-format", getenv("HOLOS_LOG_FORMAT", "text"), fmt.Sprintf("log format (%s)", strings.Join(validLogFormats, "|")))
f.StringVar(&c.format, "log-format", getenv("HOLOS_LOG_FORMAT", "console"), fmt.Sprintf("log format (%s)", strings.Join(validLogFormats, "|")))
f.Var(&c.dropAttrs, "log-drop", "log attributes to drop (example \"user-agent,version\")")
return c
}

View File

@@ -6,6 +6,7 @@ import (
"os"
"path/filepath"
"cuelang.org/go/cue"
"cuelang.org/go/cue/cuecontext"
"cuelang.org/go/cue/load"
"github.com/holos-run/holos"
@@ -31,9 +32,7 @@ type Instance struct {
mod holos.PathCueMod
}
// Export builds the cue instance into a JSON byte slice. Equivalent of cue
// export.
func (i *Instance) Export(ctx context.Context) ([]byte, error) {
func (i *Instance) Value(ctx context.Context) (*cue.Value, error) {
// CUE Loader
cfg := load.Config{Dir: string(i.mod)}
@@ -64,9 +63,20 @@ func (i *Instance) Export(ctx context.Context) ([]byte, error) {
return nil, errors.Wrap(fmt.Errorf("could not validate: %w", err))
}
return &value, nil
}
// Export builds the cue instance into a JSON byte slice. Equivalent of cue
// export.
func (i *Instance) Export(ctx context.Context) ([]byte, error) {
value, err := i.Value(ctx)
if err != nil {
return nil, errors.Wrap(err)
}
b, err := value.MarshalJSON()
if err != nil {
return nil, errors.Wrap(fmt.Errorf("could not marshal cue instance %s: %w", instance.Dir, err))
return nil, errors.Wrap(fmt.Errorf("could not marshal cue instance: %w", err))
}
return b, nil

View File

@@ -2,16 +2,19 @@
package push
import (
"bytes"
"context"
"encoding/json"
"fmt"
"path/filepath"
"cuelang.org/go/cue"
"github.com/holos-run/holos/api/v1alpha1"
"github.com/holos-run/holos/internal/errors"
object "github.com/holos-run/holos/service/gen/holos/object/v1alpha1"
"google.golang.org/protobuf/encoding/protojson"
)
const APIVersion = "holos.run/v1alpha1"
// PlatformForm builds a json powered web form from CUE code. The CUE code is
// expected to be derived from the code generated by the `holos generate
// platform` command.
@@ -23,17 +26,35 @@ func PlatformForm(ctx context.Context, name string) (*object.Form, error) {
return nil, errors.Wrap(err)
}
formData, err := instance.Export(ctx)
root, err := instance.Value(ctx)
if err != nil {
return nil, errors.Wrap(err)
}
form := &v1alpha1.Form{}
decoder := json.NewDecoder(bytes.NewReader(formData))
decoder.DisallowUnknownFields()
if err := decoder.Decode(form); err != nil {
var tm v1alpha1.TypeMeta
if err := root.Decode(&tm); err != nil {
return nil, errors.Wrap(err)
}
if tm.GetKind() != "Form" {
return nil, errors.Wrap(fmt.Errorf("want: Form have: %s", tm.GetKind()))
}
if tm.GetAPIVersion() != APIVersion {
return nil, errors.Wrap(fmt.Errorf("want: %s have: %s", APIVersion, tm.GetAPIVersion()))
}
// Extract the protobuf field to use protojson instead of json to unmarshal
// the value.
vForm := root.LookupPath(cue.ParsePath("spec.form"))
formData, err := vForm.MarshalJSON()
if err != nil {
return nil, errors.Wrap(err)
}
return &form.Spec.Form, nil
// Finally unmarshal the protobuf canonical json into the protobuf message.
m := &object.Form{}
if err := protojson.Unmarshal(formData, m); err != nil {
return nil, errors.Wrap(err)
}
return m, nil
}

View File

@@ -9,7 +9,6 @@ import (
"syscall"
"github.com/holos-run/holos"
"github.com/holos-run/holos/api/core/v1alpha2"
core "github.com/holos-run/holos/api/core/v1alpha2"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/server/middleware/logger"
@@ -44,7 +43,7 @@ func (hc *HelmChart) helm(ctx context.Context, r *Result, path holos.InstancePat
return nil
}
cachedChartPath := filepath.Join(string(path), v1alpha2.ChartDir, filepath.Base(hc.Component.Chart.Name))
cachedChartPath := filepath.Join(string(path), core.ChartDir, filepath.Base(hc.Component.Chart.Name))
if isNotExist(cachedChartPath) {
// Add repositories
repo := hc.Component.Chart.Repository
@@ -65,7 +64,7 @@ func (hc *HelmChart) helm(ctx context.Context, r *Result, path holos.InstancePat
}
// Cache the chart
if err := cacheChart(ctx, path, v1alpha2.ChartDir, hc.Component.Chart); err != nil {
if err := cacheChart(ctx, path, core.ChartDir, hc.Component.Chart); err != nil {
return fmt.Errorf("could not cache chart: %w", err)
}
}
@@ -117,7 +116,7 @@ func (hc *HelmChart) helm(ctx context.Context, r *Result, path holos.InstancePat
// the same filesystem via os.Rename. If a syscall.EEXIST error occurs during
// renaming, it indicates that the cached chart already exists, which is an
// expected scenario when this function is called concurrently.
func cacheChart(ctx context.Context, path holos.InstancePath, chartDir string, chart v1alpha2.Chart) error {
func cacheChart(ctx context.Context, path holos.InstancePath, chartDir string, chart core.Chart) error {
log := logger.FromContext(ctx)
cacheTemp, err := os.MkdirTemp(string(path), chartDir)

View File

@@ -49,7 +49,8 @@ func Platform(ctx context.Context, concurrency int, pf *core.Platform, stderr io
}
duration := time.Since(start)
log.InfoContext(ctx, "ok render component", "duration", duration)
msg := fmt.Sprintf("rendered %s for cluster %s in %s", component.Path, component.Cluster, duration)
log.InfoContext(ctx, msg, "duration", duration)
return nil
}
})

View File

@@ -4,8 +4,10 @@ import (
"context"
"fmt"
"reflect"
"time"
"connectrpc.com/connect"
"entgo.io/ent/dialect/sql"
"github.com/gofrs/uuid"
"github.com/holos-run/holos/internal/ent"
"github.com/holos-run/holos/internal/ent/organization"
@@ -42,21 +44,51 @@ func (h *PlatformHandler) CreatePlatform(ctx context.Context, req *connect.Reque
m := req.Msg.GetCreate()
builder := h.db.Platform.Create().
tryCreateID, err := uuid.NewV7()
if err != nil {
return nil, connect.NewError(connect.CodeInternal, errors.Wrap(err))
}
now := time.Now()
platformID, err := h.db.Platform.Create().
SetID(tryCreateID).
SetOrgID(dbOrg.ID).
SetCreatorID(dbUser.ID).
SetCreatedAt(now).
SetUpdatedByID(dbUser.ID).
SetUpdatedAt(now).
SetName(m.GetName()).
SetDisplayName(m.GetDisplayName()).
SetForm(&storage.Form{FieldConfigs: m.GetForm().GetFieldConfigs()}).
SetModel(&storage.Model{Model: m.GetModel()})
entPlatform, err := builder.Save(ctx)
SetModel(&storage.Model{Model: m.GetModel()}).
OnConflict(
sql.ConflictColumns(entplatform.FieldOrgID, entplatform.FieldName),
sql.ResolveWithIgnore(),
).
ID(ctx)
if err != nil {
return nil, connect.NewError(connect.CodeFailedPrecondition, errors.Wrap(err))
}
entPlatform, err := h.db.Platform.Get(ctx, platformID)
if err != nil {
return nil, connect.NewError(connect.CodeFailedPrecondition, errors.Wrap(err))
}
var already_exists bool
action := "created"
if tryCreateID != platformID {
already_exists = true
action = "already exists"
}
log := logger.FromContext(ctx)
log.InfoContext(ctx, fmt.Sprintf("platform %s %s in org %s", entPlatform.Name, action, dbOrg.ID))
resp := &platform.CreatePlatformResponse{
Platform: PlatformToRPC(entPlatform),
Platform: PlatformToRPC(entPlatform),
AlreadyExists: already_exists,
}
return connect.NewResponse(resp), nil
@@ -111,33 +143,6 @@ func (h *PlatformHandler) ListPlatforms(ctx context.Context, req *connect.Reques
return connect.NewResponse(resp), nil
}
// getEditor ensures the user identity stored in the context is a member of the
// organization. Useful to get the editor uuid for mutations. orgID must be a
// valid uuid string.
func getEditor(ctx context.Context, db *ent.Client, authnID authn.Identity, orgID string) (*ent.User, error) {
orgUUID, err := uuid.FromString(orgID)
if err != nil {
return nil, connect.NewError(connect.CodeInvalidArgument, errors.Wrap(err))
}
editor, err := db.User.Query().
Where(
user.And(
user.Iss(authnID.Issuer()),
user.Sub(authnID.Subject()),
user.HasOrganizationsWith(organization.ID(orgUUID)),
),
).Only(ctx)
if err != nil {
if ent.MaskNotFound(err) == nil {
return nil, connect.NewError(connect.CodeNotFound, errors.Wrap(err))
} else {
return nil, connect.NewError(connect.CodeFailedPrecondition, errors.Wrap(err))
}
}
return editor, nil
}
func (h *PlatformHandler) UpdatePlatform(
ctx context.Context,
req *connect.Request[platform.UpdatePlatformRequest],
@@ -224,6 +229,29 @@ func (h *PlatformHandler) UpdatePlatform(
return connect.NewResponse(&resp), nil
}
func (h *PlatformHandler) DeletePlatform(ctx context.Context, req *connect.Request[platform.DeletePlatformRequest]) (*connect.Response[platform.DeletePlatformResponse], error) {
authnID, err := authn.FromContext(ctx)
if err != nil {
return nil, connect.NewError(connect.CodePermissionDenied, errors.Wrap(err))
}
pl, err := h.getPlatform(ctx, req.Msg.GetPlatformId(), authnID)
if err != nil {
return nil, errors.Wrap(err)
}
err = h.db.Platform.DeleteOne(pl).Exec(ctx)
if err != nil {
return nil, connect.NewError(connect.CodeFailedPrecondition, errors.Wrap(err))
}
resp := platform.DeletePlatformResponse{
Platform: PlatformToRPC(pl),
}
return connect.NewResponse(&resp), nil
}
// getPlatform returns a platform by id ensuring the request comes from an
// identity that is a member of the organization owning the platform.
func (h *PlatformHandler) getPlatform(ctx context.Context, id string, uid authn.Identity) (*ent.Platform, error) {
@@ -251,6 +279,33 @@ func (h *PlatformHandler) getPlatform(ctx context.Context, id string, uid authn.
return p, nil
}
// getEditor ensures the user identity stored in the context is a member of the
// organization. Useful to get the editor uuid for mutations. orgID must be a
// valid uuid string.
func getEditor(ctx context.Context, db *ent.Client, authnID authn.Identity, orgID string) (*ent.User, error) {
orgUUID, err := uuid.FromString(orgID)
if err != nil {
return nil, connect.NewError(connect.CodeInvalidArgument, errors.Wrap(err))
}
editor, err := db.User.Query().
Where(
user.And(
user.Iss(authnID.Issuer()),
user.Sub(authnID.Subject()),
user.HasOrganizationsWith(organization.ID(orgUUID)),
),
).Only(ctx)
if err != nil {
if ent.MaskNotFound(err) == nil {
return nil, connect.NewError(connect.CodeNotFound, errors.Wrap(err))
} else {
return nil, connect.NewError(connect.CodeFailedPrecondition, errors.Wrap(err))
}
}
return editor, nil
}
func PlatformToRPC(entity *ent.Platform) *platform.Platform {
return &platform.Platform{
Id: entity.ID.String(),

View File

@@ -0,0 +1,862 @@
syntax = "proto2";
package validate;
option go_package = "github.com/envoyproxy/protoc-gen-validate/validate";
option java_package = "io.envoyproxy.pgv.validate";
import "google/protobuf/descriptor.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";
// Validation rules applied at the message level
extend google.protobuf.MessageOptions {
// Disabled nullifies any validation rules for this message, including any
// message fields associated with it that do support validation.
optional bool disabled = 1071;
// Ignore skips generation of validation methods for this message.
optional bool ignored = 1072;
}
// Validation rules applied at the oneof level
extend google.protobuf.OneofOptions {
// Required ensures that exactly one the field options in a oneof is set;
// validation fails if no fields in the oneof are set.
optional bool required = 1071;
}
// Validation rules applied at the field level
extend google.protobuf.FieldOptions {
// Rules specify the validations to be performed on this field. By default,
// no validation is performed against a field.
optional FieldRules rules = 1071;
}
// FieldRules encapsulates the rules for each type of field. Depending on the
// field, the correct set should be used to ensure proper validations.
message FieldRules {
optional MessageRules message = 17;
oneof type {
// Scalar Field Types
FloatRules float = 1;
DoubleRules double = 2;
Int32Rules int32 = 3;
Int64Rules int64 = 4;
UInt32Rules uint32 = 5;
UInt64Rules uint64 = 6;
SInt32Rules sint32 = 7;
SInt64Rules sint64 = 8;
Fixed32Rules fixed32 = 9;
Fixed64Rules fixed64 = 10;
SFixed32Rules sfixed32 = 11;
SFixed64Rules sfixed64 = 12;
BoolRules bool = 13;
StringRules string = 14;
BytesRules bytes = 15;
// Complex Field Types
EnumRules enum = 16;
RepeatedRules repeated = 18;
MapRules map = 19;
// Well-Known Field Types
AnyRules any = 20;
DurationRules duration = 21;
TimestampRules timestamp = 22;
}
}
// FloatRules describes the constraints applied to `float` values
message FloatRules {
// Const specifies that this field must be exactly the specified value
optional float const = 1;
// Lt specifies that this field must be less than the specified value,
// exclusive
optional float lt = 2;
// Lte specifies that this field must be less than or equal to the
// specified value, inclusive
optional float lte = 3;
// Gt specifies that this field must be greater than the specified value,
// exclusive. If the value of Gt is larger than a specified Lt or Lte, the
// range is reversed.
optional float gt = 4;
// Gte specifies that this field must be greater than or equal to the
// specified value, inclusive. If the value of Gte is larger than a
// specified Lt or Lte, the range is reversed.
optional float gte = 5;
// In specifies that this field must be equal to one of the specified
// values
repeated float in = 6;
// NotIn specifies that this field cannot be equal to one of the specified
// values
repeated float not_in = 7;
// IgnoreEmpty specifies that the validation rules of this field should be
// evaluated only if the field is not empty
optional bool ignore_empty = 8;
}
// DoubleRules describes the constraints applied to `double` values
message DoubleRules {
// Const specifies that this field must be exactly the specified value
optional double const = 1;
// Lt specifies that this field must be less than the specified value,
// exclusive
optional double lt = 2;
// Lte specifies that this field must be less than or equal to the
// specified value, inclusive
optional double lte = 3;
// Gt specifies that this field must be greater than the specified value,
// exclusive. If the value of Gt is larger than a specified Lt or Lte, the
// range is reversed.
optional double gt = 4;
// Gte specifies that this field must be greater than or equal to the
// specified value, inclusive. If the value of Gte is larger than a
// specified Lt or Lte, the range is reversed.
optional double gte = 5;
// In specifies that this field must be equal to one of the specified
// values
repeated double in = 6;
// NotIn specifies that this field cannot be equal to one of the specified
// values
repeated double not_in = 7;
// IgnoreEmpty specifies that the validation rules of this field should be
// evaluated only if the field is not empty
optional bool ignore_empty = 8;
}
// Int32Rules describes the constraints applied to `int32` values
message Int32Rules {
// Const specifies that this field must be exactly the specified value
optional int32 const = 1;
// Lt specifies that this field must be less than the specified value,
// exclusive
optional int32 lt = 2;
// Lte specifies that this field must be less than or equal to the
// specified value, inclusive
optional int32 lte = 3;
// Gt specifies that this field must be greater than the specified value,
// exclusive. If the value of Gt is larger than a specified Lt or Lte, the
// range is reversed.
optional int32 gt = 4;
// Gte specifies that this field must be greater than or equal to the
// specified value, inclusive. If the value of Gte is larger than a
// specified Lt or Lte, the range is reversed.
optional int32 gte = 5;
// In specifies that this field must be equal to one of the specified
// values
repeated int32 in = 6;
// NotIn specifies that this field cannot be equal to one of the specified
// values
repeated int32 not_in = 7;
// IgnoreEmpty specifies that the validation rules of this field should be
// evaluated only if the field is not empty
optional bool ignore_empty = 8;
}
// Int64Rules describes the constraints applied to `int64` values
message Int64Rules {
// Const specifies that this field must be exactly the specified value
optional int64 const = 1;
// Lt specifies that this field must be less than the specified value,
// exclusive
optional int64 lt = 2;
// Lte specifies that this field must be less than or equal to the
// specified value, inclusive
optional int64 lte = 3;
// Gt specifies that this field must be greater than the specified value,
// exclusive. If the value of Gt is larger than a specified Lt or Lte, the
// range is reversed.
optional int64 gt = 4;
// Gte specifies that this field must be greater than or equal to the
// specified value, inclusive. If the value of Gte is larger than a
// specified Lt or Lte, the range is reversed.
optional int64 gte = 5;
// In specifies that this field must be equal to one of the specified
// values
repeated int64 in = 6;
// NotIn specifies that this field cannot be equal to one of the specified
// values
repeated int64 not_in = 7;
// IgnoreEmpty specifies that the validation rules of this field should be
// evaluated only if the field is not empty
optional bool ignore_empty = 8;
}
// UInt32Rules describes the constraints applied to `uint32` values
message UInt32Rules {
// Const specifies that this field must be exactly the specified value
optional uint32 const = 1;
// Lt specifies that this field must be less than the specified value,
// exclusive
optional uint32 lt = 2;
// Lte specifies that this field must be less than or equal to the
// specified value, inclusive
optional uint32 lte = 3;
// Gt specifies that this field must be greater than the specified value,
// exclusive. If the value of Gt is larger than a specified Lt or Lte, the
// range is reversed.
optional uint32 gt = 4;
// Gte specifies that this field must be greater than or equal to the
// specified value, inclusive. If the value of Gte is larger than a
// specified Lt or Lte, the range is reversed.
optional uint32 gte = 5;
// In specifies that this field must be equal to one of the specified
// values
repeated uint32 in = 6;
// NotIn specifies that this field cannot be equal to one of the specified
// values
repeated uint32 not_in = 7;
// IgnoreEmpty specifies that the validation rules of this field should be
// evaluated only if the field is not empty
optional bool ignore_empty = 8;
}
// UInt64Rules describes the constraints applied to `uint64` values
message UInt64Rules {
// Const specifies that this field must be exactly the specified value
optional uint64 const = 1;
// Lt specifies that this field must be less than the specified value,
// exclusive
optional uint64 lt = 2;
// Lte specifies that this field must be less than or equal to the
// specified value, inclusive
optional uint64 lte = 3;
// Gt specifies that this field must be greater than the specified value,
// exclusive. If the value of Gt is larger than a specified Lt or Lte, the
// range is reversed.
optional uint64 gt = 4;
// Gte specifies that this field must be greater than or equal to the
// specified value, inclusive. If the value of Gte is larger than a
// specified Lt or Lte, the range is reversed.
optional uint64 gte = 5;
// In specifies that this field must be equal to one of the specified
// values
repeated uint64 in = 6;
// NotIn specifies that this field cannot be equal to one of the specified
// values
repeated uint64 not_in = 7;
// IgnoreEmpty specifies that the validation rules of this field should be
// evaluated only if the field is not empty
optional bool ignore_empty = 8;
}
// SInt32Rules describes the constraints applied to `sint32` values
message SInt32Rules {
// Const specifies that this field must be exactly the specified value
optional sint32 const = 1;
// Lt specifies that this field must be less than the specified value,
// exclusive
optional sint32 lt = 2;
// Lte specifies that this field must be less than or equal to the
// specified value, inclusive
optional sint32 lte = 3;
// Gt specifies that this field must be greater than the specified value,
// exclusive. If the value of Gt is larger than a specified Lt or Lte, the
// range is reversed.
optional sint32 gt = 4;
// Gte specifies that this field must be greater than or equal to the
// specified value, inclusive. If the value of Gte is larger than a
// specified Lt or Lte, the range is reversed.
optional sint32 gte = 5;
// In specifies that this field must be equal to one of the specified
// values
repeated sint32 in = 6;
// NotIn specifies that this field cannot be equal to one of the specified
// values
repeated sint32 not_in = 7;
// IgnoreEmpty specifies that the validation rules of this field should be
// evaluated only if the field is not empty
optional bool ignore_empty = 8;
}
// SInt64Rules describes the constraints applied to `sint64` values
message SInt64Rules {
// Const specifies that this field must be exactly the specified value
optional sint64 const = 1;
// Lt specifies that this field must be less than the specified value,
// exclusive
optional sint64 lt = 2;
// Lte specifies that this field must be less than or equal to the
// specified value, inclusive
optional sint64 lte = 3;
// Gt specifies that this field must be greater than the specified value,
// exclusive. If the value of Gt is larger than a specified Lt or Lte, the
// range is reversed.
optional sint64 gt = 4;
// Gte specifies that this field must be greater than or equal to the
// specified value, inclusive. If the value of Gte is larger than a
// specified Lt or Lte, the range is reversed.
optional sint64 gte = 5;
// In specifies that this field must be equal to one of the specified
// values
repeated sint64 in = 6;
// NotIn specifies that this field cannot be equal to one of the specified
// values
repeated sint64 not_in = 7;
// IgnoreEmpty specifies that the validation rules of this field should be
// evaluated only if the field is not empty
optional bool ignore_empty = 8;
}
// Fixed32Rules describes the constraints applied to `fixed32` values
message Fixed32Rules {
// Const specifies that this field must be exactly the specified value
optional fixed32 const = 1;
// Lt specifies that this field must be less than the specified value,
// exclusive
optional fixed32 lt = 2;
// Lte specifies that this field must be less than or equal to the
// specified value, inclusive
optional fixed32 lte = 3;
// Gt specifies that this field must be greater than the specified value,
// exclusive. If the value of Gt is larger than a specified Lt or Lte, the
// range is reversed.
optional fixed32 gt = 4;
// Gte specifies that this field must be greater than or equal to the
// specified value, inclusive. If the value of Gte is larger than a
// specified Lt or Lte, the range is reversed.
optional fixed32 gte = 5;
// In specifies that this field must be equal to one of the specified
// values
repeated fixed32 in = 6;
// NotIn specifies that this field cannot be equal to one of the specified
// values
repeated fixed32 not_in = 7;
// IgnoreEmpty specifies that the validation rules of this field should be
// evaluated only if the field is not empty
optional bool ignore_empty = 8;
}
// Fixed64Rules describes the constraints applied to `fixed64` values
message Fixed64Rules {
// Const specifies that this field must be exactly the specified value
optional fixed64 const = 1;
// Lt specifies that this field must be less than the specified value,
// exclusive
optional fixed64 lt = 2;
// Lte specifies that this field must be less than or equal to the
// specified value, inclusive
optional fixed64 lte = 3;
// Gt specifies that this field must be greater than the specified value,
// exclusive. If the value of Gt is larger than a specified Lt or Lte, the
// range is reversed.
optional fixed64 gt = 4;
// Gte specifies that this field must be greater than or equal to the
// specified value, inclusive. If the value of Gte is larger than a
// specified Lt or Lte, the range is reversed.
optional fixed64 gte = 5;
// In specifies that this field must be equal to one of the specified
// values
repeated fixed64 in = 6;
// NotIn specifies that this field cannot be equal to one of the specified
// values
repeated fixed64 not_in = 7;
// IgnoreEmpty specifies that the validation rules of this field should be
// evaluated only if the field is not empty
optional bool ignore_empty = 8;
}
// SFixed32Rules describes the constraints applied to `sfixed32` values
message SFixed32Rules {
// Const specifies that this field must be exactly the specified value
optional sfixed32 const = 1;
// Lt specifies that this field must be less than the specified value,
// exclusive
optional sfixed32 lt = 2;
// Lte specifies that this field must be less than or equal to the
// specified value, inclusive
optional sfixed32 lte = 3;
// Gt specifies that this field must be greater than the specified value,
// exclusive. If the value of Gt is larger than a specified Lt or Lte, the
// range is reversed.
optional sfixed32 gt = 4;
// Gte specifies that this field must be greater than or equal to the
// specified value, inclusive. If the value of Gte is larger than a
// specified Lt or Lte, the range is reversed.
optional sfixed32 gte = 5;
// In specifies that this field must be equal to one of the specified
// values
repeated sfixed32 in = 6;
// NotIn specifies that this field cannot be equal to one of the specified
// values
repeated sfixed32 not_in = 7;
// IgnoreEmpty specifies that the validation rules of this field should be
// evaluated only if the field is not empty
optional bool ignore_empty = 8;
}
// SFixed64Rules describes the constraints applied to `sfixed64` values
message SFixed64Rules {
// Const specifies that this field must be exactly the specified value
optional sfixed64 const = 1;
// Lt specifies that this field must be less than the specified value,
// exclusive
optional sfixed64 lt = 2;
// Lte specifies that this field must be less than or equal to the
// specified value, inclusive
optional sfixed64 lte = 3;
// Gt specifies that this field must be greater than the specified value,
// exclusive. If the value of Gt is larger than a specified Lt or Lte, the
// range is reversed.
optional sfixed64 gt = 4;
// Gte specifies that this field must be greater than or equal to the
// specified value, inclusive. If the value of Gte is larger than a
// specified Lt or Lte, the range is reversed.
optional sfixed64 gte = 5;
// In specifies that this field must be equal to one of the specified
// values
repeated sfixed64 in = 6;
// NotIn specifies that this field cannot be equal to one of the specified
// values
repeated sfixed64 not_in = 7;
// IgnoreEmpty specifies that the validation rules of this field should be
// evaluated only if the field is not empty
optional bool ignore_empty = 8;
}
// BoolRules describes the constraints applied to `bool` values
message BoolRules {
// Const specifies that this field must be exactly the specified value
optional bool const = 1;
}
// StringRules describe the constraints applied to `string` values
message StringRules {
// Const specifies that this field must be exactly the specified value
optional string const = 1;
// Len specifies that this field must be the specified number of
// characters (Unicode code points). Note that the number of
// characters may differ from the number of bytes in the string.
optional uint64 len = 19;
// MinLen specifies that this field must be the specified number of
// characters (Unicode code points) at a minimum. Note that the number of
// characters may differ from the number of bytes in the string.
optional uint64 min_len = 2;
// MaxLen specifies that this field must be the specified number of
// characters (Unicode code points) at a maximum. Note that the number of
// characters may differ from the number of bytes in the string.
optional uint64 max_len = 3;
// LenBytes specifies that this field must be the specified number of bytes
optional uint64 len_bytes = 20;
// MinBytes specifies that this field must be the specified number of bytes
// at a minimum
optional uint64 min_bytes = 4;
// MaxBytes specifies that this field must be the specified number of bytes
// at a maximum
optional uint64 max_bytes = 5;
// Pattern specifies that this field must match against the specified
// regular expression (RE2 syntax). The included expression should elide
// any delimiters.
optional string pattern = 6;
// Prefix specifies that this field must have the specified substring at
// the beginning of the string.
optional string prefix = 7;
// Suffix specifies that this field must have the specified substring at
// the end of the string.
optional string suffix = 8;
// Contains specifies that this field must have the specified substring
// anywhere in the string.
optional string contains = 9;
// NotContains specifies that this field cannot have the specified substring
// anywhere in the string.
optional string not_contains = 23;
// In specifies that this field must be equal to one of the specified
// values
repeated string in = 10;
// NotIn specifies that this field cannot be equal to one of the specified
// values
repeated string not_in = 11;
// WellKnown rules provide advanced constraints against common string
// patterns
oneof well_known {
// Email specifies that the field must be a valid email address as
// defined by RFC 5322
bool email = 12;
// Hostname specifies that the field must be a valid hostname as
// defined by RFC 1034. This constraint does not support
// internationalized domain names (IDNs).
bool hostname = 13;
// Ip specifies that the field must be a valid IP (v4 or v6) address.
// Valid IPv6 addresses should not include surrounding square brackets.
bool ip = 14;
// Ipv4 specifies that the field must be a valid IPv4 address.
bool ipv4 = 15;
// Ipv6 specifies that the field must be a valid IPv6 address. Valid
// IPv6 addresses should not include surrounding square brackets.
bool ipv6 = 16;
// Uri specifies that the field must be a valid, absolute URI as defined
// by RFC 3986
bool uri = 17;
// UriRef specifies that the field must be a valid URI as defined by RFC
// 3986 and may be relative or absolute.
bool uri_ref = 18;
// Address specifies that the field must be either a valid hostname as
// defined by RFC 1034 (which does not support internationalized domain
// names or IDNs), or it can be a valid IP (v4 or v6).
bool address = 21;
// Uuid specifies that the field must be a valid UUID as defined by
// RFC 4122
bool uuid = 22;
// WellKnownRegex specifies a common well known pattern defined as a regex.
KnownRegex well_known_regex = 24;
}
// This applies to regexes HTTP_HEADER_NAME and HTTP_HEADER_VALUE to enable
// strict header validation.
// By default, this is true, and HTTP header validations are RFC-compliant.
// Setting to false will enable a looser validations that only disallows
// \r\n\0 characters, which can be used to bypass header matching rules.
optional bool strict = 25 [default = true];
// IgnoreEmpty specifies that the validation rules of this field should be
// evaluated only if the field is not empty
optional bool ignore_empty = 26;
}
// WellKnownRegex contain some well-known patterns.
enum KnownRegex {
UNKNOWN = 0;
// HTTP header name as defined by RFC 7230.
HTTP_HEADER_NAME = 1;
// HTTP header value as defined by RFC 7230.
HTTP_HEADER_VALUE = 2;
}
// BytesRules describe the constraints applied to `bytes` values
message BytesRules {
// Const specifies that this field must be exactly the specified value
optional bytes const = 1;
// Len specifies that this field must be the specified number of bytes
optional uint64 len = 13;
// MinLen specifies that this field must be the specified number of bytes
// at a minimum
optional uint64 min_len = 2;
// MaxLen specifies that this field must be the specified number of bytes
// at a maximum
optional uint64 max_len = 3;
// Pattern specifies that this field must match against the specified
// regular expression (RE2 syntax). The included expression should elide
// any delimiters.
optional string pattern = 4;
// Prefix specifies that this field must have the specified bytes at the
// beginning of the string.
optional bytes prefix = 5;
// Suffix specifies that this field must have the specified bytes at the
// end of the string.
optional bytes suffix = 6;
// Contains specifies that this field must have the specified bytes
// anywhere in the string.
optional bytes contains = 7;
// In specifies that this field must be equal to one of the specified
// values
repeated bytes in = 8;
// NotIn specifies that this field cannot be equal to one of the specified
// values
repeated bytes not_in = 9;
// WellKnown rules provide advanced constraints against common byte
// patterns
oneof well_known {
// Ip specifies that the field must be a valid IP (v4 or v6) address in
// byte format
bool ip = 10;
// Ipv4 specifies that the field must be a valid IPv4 address in byte
// format
bool ipv4 = 11;
// Ipv6 specifies that the field must be a valid IPv6 address in byte
// format
bool ipv6 = 12;
}
// IgnoreEmpty specifies that the validation rules of this field should be
// evaluated only if the field is not empty
optional bool ignore_empty = 14;
}
// EnumRules describe the constraints applied to enum values
message EnumRules {
// Const specifies that this field must be exactly the specified value
optional int32 const = 1;
// DefinedOnly specifies that this field must be only one of the defined
// values for this enum, failing on any undefined value.
optional bool defined_only = 2;
// In specifies that this field must be equal to one of the specified
// values
repeated int32 in = 3;
// NotIn specifies that this field cannot be equal to one of the specified
// values
repeated int32 not_in = 4;
}
// MessageRules describe the constraints applied to embedded message values.
// For message-type fields, validation is performed recursively.
message MessageRules {
// Skip specifies that the validation rules of this field should not be
// evaluated
optional bool skip = 1;
// Required specifies that this field must be set
optional bool required = 2;
}
// RepeatedRules describe the constraints applied to `repeated` values
message RepeatedRules {
// MinItems specifies that this field must have the specified number of
// items at a minimum
optional uint64 min_items = 1;
// MaxItems specifies that this field must have the specified number of
// items at a maximum
optional uint64 max_items = 2;
// Unique specifies that all elements in this field must be unique. This
// constraint is only applicable to scalar and enum types (messages are not
// supported).
optional bool unique = 3;
// Items specifies the constraints to be applied to each item in the field.
// Repeated message fields will still execute validation against each item
// unless skip is specified here.
optional FieldRules items = 4;
// IgnoreEmpty specifies that the validation rules of this field should be
// evaluated only if the field is not empty
optional bool ignore_empty = 5;
}
// MapRules describe the constraints applied to `map` values
message MapRules {
// MinPairs specifies that this field must have the specified number of
// KVs at a minimum
optional uint64 min_pairs = 1;
// MaxPairs specifies that this field must have the specified number of
// KVs at a maximum
optional uint64 max_pairs = 2;
// NoSparse specifies values in this field cannot be unset. This only
// applies to map's with message value types.
optional bool no_sparse = 3;
// Keys specifies the constraints to be applied to each key in the field.
optional FieldRules keys = 4;
// Values specifies the constraints to be applied to the value of each key
// in the field. Message values will still have their validations evaluated
// unless skip is specified here.
optional FieldRules values = 5;
// IgnoreEmpty specifies that the validation rules of this field should be
// evaluated only if the field is not empty
optional bool ignore_empty = 6;
}
// AnyRules describe constraints applied exclusively to the
// `google.protobuf.Any` well-known type
message AnyRules {
// Required specifies that this field must be set
optional bool required = 1;
// In specifies that this field's `type_url` must be equal to one of the
// specified values.
repeated string in = 2;
// NotIn specifies that this field's `type_url` must not be equal to any of
// the specified values.
repeated string not_in = 3;
}
// DurationRules describe the constraints applied exclusively to the
// `google.protobuf.Duration` well-known type
message DurationRules {
// Required specifies that this field must be set
optional bool required = 1;
// Const specifies that this field must be exactly the specified value
optional google.protobuf.Duration const = 2;
// Lt specifies that this field must be less than the specified value,
// exclusive
optional google.protobuf.Duration lt = 3;
// Lt specifies that this field must be less than the specified value,
// inclusive
optional google.protobuf.Duration lte = 4;
// Gt specifies that this field must be greater than the specified value,
// exclusive
optional google.protobuf.Duration gt = 5;
// Gte specifies that this field must be greater than the specified value,
// inclusive
optional google.protobuf.Duration gte = 6;
// In specifies that this field must be equal to one of the specified
// values
repeated google.protobuf.Duration in = 7;
// NotIn specifies that this field cannot be equal to one of the specified
// values
repeated google.protobuf.Duration not_in = 8;
}
// TimestampRules describe the constraints applied exclusively to the
// `google.protobuf.Timestamp` well-known type
message TimestampRules {
// Required specifies that this field must be set
optional bool required = 1;
// Const specifies that this field must be exactly the specified value
optional google.protobuf.Timestamp const = 2;
// Lt specifies that this field must be less than the specified value,
// exclusive
optional google.protobuf.Timestamp lt = 3;
// Lte specifies that this field must be less than the specified value,
// inclusive
optional google.protobuf.Timestamp lte = 4;
// Gt specifies that this field must be greater than the specified value,
// exclusive
optional google.protobuf.Timestamp gt = 5;
// Gte specifies that this field must be greater than the specified value,
// inclusive
optional google.protobuf.Timestamp gte = 6;
// LtNow specifies that this must be less than the current time. LtNow
// can only be used with the Within rule.
optional bool lt_now = 7;
// GtNow specifies that this must be greater than the current time. GtNow
// can only be used with the Within rule.
optional bool gt_now = 8;
// Within specifies that this field must be within this duration of the
// current time. This constraint can be used alone or with the LtNow and
// GtNow rules.
optional google.protobuf.Duration within = 9;
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,115 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto3";
package google.protobuf;
option cc_enable_arenas = true;
option go_package = "google.golang.org/protobuf/types/known/durationpb";
option java_package = "com.google.protobuf";
option java_outer_classname = "DurationProto";
option java_multiple_files = true;
option objc_class_prefix = "GPB";
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
// A Duration represents a signed, fixed-length span of time represented
// as a count of seconds and fractions of seconds at nanosecond
// resolution. It is independent of any calendar and concepts like "day"
// or "month". It is related to Timestamp in that the difference between
// two Timestamp values is a Duration and it can be added or subtracted
// from a Timestamp. Range is approximately +-10,000 years.
//
// # Examples
//
// Example 1: Compute Duration from two Timestamps in pseudo code.
//
// Timestamp start = ...;
// Timestamp end = ...;
// Duration duration = ...;
//
// duration.seconds = end.seconds - start.seconds;
// duration.nanos = end.nanos - start.nanos;
//
// if (duration.seconds < 0 && duration.nanos > 0) {
// duration.seconds += 1;
// duration.nanos -= 1000000000;
// } else if (duration.seconds > 0 && duration.nanos < 0) {
// duration.seconds -= 1;
// duration.nanos += 1000000000;
// }
//
// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
//
// Timestamp start = ...;
// Duration duration = ...;
// Timestamp end = ...;
//
// end.seconds = start.seconds + duration.seconds;
// end.nanos = start.nanos + duration.nanos;
//
// if (end.nanos < 0) {
// end.seconds -= 1;
// end.nanos += 1000000000;
// } else if (end.nanos >= 1000000000) {
// end.seconds += 1;
// end.nanos -= 1000000000;
// }
//
// Example 3: Compute Duration from datetime.timedelta in Python.
//
// td = datetime.timedelta(days=3, minutes=10)
// duration = Duration()
// duration.FromTimedelta(td)
//
// # JSON Mapping
//
// In JSON format, the Duration type is encoded as a string rather than an
// object, where the string ends in the suffix "s" (indicating seconds) and
// is preceded by the number of seconds, with nanoseconds expressed as
// fractional seconds. For example, 3 seconds with 0 nanoseconds should be
// encoded in JSON format as "3s", while 3 seconds and 1 nanosecond should
// be expressed in JSON format as "3.000000001s", and 3 seconds and 1
// microsecond should be expressed in JSON format as "3.000001s".
//
message Duration {
// Signed seconds of the span of time. Must be from -315,576,000,000
// to +315,576,000,000 inclusive. Note: these bounds are computed from:
// 60 sec/min * 60 min/hr * 24 hr/day * 365.25 days/year * 10000 years
int64 seconds = 1;
// Signed fractions of a second at nanosecond resolution of the span
// of time. Durations less than one second are represented with a 0
// `seconds` field and a positive or negative `nanos` field. For durations
// of one second or more, a non-zero value for the `nanos` field must be
// of the same sign as the `seconds` field. Must be from -999,999,999
// to +999,999,999 inclusive.
int32 nanos = 2;
}

View File

@@ -0,0 +1,95 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto3";
package google.protobuf;
option cc_enable_arenas = true;
option go_package = "google.golang.org/protobuf/types/known/structpb";
option java_package = "com.google.protobuf";
option java_outer_classname = "StructProto";
option java_multiple_files = true;
option objc_class_prefix = "GPB";
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
// `Struct` represents a structured data value, consisting of fields
// which map to dynamically typed values. In some languages, `Struct`
// might be supported by a native representation. For example, in
// scripting languages like JS a struct is represented as an
// object. The details of that representation are described together
// with the proto support for the language.
//
// The JSON representation for `Struct` is JSON object.
message Struct {
// Unordered map of dynamically typed values.
map<string, Value> fields = 1;
}
// `Value` represents a dynamically typed value which can be either
// null, a number, a string, a boolean, a recursive struct value, or a
// list of values. A producer of value is expected to set one of these
// variants. Absence of any variant indicates an error.
//
// The JSON representation for `Value` is JSON value.
message Value {
// The kind of value.
oneof kind {
// Represents a null value.
NullValue null_value = 1;
// Represents a double value.
double number_value = 2;
// Represents a string value.
string string_value = 3;
// Represents a boolean value.
bool bool_value = 4;
// Represents a structured value.
Struct struct_value = 5;
// Represents a repeated `Value`.
ListValue list_value = 6;
}
}
// `NullValue` is a singleton enumeration to represent the null value for the
// `Value` type union.
//
// The JSON representation for `NullValue` is JSON `null`.
enum NullValue {
// Null value.
NULL_VALUE = 0;
}
// `ListValue` is a wrapper around a repeated field of values.
//
// The JSON representation for `ListValue` is JSON array.
message ListValue {
// Repeated field of dynamically typed values.
repeated Value values = 1;
}

View File

@@ -0,0 +1,144 @@
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
syntax = "proto3";
package google.protobuf;
option cc_enable_arenas = true;
option go_package = "google.golang.org/protobuf/types/known/timestamppb";
option java_package = "com.google.protobuf";
option java_outer_classname = "TimestampProto";
option java_multiple_files = true;
option objc_class_prefix = "GPB";
option csharp_namespace = "Google.Protobuf.WellKnownTypes";
// A Timestamp represents a point in time independent of any time zone or local
// calendar, encoded as a count of seconds and fractions of seconds at
// nanosecond resolution. The count is relative to an epoch at UTC midnight on
// January 1, 1970, in the proleptic Gregorian calendar which extends the
// Gregorian calendar backwards to year one.
//
// All minutes are 60 seconds long. Leap seconds are "smeared" so that no leap
// second table is needed for interpretation, using a [24-hour linear
// smear](https://developers.google.com/time/smear).
//
// The range is from 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z. By
// restricting to that range, we ensure that we can convert to and from [RFC
// 3339](https://www.ietf.org/rfc/rfc3339.txt) date strings.
//
// # Examples
//
// Example 1: Compute Timestamp from POSIX `time()`.
//
// Timestamp timestamp;
// timestamp.set_seconds(time(NULL));
// timestamp.set_nanos(0);
//
// Example 2: Compute Timestamp from POSIX `gettimeofday()`.
//
// struct timeval tv;
// gettimeofday(&tv, NULL);
//
// Timestamp timestamp;
// timestamp.set_seconds(tv.tv_sec);
// timestamp.set_nanos(tv.tv_usec * 1000);
//
// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
//
// FILETIME ft;
// GetSystemTimeAsFileTime(&ft);
// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
//
// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
// Timestamp timestamp;
// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
//
// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
//
// long millis = System.currentTimeMillis();
//
// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
// .setNanos((int) ((millis % 1000) * 1000000)).build();
//
// Example 5: Compute Timestamp from Java `Instant.now()`.
//
// Instant now = Instant.now();
//
// Timestamp timestamp =
// Timestamp.newBuilder().setSeconds(now.getEpochSecond())
// .setNanos(now.getNano()).build();
//
// Example 6: Compute Timestamp from current time in Python.
//
// timestamp = Timestamp()
// timestamp.GetCurrentTime()
//
// # JSON Mapping
//
// In JSON format, the Timestamp type is encoded as a string in the
// [RFC 3339](https://www.ietf.org/rfc/rfc3339.txt) format. That is, the
// format is "{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z"
// where {year} is always expressed using four digits while {month}, {day},
// {hour}, {min}, and {sec} are zero-padded to two digits each. The fractional
// seconds, which can go up to 9 digits (i.e. up to 1 nanosecond resolution),
// are optional. The "Z" suffix indicates the timezone ("UTC"); the timezone
// is required. A proto3 JSON serializer should always use UTC (as indicated by
// "Z") when printing the Timestamp type and a proto3 JSON parser should be
// able to accept both UTC and other timezones (as indicated by an offset).
//
// For example, "2017-01-15T01:30:15.01Z" encodes 15.01 seconds past
// 01:30 UTC on January 15, 2017.
//
// In JavaScript, one can convert a Date object to this format using the
// standard
// [toISOString()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString)
// method. In Python, a standard `datetime.datetime` object can be converted
// to this format using
// [`strftime`](https://docs.python.org/2/library/time.html#time.strftime) with
// the time format spec '%Y-%m-%dT%H:%M:%S.%fZ'. Likewise, in Java, one can use
// the Joda Time's [`ISODateTimeFormat.dateTime()`](
// http://joda-time.sourceforge.net/apidocs/org/joda/time/format/ISODateTimeFormat.html#dateTime()
// ) to obtain a formatter capable of generating timestamps in this format.
//
message Timestamp {
// Represents seconds of UTC time since Unix epoch
// 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
// 9999-12-31T23:59:59Z inclusive.
int64 seconds = 1;
// Non-negative fractions of a second at nanosecond resolution. Negative
// second values with fractions must still have non-negative nanos values
// that count forward in time. Must be from 0 to 999,999,999
// inclusive.
int32 nanos = 2;
}

View File

@@ -4,5 +4,5 @@ deps:
- remote: buf.build
owner: bufbuild
repository: protovalidate
commit: 46a4cf4ba1094a34bcd89a6c67163b4b
digest: shake256:436ce453801917c11bc7b21d66bcfae87da2aceb804a041487be1e51dc9fbc219e61ea6a552db7a7aa6d63bb5efd0f3ed5fe3d4c42d4f750d0eb35f14144e3b6
commit: a6c49f84cc0f4e038680d390392e2ab0
digest: shake256:3deb629c655e469d87c58babcfbed403275a741fb4a269366c4fd6ea9db012cf562a1e64819508d73670c506f96d01f724c43bc97b44e2e02aa6e8bbdd160ab2

View File

@@ -490,8 +490,8 @@ type Form struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// fields represents FormlyFieldConfig[] encoded as an array of JSON objects
// organized by section.
// field_configs represents FormlyFieldConfig[] encoded as an array of JSON
// objects organized by section.
FieldConfigs []*structpb.Struct `protobuf:"bytes,1,rep,name=field_configs,json=fieldConfigs,proto3" json:"field_configs,omitempty"`
}
@@ -535,16 +535,19 @@ func (x *Form) GetFieldConfigs() []*structpb.Struct {
}
// PlatformConfig represents the data passed from the holos cli to CUE when
// rendering configuration.
// rendering configuration. At present it contains only the platform model from
// the PlatformService, but it is expected to carry additional fields from
// additional data sources. For this reason, there is a distinction in domain
// language between the "Platform Config" and the "Platform Model" The config
// is a data transfer object that carries at least the model. The model
// represents the form values from the PlatformService.
type PlatformConfig struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// Platform UUID.
PlatformId string `protobuf:"bytes,1,opt,name=platform_id,json=platformId,proto3" json:"platform_id,omitempty"`
// Platform Model.
PlatformModel *structpb.Struct `protobuf:"bytes,2,opt,name=platform_model,json=platformModel,proto3" json:"platform_model,omitempty"`
// platform_model represents the form values from the PlatformService.
PlatformModel *structpb.Struct `protobuf:"bytes,1,opt,name=platform_model,json=platformModel,proto3" json:"platform_model,omitempty"`
}
func (x *PlatformConfig) Reset() {
@@ -579,13 +582,6 @@ func (*PlatformConfig) Descriptor() ([]byte, []int) {
return file_holos_object_v1alpha1_object_proto_rawDescGZIP(), []int{7}
}
func (x *PlatformConfig) GetPlatformId() string {
if x != nil {
return x.PlatformId
}
return ""
}
func (x *PlatformConfig) GetPlatformModel() *structpb.Struct {
if x != nil {
return x.PlatformModel
@@ -678,20 +674,17 @@ var file_holos_object_v1alpha1_object_proto_rawDesc = []byte{
0x5f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0c, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x43, 0x6f,
0x6e, 0x66, 0x69, 0x67, 0x73, 0x22, 0x7b, 0x0a, 0x0e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x29, 0x0a, 0x0b, 0x70, 0x6c, 0x61, 0x74, 0x66,
0x6f, 0x72, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48,
0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x0a, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d,
0x49, 0x64, 0x12, 0x3e, 0x0a, 0x0e, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x6d,
0x6f, 0x64, 0x65, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72,
0x75, 0x63, 0x74, 0x52, 0x0d, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x4d, 0x6f, 0x64,
0x65, 0x6c, 0x42, 0x45, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
0x2f, 0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2d, 0x72, 0x75, 0x6e, 0x2f, 0x68, 0x6f, 0x6c, 0x6f, 0x73,
0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x68, 0x6f, 0x6c,
0x6f, 0x73, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
0x61, 0x31, 0x3b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x33,
0x6e, 0x66, 0x69, 0x67, 0x73, 0x22, 0x50, 0x0a, 0x0e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
0x6d, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x3e, 0x0a, 0x0e, 0x70, 0x6c, 0x61, 0x74, 0x66,
0x6f, 0x72, 0x6d, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x52, 0x0d, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f,
0x72, 0x6d, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x42, 0x45, 0x5a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75,
0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2d, 0x72, 0x75, 0x6e, 0x2f,
0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x67, 0x65,
0x6e, 0x2f, 0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2f, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2f, 0x76,
0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x62, 0x06,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

View File

@@ -84,7 +84,8 @@ type CreatePlatformResponse struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Platform *Platform `protobuf:"bytes,1,opt,name=platform,proto3" json:"platform,omitempty"`
Platform *Platform `protobuf:"bytes,1,opt,name=platform,proto3" json:"platform,omitempty"`
AlreadyExists bool `protobuf:"varint,2,opt,name=already_exists,json=alreadyExists,proto3" json:"already_exists,omitempty"`
}
func (x *CreatePlatformResponse) Reset() {
@@ -126,6 +127,13 @@ func (x *CreatePlatformResponse) GetPlatform() *Platform {
return nil
}
func (x *CreatePlatformResponse) GetAlreadyExists() bool {
if x != nil {
return x.AlreadyExists
}
return false
}
type GetPlatformRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -524,6 +532,100 @@ func (x *PlatformMutation) GetForm() *v1alpha1.Form {
return nil
}
type DeletePlatformRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
PlatformId string `protobuf:"bytes,1,opt,name=platform_id,json=platformId,proto3" json:"platform_id,omitempty"`
}
func (x *DeletePlatformRequest) Reset() {
*x = DeletePlatformRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_holos_platform_v1alpha1_platform_service_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DeletePlatformRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeletePlatformRequest) ProtoMessage() {}
func (x *DeletePlatformRequest) ProtoReflect() protoreflect.Message {
mi := &file_holos_platform_v1alpha1_platform_service_proto_msgTypes[9]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeletePlatformRequest.ProtoReflect.Descriptor instead.
func (*DeletePlatformRequest) Descriptor() ([]byte, []int) {
return file_holos_platform_v1alpha1_platform_service_proto_rawDescGZIP(), []int{9}
}
func (x *DeletePlatformRequest) GetPlatformId() string {
if x != nil {
return x.PlatformId
}
return ""
}
type DeletePlatformResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Platform *Platform `protobuf:"bytes,1,opt,name=platform,proto3" json:"platform,omitempty"`
}
func (x *DeletePlatformResponse) Reset() {
*x = DeletePlatformResponse{}
if protoimpl.UnsafeEnabled {
mi := &file_holos_platform_v1alpha1_platform_service_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DeletePlatformResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeletePlatformResponse) ProtoMessage() {}
func (x *DeletePlatformResponse) ProtoReflect() protoreflect.Message {
mi := &file_holos_platform_v1alpha1_platform_service_proto_msgTypes[10]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeletePlatformResponse.ProtoReflect.Descriptor instead.
func (*DeletePlatformResponse) Descriptor() ([]byte, []int) {
return file_holos_platform_v1alpha1_platform_service_proto_rawDescGZIP(), []int{10}
}
func (x *DeletePlatformResponse) GetPlatform() *Platform {
if x != nil {
return x.Platform
}
return nil
}
var File_holos_platform_v1alpha1_platform_service_proto protoreflect.FileDescriptor
var file_holos_platform_v1alpha1_platform_service_proto_rawDesc = []byte{
@@ -550,146 +652,166 @@ var file_holos_platform_v1alpha1_platform_service_proto_rawDesc = []byte{
0x6f, 0x6c, 0x6f, 0x73, 0x2e, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x76, 0x31,
0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x4d,
0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x22,
0x57, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
0x7e, 0x0a, 0x16, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x08, 0x70, 0x6c, 0x61,
0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x6f,
0x6c, 0x6f, 0x73, 0x2e, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x61,
0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x08,
0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x22, 0x7a, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x50,
0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29,
0x0a, 0x0b, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20,
0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x0a, 0x70,
0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x49, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x66, 0x69, 0x65,
0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e,
0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e,
0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64,
0x4d, 0x61, 0x73, 0x6b, 0x22, 0x54, 0x0a, 0x13, 0x47, 0x65, 0x74, 0x50, 0x6c, 0x61, 0x74, 0x66,
0x6f, 0x72, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x08, 0x70,
0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e,
0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2e, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x76,
0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d,
0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x22, 0xd7, 0x01, 0x0a, 0x15, 0x55,
0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x0b, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d,
0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03,
0xb0, 0x01, 0x01, 0x52, 0x0a, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x49, 0x64, 0x12,
0x41, 0x0a, 0x06, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32,
0x29, 0x2e, 0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2e, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d,
0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f,
0x72, 0x6d, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x75, 0x70, 0x64, 0x61,
0x74, 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73,
0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d,
0x61, 0x73, 0x6b, 0x48, 0x00, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73,
0x6b, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f,
0x6d, 0x61, 0x73, 0x6b, 0x22, 0x57, 0x0a, 0x16, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6c,
0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d,
0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
0x32, 0x21, 0x2e, 0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2e, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
0x6d, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66,
0x6f, 0x72, 0x6d, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x22, 0x72, 0x0a,
0x14, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x06, 0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52,
0x05, 0x6f, 0x72, 0x67, 0x49, 0x64, 0x12, 0x39, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f,
0x6d, 0x61, 0x73, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f,
0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65,
0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73,
0x6b, 0x22, 0x58, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3f, 0x0a, 0x09, 0x70, 0x6c,
0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e,
0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2e, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x76,
0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d,
0x52, 0x09, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x22, 0xe1, 0x06, 0x0a, 0x10,
0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x12, 0xfe, 0x02, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42,
0xe4, 0x02, 0xba, 0x48, 0xe0, 0x02, 0xba, 0x01, 0x4a, 0x0a, 0x14, 0x6e, 0x61, 0x6d, 0x65, 0x2e,
0x6e, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x12,
0x1b, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x77, 0x69,
0x74, 0x68, 0x20, 0x61, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x2e, 0x1a, 0x15, 0x21, 0x74,
0x68, 0x69, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x73, 0x57, 0x69, 0x74, 0x68, 0x28, 0x27,
0x2d, 0x27, 0x29, 0xba, 0x01, 0x44, 0x0a, 0x12, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x6e, 0x6f, 0x5f,
0x65, 0x6e, 0x64, 0x5f, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x12, 0x19, 0x43, 0x61, 0x6e, 0x6e,
0x6f, 0x74, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x68, 0x79,
0x70, 0x68, 0x65, 0x6e, 0x2e, 0x1a, 0x13, 0x21, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x65, 0x6e, 0x64,
0x73, 0x57, 0x69, 0x74, 0x68, 0x28, 0x27, 0x2d, 0x27, 0x29, 0xba, 0x01, 0x58, 0x0a, 0x1b, 0x6e,
0x61, 0x6d, 0x65, 0x2e, 0x6e, 0x6f, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69,
0x76, 0x65, 0x5f, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x12, 0x23, 0x43, 0x61, 0x6e, 0x6e,
0x6f, 0x74, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x65,
0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x73, 0x2e, 0x1a,
0x14, 0x21, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x28,
0x27, 0x2d, 0x2d, 0x27, 0x29, 0xba, 0x01, 0x68, 0x0a, 0x0c, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x70,
0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x12, 0x37, 0x41, 0x6c, 0x6c, 0x20, 0x63, 0x68, 0x61, 0x72,
0x61, 0x63, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6d, 0x75, 0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x65,
0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x61, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x20, 0x6f,
0x72, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75, 0x6d, 0x65, 0x72, 0x69, 0x63, 0x2e, 0x1a,
0x1f, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74, 0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e,
0x5b, 0x41, 0x2d, 0x5a, 0x61, 0x2d, 0x7a, 0x30, 0x2d, 0x39, 0x2d, 0x5d, 0x2b, 0x24, 0x27, 0x29,
0x72, 0x04, 0x10, 0x01, 0x18, 0x27, 0x48, 0x00, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x88, 0x01,
0x01, 0x12, 0xb4, 0x02, 0x0a, 0x0c, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61,
0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x8b, 0x02, 0xba, 0x48, 0x87, 0x02, 0xba,
0x01, 0x50, 0x0a, 0x1b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
0x2e, 0x6e, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12,
0x1a, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x73, 0x74, 0x61, 0x72, 0x74, 0x20, 0x77, 0x69,
0x74, 0x68, 0x20, 0x61, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x1a, 0x15, 0x21, 0x74, 0x68,
0x69, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x73, 0x57, 0x69, 0x74, 0x68, 0x28, 0x27, 0x20,
0x27, 0x29, 0xba, 0x01, 0x4a, 0x0a, 0x19, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e,
0x61, 0x6d, 0x65, 0x2e, 0x6e, 0x6f, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x73, 0x70, 0x61, 0x63, 0x65,
0x12, 0x18, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74,
0x68, 0x20, 0x61, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x2e, 0x1a, 0x13, 0x21, 0x74, 0x68, 0x69,
0x73, 0x2e, 0x65, 0x6e, 0x64, 0x73, 0x57, 0x69, 0x74, 0x68, 0x28, 0x27, 0x20, 0x27, 0x29, 0xba,
0x01, 0x5e, 0x0a, 0x22, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65,
0x2e, 0x6e, 0x6f, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x5f,
0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x22, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x69,
0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69,
0x76, 0x65, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x2e, 0x1a, 0x14, 0x21, 0x74, 0x68, 0x69,
0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x28, 0x27, 0x20, 0x20, 0x27, 0x29,
0x72, 0x04, 0x10, 0x01, 0x18, 0x64, 0x48, 0x01, 0x52, 0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61,
0x79, 0x4e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0x32, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65,
0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65,
0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74,
0x48, 0x02, 0x52, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x34, 0x0a, 0x04,
0x66, 0x6f, 0x72, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x6f, 0x6c,
0x6f, 0x73, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
0x61, 0x31, 0x2e, 0x46, 0x6f, 0x72, 0x6d, 0x48, 0x03, 0x52, 0x04, 0x66, 0x6f, 0x72, 0x6d, 0x88,
0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x0f, 0x0a, 0x0d, 0x5f,
0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x08, 0x0a, 0x06,
0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x32,
0xd9, 0x03, 0x0a, 0x0f, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x53, 0x65, 0x72, 0x76,
0x69, 0x63, 0x65, 0x12, 0x73, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x6c, 0x61,
0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x2e, 0x2e, 0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2e, 0x70, 0x6c,
0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e,
0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2e, 0x70, 0x6c,
0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e,
0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6a, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x50,
0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x2b, 0x2e, 0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2e,
0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x65, 0x71,
0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2e, 0x70, 0x6c, 0x61,
0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47,
0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x25, 0x0a, 0x0e, 0x61, 0x6c, 0x72, 0x65,
0x61, 0x64, 0x79, 0x5f, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08,
0x52, 0x0d, 0x61, 0x6c, 0x72, 0x65, 0x61, 0x64, 0x79, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x22,
0x7a, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x0b, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72,
0x03, 0xb0, 0x01, 0x01, 0x52, 0x0a, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x49, 0x64,
0x12, 0x39, 0x0a, 0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x02,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72,
0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b,
0x52, 0x09, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x22, 0x54, 0x0a, 0x13, 0x47,
0x65, 0x74, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0x00, 0x12, 0x73, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6c,
0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x2e, 0x2e, 0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2e, 0x70,
0x73, 0x65, 0x12, 0x3d, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x01,
0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2e, 0x70, 0x6c, 0x61,
0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50,
0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
0x6d, 0x22, 0xd7, 0x01, 0x0a, 0x15, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6c, 0x61, 0x74,
0x66, 0x6f, 0x72, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x29, 0x0a, 0x0b, 0x70,
0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x0a, 0x70, 0x6c, 0x61, 0x74,
0x66, 0x6f, 0x72, 0x6d, 0x49, 0x64, 0x12, 0x41, 0x0a, 0x06, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65,
0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2e, 0x70,
0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52,
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2e, 0x70,
0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x4d, 0x75, 0x74, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x52, 0x06, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x75, 0x70, 0x64,
0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x48, 0x00, 0x52, 0x0a, 0x75, 0x70,
0x64, 0x61, 0x74, 0x65, 0x4d, 0x61, 0x73, 0x6b, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, 0x0c, 0x5f,
0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x22, 0x57, 0x0a, 0x16, 0x55,
0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2e,
0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61,
0x31, 0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74,
0x66, 0x6f, 0x72, 0x6d, 0x22, 0x72, 0x0a, 0x14, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6c, 0x61, 0x74,
0x66, 0x6f, 0x72, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1f, 0x0a, 0x06,
0x6f, 0x72, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48,
0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x05, 0x6f, 0x72, 0x67, 0x49, 0x64, 0x12, 0x39, 0x0a,
0x0a, 0x66, 0x69, 0x65, 0x6c, 0x64, 0x5f, 0x6d, 0x61, 0x73, 0x6b, 0x18, 0x02, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
0x62, 0x75, 0x66, 0x2e, 0x46, 0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x52, 0x09, 0x66,
0x69, 0x65, 0x6c, 0x64, 0x4d, 0x61, 0x73, 0x6b, 0x22, 0x58, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74,
0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73,
0x65, 0x12, 0x3f, 0x0a, 0x09, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x18, 0x01,
0x20, 0x03, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2e, 0x70, 0x6c, 0x61,
0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x50,
0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x09, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
0x6d, 0x73, 0x22, 0xe1, 0x06, 0x0a, 0x10, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x4d,
0x75, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0xfe, 0x02, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65,
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x42, 0xe4, 0x02, 0xba, 0x48, 0xe0, 0x02, 0xba, 0x01, 0x4a,
0x0a, 0x14, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x6e, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f,
0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x12, 0x1b, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x73,
0x74, 0x61, 0x72, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x68, 0x79, 0x70, 0x68,
0x65, 0x6e, 0x2e, 0x1a, 0x15, 0x21, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x72, 0x74,
0x73, 0x57, 0x69, 0x74, 0x68, 0x28, 0x27, 0x2d, 0x27, 0x29, 0xba, 0x01, 0x44, 0x0a, 0x12, 0x6e,
0x61, 0x6d, 0x65, 0x2e, 0x6e, 0x6f, 0x5f, 0x65, 0x6e, 0x64, 0x5f, 0x68, 0x79, 0x70, 0x68, 0x65,
0x6e, 0x12, 0x19, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x65, 0x6e, 0x64, 0x20, 0x77, 0x69,
0x74, 0x68, 0x20, 0x61, 0x20, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e, 0x2e, 0x1a, 0x13, 0x21, 0x74,
0x68, 0x69, 0x73, 0x2e, 0x65, 0x6e, 0x64, 0x73, 0x57, 0x69, 0x74, 0x68, 0x28, 0x27, 0x2d, 0x27,
0x29, 0xba, 0x01, 0x58, 0x0a, 0x1b, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x6e, 0x6f, 0x5f, 0x63, 0x6f,
0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x68, 0x79, 0x70, 0x68, 0x65, 0x6e,
0x73, 0x12, 0x23, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64,
0x65, 0x20, 0x63, 0x6f, 0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x20, 0x68, 0x79,
0x70, 0x68, 0x65, 0x6e, 0x73, 0x2e, 0x1a, 0x14, 0x21, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x63, 0x6f,
0x6e, 0x74, 0x61, 0x69, 0x6e, 0x73, 0x28, 0x27, 0x2d, 0x2d, 0x27, 0x29, 0xba, 0x01, 0x68, 0x0a,
0x0c, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x12, 0x37, 0x41,
0x6c, 0x6c, 0x20, 0x63, 0x68, 0x61, 0x72, 0x61, 0x63, 0x74, 0x65, 0x72, 0x73, 0x20, 0x6d, 0x75,
0x73, 0x74, 0x20, 0x62, 0x65, 0x20, 0x65, 0x69, 0x74, 0x68, 0x65, 0x72, 0x20, 0x61, 0x20, 0x68,
0x79, 0x70, 0x68, 0x65, 0x6e, 0x20, 0x6f, 0x72, 0x20, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x6e, 0x75,
0x6d, 0x65, 0x72, 0x69, 0x63, 0x2e, 0x1a, 0x1f, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x6d, 0x61, 0x74,
0x63, 0x68, 0x65, 0x73, 0x28, 0x27, 0x5e, 0x5b, 0x41, 0x2d, 0x5a, 0x61, 0x2d, 0x7a, 0x30, 0x2d,
0x39, 0x2d, 0x5d, 0x2b, 0x24, 0x27, 0x29, 0x72, 0x04, 0x10, 0x01, 0x18, 0x27, 0x48, 0x00, 0x52,
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12, 0xb4, 0x02, 0x0a, 0x0c, 0x64, 0x69, 0x73,
0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42,
0x8b, 0x02, 0xba, 0x48, 0x87, 0x02, 0xba, 0x01, 0x50, 0x0a, 0x1b, 0x64, 0x69, 0x73, 0x70, 0x6c,
0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x6e, 0x6f, 0x5f, 0x73, 0x74, 0x61, 0x72, 0x74,
0x5f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x1a, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x73,
0x74, 0x61, 0x72, 0x74, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x73, 0x70, 0x61, 0x63,
0x65, 0x2e, 0x1a, 0x15, 0x21, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x73, 0x74, 0x61, 0x72, 0x74, 0x73,
0x57, 0x69, 0x74, 0x68, 0x28, 0x27, 0x20, 0x27, 0x29, 0xba, 0x01, 0x4a, 0x0a, 0x19, 0x64, 0x69,
0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x6e, 0x6f, 0x5f, 0x65, 0x6e,
0x64, 0x5f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x12, 0x18, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20,
0x65, 0x6e, 0x64, 0x20, 0x77, 0x69, 0x74, 0x68, 0x20, 0x61, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65,
0x2e, 0x1a, 0x13, 0x21, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x65, 0x6e, 0x64, 0x73, 0x57, 0x69, 0x74,
0x68, 0x28, 0x27, 0x20, 0x27, 0x29, 0xba, 0x01, 0x5e, 0x0a, 0x22, 0x64, 0x69, 0x73, 0x70, 0x6c,
0x61, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x2e, 0x6e, 0x6f, 0x5f, 0x63, 0x6f, 0x6e, 0x73, 0x65,
0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x5f, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x22, 0x43,
0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x20, 0x63, 0x6f,
0x6e, 0x73, 0x65, 0x63, 0x75, 0x74, 0x69, 0x76, 0x65, 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73,
0x2e, 0x1a, 0x14, 0x21, 0x74, 0x68, 0x69, 0x73, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e,
0x73, 0x28, 0x27, 0x20, 0x20, 0x27, 0x29, 0x72, 0x04, 0x10, 0x01, 0x18, 0x64, 0x48, 0x01, 0x52,
0x0b, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x88, 0x01, 0x01, 0x12,
0x32, 0x0a, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17,
0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66,
0x2e, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, 0x48, 0x02, 0x52, 0x05, 0x6d, 0x6f, 0x64, 0x65, 0x6c,
0x88, 0x01, 0x01, 0x12, 0x34, 0x0a, 0x04, 0x66, 0x6f, 0x72, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28,
0x0b, 0x32, 0x1b, 0x2e, 0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2e, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74,
0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x46, 0x6f, 0x72, 0x6d, 0x48, 0x03,
0x52, 0x04, 0x66, 0x6f, 0x72, 0x6d, 0x88, 0x01, 0x01, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x6e, 0x61,
0x6d, 0x65, 0x42, 0x0f, 0x0a, 0x0d, 0x5f, 0x64, 0x69, 0x73, 0x70, 0x6c, 0x61, 0x79, 0x5f, 0x6e,
0x61, 0x6d, 0x65, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x6c, 0x42, 0x07, 0x0a,
0x05, 0x5f, 0x66, 0x6f, 0x72, 0x6d, 0x22, 0x42, 0x0a, 0x15, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65,
0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12,
0x29, 0x0a, 0x0b, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x01,
0x20, 0x01, 0x28, 0x09, 0x42, 0x08, 0xba, 0x48, 0x05, 0x72, 0x03, 0xb0, 0x01, 0x01, 0x52, 0x0a,
0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x49, 0x64, 0x22, 0x57, 0x0a, 0x16, 0x44, 0x65,
0x6c, 0x65, 0x74, 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x65, 0x73, 0x70,
0x6f, 0x6e, 0x73, 0x65, 0x12, 0x3d, 0x0a, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2e, 0x70,
0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31,
0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52,
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x70, 0x0a, 0x0d, 0x4c, 0x69, 0x73,
0x74, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x12, 0x2d, 0x2e, 0x68, 0x6f, 0x6c,
0x6f, 0x73, 0x2e, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x68, 0x6f, 0x6c, 0x6f,
0x2e, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x08, 0x70, 0x6c, 0x61, 0x74, 0x66,
0x6f, 0x72, 0x6d, 0x32, 0xce, 0x04, 0x0a, 0x0f, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d,
0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x73, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74,
0x65, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x2e, 0x2e, 0x68, 0x6f, 0x6c, 0x6f,
0x73, 0x2e, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70,
0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d,
0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x42, 0x49, 0x5a, 0x47, 0x67,
0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2d,
0x72, 0x75, 0x6e, 0x2f, 0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
0x65, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2f, 0x70, 0x6c, 0x61, 0x74,
0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x70, 0x6c,
0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x68, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f,
0x72, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x68, 0x6f, 0x6c, 0x6f,
0x73, 0x2e, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70,
0x68, 0x61, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f,
0x72, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x6a, 0x0a, 0x0b,
0x47, 0x65, 0x74, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x2b, 0x2e, 0x68, 0x6f,
0x6c, 0x6f, 0x73, 0x2e, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x61,
0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x68, 0x6f, 0x6c, 0x6f, 0x73,
0x2e, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68,
0x61, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x73, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61,
0x74, 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x12, 0x2e, 0x2e, 0x68, 0x6f, 0x6c,
0x6f, 0x73, 0x2e, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66,
0x6f, 0x72, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x68, 0x6f, 0x6c,
0x6f, 0x73, 0x2e, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x76, 0x31, 0x61, 0x6c,
0x70, 0x68, 0x61, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66,
0x6f, 0x72, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12, 0x70, 0x0a,
0x0d, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x12, 0x2d,
0x2e, 0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2e, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e,
0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6c, 0x61,
0x74, 0x66, 0x6f, 0x72, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e,
0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2e, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2e, 0x76,
0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x50, 0x6c, 0x61, 0x74,
0x66, 0x6f, 0x72, 0x6d, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, 0x12,
0x73, 0x0a, 0x0e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72,
0x6d, 0x12, 0x2e, 0x2e, 0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2e, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f,
0x72, 0x6d, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65,
0x74, 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
0x74, 0x1a, 0x2f, 0x2e, 0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2e, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f,
0x72, 0x6d, 0x2e, 0x76, 0x31, 0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65,
0x74, 0x65, 0x50, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
0x73, 0x65, 0x22, 0x00, 0x42, 0x49, 0x5a, 0x47, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63,
0x6f, 0x6d, 0x2f, 0x68, 0x6f, 0x6c, 0x6f, 0x73, 0x2d, 0x72, 0x75, 0x6e, 0x2f, 0x68, 0x6f, 0x6c,
0x6f, 0x73, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x68,
0x6f, 0x6c, 0x6f, 0x73, 0x2f, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x2f, 0x76, 0x31,
0x61, 0x6c, 0x70, 0x68, 0x61, 0x31, 0x3b, 0x70, 0x6c, 0x61, 0x74, 0x66, 0x6f, 0x72, 0x6d, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -704,7 +826,7 @@ func file_holos_platform_v1alpha1_platform_service_proto_rawDescGZIP() []byte {
return file_holos_platform_v1alpha1_platform_service_proto_rawDescData
}
var file_holos_platform_v1alpha1_platform_service_proto_msgTypes = make([]protoimpl.MessageInfo, 9)
var file_holos_platform_v1alpha1_platform_service_proto_msgTypes = make([]protoimpl.MessageInfo, 11)
var file_holos_platform_v1alpha1_platform_service_proto_goTypes = []interface{}{
(*CreatePlatformRequest)(nil), // 0: holos.platform.v1alpha1.CreatePlatformRequest
(*CreatePlatformResponse)(nil), // 1: holos.platform.v1alpha1.CreatePlatformResponse
@@ -715,36 +837,41 @@ var file_holos_platform_v1alpha1_platform_service_proto_goTypes = []interface{}{
(*ListPlatformsRequest)(nil), // 6: holos.platform.v1alpha1.ListPlatformsRequest
(*ListPlatformsResponse)(nil), // 7: holos.platform.v1alpha1.ListPlatformsResponse
(*PlatformMutation)(nil), // 8: holos.platform.v1alpha1.PlatformMutation
(*Platform)(nil), // 9: holos.platform.v1alpha1.Platform
(*fieldmaskpb.FieldMask)(nil), // 10: google.protobuf.FieldMask
(*structpb.Struct)(nil), // 11: google.protobuf.Struct
(*v1alpha1.Form)(nil), // 12: holos.object.v1alpha1.Form
(*DeletePlatformRequest)(nil), // 9: holos.platform.v1alpha1.DeletePlatformRequest
(*DeletePlatformResponse)(nil), // 10: holos.platform.v1alpha1.DeletePlatformResponse
(*Platform)(nil), // 11: holos.platform.v1alpha1.Platform
(*fieldmaskpb.FieldMask)(nil), // 12: google.protobuf.FieldMask
(*structpb.Struct)(nil), // 13: google.protobuf.Struct
(*v1alpha1.Form)(nil), // 14: holos.object.v1alpha1.Form
}
var file_holos_platform_v1alpha1_platform_service_proto_depIdxs = []int32{
8, // 0: holos.platform.v1alpha1.CreatePlatformRequest.create:type_name -> holos.platform.v1alpha1.PlatformMutation
9, // 1: holos.platform.v1alpha1.CreatePlatformResponse.platform:type_name -> holos.platform.v1alpha1.Platform
10, // 2: holos.platform.v1alpha1.GetPlatformRequest.field_mask:type_name -> google.protobuf.FieldMask
9, // 3: holos.platform.v1alpha1.GetPlatformResponse.platform:type_name -> holos.platform.v1alpha1.Platform
11, // 1: holos.platform.v1alpha1.CreatePlatformResponse.platform:type_name -> holos.platform.v1alpha1.Platform
12, // 2: holos.platform.v1alpha1.GetPlatformRequest.field_mask:type_name -> google.protobuf.FieldMask
11, // 3: holos.platform.v1alpha1.GetPlatformResponse.platform:type_name -> holos.platform.v1alpha1.Platform
8, // 4: holos.platform.v1alpha1.UpdatePlatformRequest.update:type_name -> holos.platform.v1alpha1.PlatformMutation
10, // 5: holos.platform.v1alpha1.UpdatePlatformRequest.update_mask:type_name -> google.protobuf.FieldMask
9, // 6: holos.platform.v1alpha1.UpdatePlatformResponse.platform:type_name -> holos.platform.v1alpha1.Platform
10, // 7: holos.platform.v1alpha1.ListPlatformsRequest.field_mask:type_name -> google.protobuf.FieldMask
9, // 8: holos.platform.v1alpha1.ListPlatformsResponse.platforms:type_name -> holos.platform.v1alpha1.Platform
11, // 9: holos.platform.v1alpha1.PlatformMutation.model:type_name -> google.protobuf.Struct
12, // 10: holos.platform.v1alpha1.PlatformMutation.form:type_name -> holos.object.v1alpha1.Form
0, // 11: holos.platform.v1alpha1.PlatformService.CreatePlatform:input_type -> holos.platform.v1alpha1.CreatePlatformRequest
2, // 12: holos.platform.v1alpha1.PlatformService.GetPlatform:input_type -> holos.platform.v1alpha1.GetPlatformRequest
4, // 13: holos.platform.v1alpha1.PlatformService.UpdatePlatform:input_type -> holos.platform.v1alpha1.UpdatePlatformRequest
6, // 14: holos.platform.v1alpha1.PlatformService.ListPlatforms:input_type -> holos.platform.v1alpha1.ListPlatformsRequest
1, // 15: holos.platform.v1alpha1.PlatformService.CreatePlatform:output_type -> holos.platform.v1alpha1.CreatePlatformResponse
3, // 16: holos.platform.v1alpha1.PlatformService.GetPlatform:output_type -> holos.platform.v1alpha1.GetPlatformResponse
5, // 17: holos.platform.v1alpha1.PlatformService.UpdatePlatform:output_type -> holos.platform.v1alpha1.UpdatePlatformResponse
7, // 18: holos.platform.v1alpha1.PlatformService.ListPlatforms:output_type -> holos.platform.v1alpha1.ListPlatformsResponse
15, // [15:19] is the sub-list for method output_type
11, // [11:15] is the sub-list for method input_type
11, // [11:11] is the sub-list for extension type_name
11, // [11:11] is the sub-list for extension extendee
0, // [0:11] is the sub-list for field type_name
12, // 5: holos.platform.v1alpha1.UpdatePlatformRequest.update_mask:type_name -> google.protobuf.FieldMask
11, // 6: holos.platform.v1alpha1.UpdatePlatformResponse.platform:type_name -> holos.platform.v1alpha1.Platform
12, // 7: holos.platform.v1alpha1.ListPlatformsRequest.field_mask:type_name -> google.protobuf.FieldMask
11, // 8: holos.platform.v1alpha1.ListPlatformsResponse.platforms:type_name -> holos.platform.v1alpha1.Platform
13, // 9: holos.platform.v1alpha1.PlatformMutation.model:type_name -> google.protobuf.Struct
14, // 10: holos.platform.v1alpha1.PlatformMutation.form:type_name -> holos.object.v1alpha1.Form
11, // 11: holos.platform.v1alpha1.DeletePlatformResponse.platform:type_name -> holos.platform.v1alpha1.Platform
0, // 12: holos.platform.v1alpha1.PlatformService.CreatePlatform:input_type -> holos.platform.v1alpha1.CreatePlatformRequest
2, // 13: holos.platform.v1alpha1.PlatformService.GetPlatform:input_type -> holos.platform.v1alpha1.GetPlatformRequest
4, // 14: holos.platform.v1alpha1.PlatformService.UpdatePlatform:input_type -> holos.platform.v1alpha1.UpdatePlatformRequest
6, // 15: holos.platform.v1alpha1.PlatformService.ListPlatforms:input_type -> holos.platform.v1alpha1.ListPlatformsRequest
9, // 16: holos.platform.v1alpha1.PlatformService.DeletePlatform:input_type -> holos.platform.v1alpha1.DeletePlatformRequest
1, // 17: holos.platform.v1alpha1.PlatformService.CreatePlatform:output_type -> holos.platform.v1alpha1.CreatePlatformResponse
3, // 18: holos.platform.v1alpha1.PlatformService.GetPlatform:output_type -> holos.platform.v1alpha1.GetPlatformResponse
5, // 19: holos.platform.v1alpha1.PlatformService.UpdatePlatform:output_type -> holos.platform.v1alpha1.UpdatePlatformResponse
7, // 20: holos.platform.v1alpha1.PlatformService.ListPlatforms:output_type -> holos.platform.v1alpha1.ListPlatformsResponse
10, // 21: holos.platform.v1alpha1.PlatformService.DeletePlatform:output_type -> holos.platform.v1alpha1.DeletePlatformResponse
17, // [17:22] is the sub-list for method output_type
12, // [12:17] is the sub-list for method input_type
12, // [12:12] is the sub-list for extension type_name
12, // [12:12] is the sub-list for extension extendee
0, // [0:12] is the sub-list for field type_name
}
func init() { file_holos_platform_v1alpha1_platform_service_proto_init() }
@@ -862,6 +989,30 @@ func file_holos_platform_v1alpha1_platform_service_proto_init() {
return nil
}
}
file_holos_platform_v1alpha1_platform_service_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeletePlatformRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_holos_platform_v1alpha1_platform_service_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeletePlatformResponse); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
file_holos_platform_v1alpha1_platform_service_proto_msgTypes[4].OneofWrappers = []interface{}{}
file_holos_platform_v1alpha1_platform_service_proto_msgTypes[8].OneofWrappers = []interface{}{}
@@ -871,7 +1022,7 @@ func file_holos_platform_v1alpha1_platform_service_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_holos_platform_v1alpha1_platform_service_proto_rawDesc,
NumEnums: 0,
NumMessages: 9,
NumMessages: 11,
NumExtensions: 0,
NumServices: 1,
},

View File

@@ -45,6 +45,9 @@ const (
// PlatformServiceListPlatformsProcedure is the fully-qualified name of the PlatformService's
// ListPlatforms RPC.
PlatformServiceListPlatformsProcedure = "/holos.platform.v1alpha1.PlatformService/ListPlatforms"
// PlatformServiceDeletePlatformProcedure is the fully-qualified name of the PlatformService's
// DeletePlatform RPC.
PlatformServiceDeletePlatformProcedure = "/holos.platform.v1alpha1.PlatformService/DeletePlatform"
)
// These variables are the protoreflect.Descriptor objects for the RPCs defined in this package.
@@ -54,6 +57,7 @@ var (
platformServiceGetPlatformMethodDescriptor = platformServiceServiceDescriptor.Methods().ByName("GetPlatform")
platformServiceUpdatePlatformMethodDescriptor = platformServiceServiceDescriptor.Methods().ByName("UpdatePlatform")
platformServiceListPlatformsMethodDescriptor = platformServiceServiceDescriptor.Methods().ByName("ListPlatforms")
platformServiceDeletePlatformMethodDescriptor = platformServiceServiceDescriptor.Methods().ByName("DeletePlatform")
)
// PlatformServiceClient is a client for the holos.platform.v1alpha1.PlatformService service.
@@ -62,6 +66,7 @@ type PlatformServiceClient interface {
GetPlatform(context.Context, *connect.Request[v1alpha1.GetPlatformRequest]) (*connect.Response[v1alpha1.GetPlatformResponse], error)
UpdatePlatform(context.Context, *connect.Request[v1alpha1.UpdatePlatformRequest]) (*connect.Response[v1alpha1.UpdatePlatformResponse], error)
ListPlatforms(context.Context, *connect.Request[v1alpha1.ListPlatformsRequest]) (*connect.Response[v1alpha1.ListPlatformsResponse], error)
DeletePlatform(context.Context, *connect.Request[v1alpha1.DeletePlatformRequest]) (*connect.Response[v1alpha1.DeletePlatformResponse], error)
}
// NewPlatformServiceClient constructs a client for the holos.platform.v1alpha1.PlatformService
@@ -98,6 +103,12 @@ func NewPlatformServiceClient(httpClient connect.HTTPClient, baseURL string, opt
connect.WithSchema(platformServiceListPlatformsMethodDescriptor),
connect.WithClientOptions(opts...),
),
deletePlatform: connect.NewClient[v1alpha1.DeletePlatformRequest, v1alpha1.DeletePlatformResponse](
httpClient,
baseURL+PlatformServiceDeletePlatformProcedure,
connect.WithSchema(platformServiceDeletePlatformMethodDescriptor),
connect.WithClientOptions(opts...),
),
}
}
@@ -107,6 +118,7 @@ type platformServiceClient struct {
getPlatform *connect.Client[v1alpha1.GetPlatformRequest, v1alpha1.GetPlatformResponse]
updatePlatform *connect.Client[v1alpha1.UpdatePlatformRequest, v1alpha1.UpdatePlatformResponse]
listPlatforms *connect.Client[v1alpha1.ListPlatformsRequest, v1alpha1.ListPlatformsResponse]
deletePlatform *connect.Client[v1alpha1.DeletePlatformRequest, v1alpha1.DeletePlatformResponse]
}
// CreatePlatform calls holos.platform.v1alpha1.PlatformService.CreatePlatform.
@@ -129,6 +141,11 @@ func (c *platformServiceClient) ListPlatforms(ctx context.Context, req *connect.
return c.listPlatforms.CallUnary(ctx, req)
}
// DeletePlatform calls holos.platform.v1alpha1.PlatformService.DeletePlatform.
func (c *platformServiceClient) DeletePlatform(ctx context.Context, req *connect.Request[v1alpha1.DeletePlatformRequest]) (*connect.Response[v1alpha1.DeletePlatformResponse], error) {
return c.deletePlatform.CallUnary(ctx, req)
}
// PlatformServiceHandler is an implementation of the holos.platform.v1alpha1.PlatformService
// service.
type PlatformServiceHandler interface {
@@ -136,6 +153,7 @@ type PlatformServiceHandler interface {
GetPlatform(context.Context, *connect.Request[v1alpha1.GetPlatformRequest]) (*connect.Response[v1alpha1.GetPlatformResponse], error)
UpdatePlatform(context.Context, *connect.Request[v1alpha1.UpdatePlatformRequest]) (*connect.Response[v1alpha1.UpdatePlatformResponse], error)
ListPlatforms(context.Context, *connect.Request[v1alpha1.ListPlatformsRequest]) (*connect.Response[v1alpha1.ListPlatformsResponse], error)
DeletePlatform(context.Context, *connect.Request[v1alpha1.DeletePlatformRequest]) (*connect.Response[v1alpha1.DeletePlatformResponse], error)
}
// NewPlatformServiceHandler builds an HTTP handler from the service implementation. It returns the
@@ -168,6 +186,12 @@ func NewPlatformServiceHandler(svc PlatformServiceHandler, opts ...connect.Handl
connect.WithSchema(platformServiceListPlatformsMethodDescriptor),
connect.WithHandlerOptions(opts...),
)
platformServiceDeletePlatformHandler := connect.NewUnaryHandler(
PlatformServiceDeletePlatformProcedure,
svc.DeletePlatform,
connect.WithSchema(platformServiceDeletePlatformMethodDescriptor),
connect.WithHandlerOptions(opts...),
)
return "/holos.platform.v1alpha1.PlatformService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case PlatformServiceCreatePlatformProcedure:
@@ -178,6 +202,8 @@ func NewPlatformServiceHandler(svc PlatformServiceHandler, opts ...connect.Handl
platformServiceUpdatePlatformHandler.ServeHTTP(w, r)
case PlatformServiceListPlatformsProcedure:
platformServiceListPlatformsHandler.ServeHTTP(w, r)
case PlatformServiceDeletePlatformProcedure:
platformServiceDeletePlatformHandler.ServeHTTP(w, r)
default:
http.NotFound(w, r)
}
@@ -202,3 +228,7 @@ func (UnimplementedPlatformServiceHandler) UpdatePlatform(context.Context, *conn
func (UnimplementedPlatformServiceHandler) ListPlatforms(context.Context, *connect.Request[v1alpha1.ListPlatformsRequest]) (*connect.Response[v1alpha1.ListPlatformsResponse], error) {
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("holos.platform.v1alpha1.PlatformService.ListPlatforms is not implemented"))
}
func (UnimplementedPlatformServiceHandler) DeletePlatform(context.Context, *connect.Request[v1alpha1.DeletePlatformRequest]) (*connect.Response[v1alpha1.DeletePlatformResponse], error) {
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("holos.platform.v1alpha1.PlatformService.DeletePlatform is not implemented"))
}

View File

@@ -8,6 +8,7 @@ import "google/protobuf/timestamp.proto";
import "google/protobuf/struct.proto";
import "buf/validate/validate.proto";
// For validation, see the [Standard constraints](https://github.com/bufbuild/protovalidate/blob/main/docs/standard-constraints.md)
message Detail {
@@ -83,16 +84,19 @@ message ResourceOwner {
// Form represents a Formly json powered form.
message Form {
// fields represents FormlyFieldConfig[] encoded as an array of JSON objects
// organized by section.
// field_configs represents FormlyFieldConfig[] encoded as an array of JSON
// objects organized by section.
repeated google.protobuf.Struct field_configs = 1;
}
// PlatformConfig represents the data passed from the holos cli to CUE when
// rendering configuration.
// rendering configuration. At present it contains only the platform model from
// the PlatformService, but it is expected to carry additional fields from
// additional data sources. For this reason, there is a distinction in domain
// language between the "Platform Config" and the "Platform Model" The config
// is a data transfer object that carries at least the model. The model
// represents the form values from the PlatformService.
message PlatformConfig {
// Platform UUID.
string platform_id = 1 [(buf.validate.field).string.uuid = true];
// Platform Model.
google.protobuf.Struct platform_model = 2;
// platform_model represents the form values from the PlatformService.
google.protobuf.Struct platform_model = 1;
}

View File

@@ -16,6 +16,7 @@ message CreatePlatformRequest {
message CreatePlatformResponse {
Platform platform = 1;
bool already_exists = 2;
}
message GetPlatformRequest {
@@ -110,9 +111,18 @@ message PlatformMutation {
optional holos.object.v1alpha1.Form form = 5;
}
message DeletePlatformRequest {
string platform_id = 1 [(buf.validate.field).string.uuid = true];
}
message DeletePlatformResponse {
Platform platform = 1;
}
service PlatformService {
rpc CreatePlatform(CreatePlatformRequest) returns (CreatePlatformResponse) {}
rpc GetPlatform(GetPlatformRequest) returns (GetPlatformResponse) {}
rpc UpdatePlatform(UpdatePlatformRequest) returns (UpdatePlatformResponse) {}
rpc ListPlatforms(ListPlatformsRequest) returns (ListPlatformsResponse) {}
rpc DeletePlatform(DeletePlatformRequest) returns (DeletePlatformResponse) {}
}

View File

@@ -1 +1 @@
87
90

View File

@@ -1 +1 @@
2
0