Compare commits

..

58 Commits

Author SHA1 Message Date
Jeff McCune
e4e7cd8c47 (#175) Make holos render --cluster-name flag optional
Problem:
Rendering the whole platform doesn't need a cluster name.

Solution:
Make the flag optional, do not set the cue tag if it's empty.

Result:
Holos renders the platform resource and proceeds to the point where we
need to implement the iteration over platform components, passing the
platform model to each one and rendering the component.
2024-05-17 15:48:36 -07:00
Jeff McCune
fb22e5521b (#175) Define the Platform resource in CUE
We need to output a kind: Platform resource from cue so holos can
iterate over each build plan.  The platform resource itself should also
contain a copy of the platform model obtained from the PlatformService
so holos can easily pass the model to each BuildPlan it needs to execute
to render the full platform.

This patch lays the groundwork for the Platform resource.  A future
patch will have the holos cli obtain the platform model and inject it as
a JSON encoded string to CUE.  CUE will return the Platform resource
which is a list of references to build plans.  Holos will then iterate
over each build plan, pass the model back in, and execute the build
plan.

To illustrate where we're headed, the `cue export` step will move into
`holos` with a future patch.

```
❯ holos register user
3:34PM INF register.go:77 user version=0.80.0 email=jeff@ois.run server=https://app.dev.k2.holos.run:443 user_id=018f8839-3d74-7e39-afe9-181ad2fc8abe org_id=018f8839-3d74-7e3a-918c-b36494da0115
❯ holos generate platform bare
3:34PM INF generate.go:79 wrote platform.metadata.json version=0.80.0 platform_id=018f8839-3d74-7e3b-8cb8-77a2c124d173 path=/home/jeff/holos/dev/bare/platform.metadata.json
3:34PM INF generate.go:91 generated platform bare version=0.80.0 platform_id=018f8839-3d74-7e3b-8cb8-77a2c124d173 path=/home/jeff/holos/dev/bare
❯ holos push platform form .
3:34PM INF push.go:70 pushed: https://app.dev.k2.holos.run:443/ui/platform/018f8839-3d74-7e3b-8cb8-77a2c124d173 version=0.80.0
❯ cue export ./platform/
{
    "metadata": {
        "name": "bare",
        "labels": {},
        "annotations": {}
    },
    "spec": {
        "model": {}
    },
    "kind": "Platform",
    "apiVersion": "holos.run/v1alpha1"
}
```
2024-05-17 15:34:56 -07:00
Jeff McCune
d2ae766ae3 Merge pull request #176 from holos-run/dependabot/go_modules/github.com/docker/docker-26.0.2incompatible
Bump github.com/docker/docker from 26.0.0+incompatible to 26.0.2+incompatible
2024-05-17 11:53:44 -07:00
dependabot[bot]
c0db949729 Bump github.com/docker/docker
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 26.0.0+incompatible to 26.0.2+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v26.0.0...v26.0.2)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-05-17 18:52:51 +00:00
Jeff McCune
d2d4337ffd (#175) Improve url output
❯ holos push platform form .
11:49AM INF push.go:70 pushed: https://app.dev.k2.holos.run:443/ui/platform/018f87d1-7ca2-7e37-97ed-a06bcee9b442 version=0.79.0
2024-05-17 11:49:04 -07:00
Jeff McCune
b0ca04635e (#175) Update the client context when switching servers
When the holos server URL switches, we also need to update the client
context to get the correct org id.

Also improve quality of life by printing the url to the form when the
platform form is pushed to the server.

❯ holos push platform form .
11:41AM INF push.go:71 updated platform form version=0.79.0 server=https://app.dev.k2.holos.run:443 platform_id=018f87d1-7ca2-7e37-97ed-a06bcee9b442
11:41AM INF push.go:72 https://app.dev.k2.holos.run:443/ui/platform/018f87d1-7ca2-7e37-97ed-a06bcee9b442 version=0.79.0
2024-05-17 11:43:52 -07:00
Jeff McCune
198c66e6cd (#175) Fix tests
Not sure why this started failing, but it wasn't necessary.
2024-05-17 10:22:35 -07:00
Jeff McCune
24346b9a38 (#172) Deploy v0.79.0 to dev 2024-05-17 10:15:05 -07:00
Jeff McCune
0639562f1c (#175) go mod tidy 2024-05-17 10:09:40 -07:00
Jeff McCune
c1fa9cc531 (#175) Fix lint 2024-05-17 10:08:06 -07:00
Jeff McCune
18653534ad (#175) Add holos push platform form command
This sub-command renders the web app form from CUE code and updates the
form using the `holos.platform.v1alpha1.PlatformService/UpdatePlatform`
rpc method.

Example use case, starting fresh:

```
rm -rf ~/holos
mkdir ~/holos
cd ~/holos
```

Step 1: Login

```sh
holos login
```

```txt
9:53AM INF login.go:40 logged in as jeff@ois.run version=0.79.0 name="Jeff McCune" exp="2024-05-17 21:16:07 -0700 PDT" email=jeff@ois.run
```

Step 2: Register to create server side resources.

```sh
holos register user
```

```
9:52AM INF register.go:68 user version=0.79.0 email=jeff@ois.run user_id=018f826d-85a8-751d-81ee-64d0f2775b3f org_id=018f826d-85a8-751e-98dd-a6cddd9dd8f0
```

Step 3: Generate the bare platform in the local filesystem.

```sh
holos generate platform bare
```

```txt
9:52AM INF generate.go:79 wrote platform.metadata.json version=0.79.0 platform_id=018f826d-85a8-751f-96d0-0d2bf70df909 path=/home/jeff/holos/platform.metadata.json
9:52AM INF generate.go:91 generated platform bare version=0.79.0 platform_id=018f826d-85a8-751f-96d0-0d2bf70df909 path=/home/jeff/holos
```

Step 4: Push the platform form to the `holos server` web app.

```sh
holos push platform form .
```

```txt
9:52AM INF client.go:67 updated platform version=0.79.0 platform_id=018f826d-85a8-751f-96d0-0d2bf70df909 duration=73.62995ms
```

At this point the platform form is published and functions as expected
when visiting the platform web interface.
2024-05-17 09:51:36 -07:00
Jeff McCune
2b89c33067 (#175) Add holos orgid command
Makes it easier to work with grpcurl:

    grpcurl -H "x-oidc-id-token: $(holos token)" -d '{"org_id":"'$(holos orgid)'"}' ${HOLOS_SERVER##*/} holos.platform.v1alpha1.PlatformService.ListPlatforms
2024-05-16 21:11:24 -07:00
Jeff McCune
aee26d9375 (#175) Set header User-Agent: holos/0.70.0 (go1.22.2)
Previously: User-Agent: connect-go/1.16.0 (go1.22.2)
2024-05-16 20:49:06 -07:00
Jeff McCune
7b04d492ab (#175) Set http.Server ReadHeaderTimeout
Upstream connectrpc recommends it.  Refer to
https://connectrpc.com/docs/faq#stream-error
2024-05-16 20:28:31 -07:00
Jeff McCune
8abd03e165 (#175) Log x-request-id and x-b3-trace headers
This patch logs the x-request-id header which makes it straight forward
to correlate the logs with the service mesh logs.

For example, select the request id from the gateway logs by copying the
log from the holos server logs.

```sh
kubectl -n istio-ingress logs -l app=istio-ingressgateway -f \
  | grep --line-buffered '^{' \
  | jq 'select(.request_id=="'d0867115-5795-4096-942e-5ac188cdf618'")'
```

```json
{
  "upstream_local_address": "10.244.1.51:44248",
  "x_forwarded_for": "192.168.2.21",
  "authority": "jeff.app.dev.k2.holos.run:443",
  "upstream_transport_failure_reason": null,
  "connection_termination_details": null,
  "response_code": 200,
  "duration": 6,
  "response_flags": "-",
  "upstream_service_time": "5",
  "upstream_cluster": "outbound|3000||holos.jeff-holos.svc.cluster.local",
  "upstream_host": "10.244.1.249:3000",
  "user_agent": "connect-go/1.16.0 (go1.22.2)",
  "requested_server_name": "jeff.app.dev.k2.holos.run",
  "request_id": "d0867115-5795-4096-942e-5ac188cdf618",
  "start_time": "2024-05-17T03:16:37.900Z",
  "method": "POST",
  "protocol": "HTTP/2",
  "downstream_local_address": "65.102.23.41:443",
  "path": "/holos.user.v1alpha1.UserService/GetUser",
  "bytes_sent": 159,
  "downstream_remote_address": "192.168.2.21:59564",
  "response_code_details": "via_upstream",
  "bytes_received": 0,
  "route_name": "holos-api"
}
```
2024-05-16 20:14:34 -07:00
Jeff McCune
2df843bc98 (#175) Link the generated platform to holos server
When the user generates a platform, we need to know the platform ID it's
linked to in the holos server.  If there is no platform with the same
name, the `holos generate platform` command should error out.

This is necessary because the first thing we want to show is pushing an
updated form to `holos server`.  To update the web ui the CLI needs to
know the platform ID to update.

This patch modifies the generate command to obtain a list of platforms
for the org and verify the generated name matches one of the platforms
  that already exists.

A future patch could have the `generate platform` command call the
`holos.platform.v1alpha1.PlatformService.CreatePlatform` method if the
platform isn't found.

Results:

```sh
holos generate platform bare
```

```txt
4:15PM INF generate.go:77 wrote platform.metadata.json version=0.77.1 platform_id=018f826d-85a8-751f-96d0-0d2bf70df909 path=/home/jeff/holos/platform.metadata.json
4:15PM INF generate.go:89 generated platform bare version=0.77.1 platform_id=018f826d-85a8-751f-96d0-0d2bf70df909 path=/home/jeff/holos
```

```sh
cat platform.metadata.json
```

```json
{
  "id": "018f826d-85a8-751f-96d0-0d2bf70df909",
  "name": "bare",
  "display_name": "Bare Platform"
}
```
2024-05-16 16:18:38 -07:00
Jeff McCune
be4d2c29a5 (#175) Log info message when generating a platform
holos generate platform bare
    2:11PM INF generate.go:55 generated platform bare version=0.77.1 path=/home/jeff/holos
2024-05-16 14:26:51 -07:00
Jeff McCune
8ce88bf491 (#175) Fix goreleaser
Buf was being automatically updated in the pipeline.
2024-05-16 14:00:37 -07:00
Jeff McCune
b05571a595 (#175) Go tidy and update package.json
For goreleaser
2024-05-16 13:41:47 -07:00
Jeff McCune
4edfc71d68 (#175) Log the grpc procedure at info level
This patch logs the service and rpc method of every request at Info
level.  The error code and message is also logged.  This gives a good
indication of what rpc methods are being called and by whom.
2024-05-16 11:43:20 -07:00
Jeff McCune
3049694a0a (#175) holos register user
This patch adds a `holos register user` command.  Given an authenticated
id token and no other record of the user in the database, the cli tool
use the API to:

 1. User is registered in `holos server`
 2. User is linked to one Holos Organization.
 3. Holos Organization has the `bare` platform.
 4. Holos Organization has the `reference` platform.
 5. Ensure `~/.holos/client-context.json` contains the user id and an
    org id.

The `holos.ClientContext` struct is intended as a light weight way to
save and load the current organization id to the file system for further
API calls.

The assumption is most users will have only one single org.  We can add
a more complicated config context system like kubectl uses if and when
we need it.
2024-05-16 10:51:40 -07:00
Jeff McCune
5860c5747b (#87) generate sub-command with embedded platform
This patch adds a generate subcommand that copies a platform embedded
into the executable to the local filesystem.  The purpose is to
accelerate initial setup with canned example platforms.

Two platforms are intended to start, one bare and one reference
platform.  The number of platforms embedded into holos should be kept
small (2-3) to limit our support burden.
2024-05-14 15:03:21 -07:00
Jeff McCune
d3c2d55706 (#172) Deploy v0.76.0 to dev 2024-05-14 13:28:19 -07:00
Jeff McCune
ac2ff47a9c (#172) Wire Version Info in the UI
This patch adds the GetVersion rpc method to
holos.system.v1alpha1.SystemService and wires the version information up
to the Web UI.

This is a good example to crib from later regarding fetching and
refreshing data from the web ui using grpc and field masks.
2024-05-14 11:50:06 -07:00
Jeff McCune
9a2773c618 (#171) Refactor API to use FieldMasks
This patch refactors the API following the [API Best Practices][api]
documentation.  The UpdatePlatform method is modeled after a mutating
operation described [by Netflix][nflx] instead of using a REST resource
representation.  This makes it much easier to iterate over the fields
that need to be updated as the PlatformUpdateOperation is a flat data
structure while a Platform resource may have nested fields.  Nested
fields are more complicated and less clear to handle with a FieldMask.

This patch also adds a snapckbar message on save.  Previously, the save
button didn't give any indication of success or failure.  This patch
fixes the problem by adding a snackbar message that pop up at the bottom
of the screen nicely.

When the snackbar message is dismissed or times out the save button is
re-enabled.

[api]: https://protobuf.dev/programming-guides/api/
[nflx]: https://netflixtechblog.com/practical-api-design-at-netflix-part-2-protobuf-fieldmask-for-mutation-operations-2e75e1d230e4

Examples:

FieldMask for ListPlatforms

```
grpcurl -H "x-oidc-id-token: $(holos token)" -d @ ${HOLOS_SERVER##*/} holos.platform.v1alpha1.PlatformService.ListPlatforms <<EOF
{
  "org_id": "018f36fb-e3f7-7f7f-a1c5-c85fb735d215",
  "field_mask": { "paths": ["id","name"] }
}
EOF
```

```json
{
 "platforms": [
   {
     "id": "018f36fb-e3ff-7f7f-a5d1-7ca2bf499e94",
     "name": "bare"
   },
   {
     "id": "018f6b06-9e57-7223-91a9-784e145d998c",
     "name": "gary"
   },
   {
     "id": "018f6b06-9e53-7223-8ae1-1ad53d46b158",
     "name": "jeff"
   },
   {
     "id": "018f6b06-9e5b-7223-8b8b-ea62618e8200",
     "name": "nate"
   }
 ]
}
```

Closes: #171
2024-05-13 16:20:20 -07:00
Jeff McCune
51b6575d9f (#171) Refactor to API Best Practices
This patch refactors the API to be resource-oriented around one service
per resource type.  PlatformService, OrganizationService, UserService,
etc...

Validation is improved to use CEL rules provided by [protovalidate][1].

Place holders for FieldMask and other best practices are added, but are
unimplemented as per [API Best Practices][2].

The intent is to set us up well for copying and pasting solid existing
examples as we add features.

With this patch the server and web app client are both updated to use
the refactored API, however the following are not working:

 1. Update the model.
 2. Field Masks.

[1]: https://buf.build/bufbuild/protovalidate
[2]: https://protobuf.dev/programming-guides/api/
2024-05-10 15:55:41 -07:00
Jeff McCune
68a43f0682 (#167) Add holos rpc platform-model command
This command is just a prototype of how to fetch the platform model so
we can make it available to CUE.

The idea is we take the data from the holos server and write it into a
CUE `_Platform` struct.  This will probably involve converting the data
to CUE format and nesting it under the platform struct spec field.
2024-05-08 16:34:00 -07:00
Jeff McCune
9da88c4d1b (#169) ZITADEL ServerError - PGBouncer DNS
Add runbook notes.  Root cause and permanent solution have not been
identified yet.
2024-05-08 12:04:50 -07:00
Jeff McCune
19df2ec0fb (#167) Bump dev deployment to 0.74.0 2024-05-07 16:58:03 -07:00
Jeff McCune
bac7aec0ba (#167) Restructure the bare platform
This patch restructures the bare platform in preparation for a
`Platform` kind of output from CUE in addition to the existing
`BuildPlan` kind.

This patch establishes a pattern where our own CUE defined code goes
into the two CUE module paths:

1. `internal/platforms/cue.mod/gen/github.com/holos-run/holos/api/v1alpha1`
2. `internal/platforms/cue.mod/pkg/github.com/holos-run/holos/api/v1alpha1`
3. `internal/platforms/cue.mod/usr/github.com/holos-run/holos/api/v1alpha1`

The first path is automatically generated from Go structs.  The second
path is where we override and provide additional cue level integration.

The third path is reserved for the end user to further refine and
constrain our definitions.
2024-05-07 16:53:00 -07:00
Jeff McCune
42f916af41 (#164) Use quay.io/holos/oauth2-proxy:v7.6.0-1-g77a03ae2
Custom build to set samesite=none on the csrf cookie.
2024-05-06 16:18:32 -07:00
Jeff McCune
47a5e237e0 (#162) Lint go, typescript, and proto3 files
This patch adds lint coverage for proto3 and typescript to keep our code
reasonably clean.  The go linter was already enabled.
2024-05-06 14:17:08 -07:00
Jeff McCune
1279e2351a (#162) Move Platform back to holos.v1alpha1
No need to have a separate package for the PlatformService and related
protobuf messages.
2024-05-06 13:47:37 -07:00
Jeff McCune
adb8177026 Merge pull request #166 from holos-run/jeff/165-deploy-holos
(#165) Deploy Holos to Dev
2024-05-06 11:23:48 -07:00
Jeff McCune
4e8fa5abda (#165) Bump dev deployment to 0.73.1 2024-05-06 11:22:24 -07:00
Jeff McCune
6894f45b6c (#165) Deploy Holos to Dev
This patch deploys holos to the dev environment on the k2 cluster.  It's
accessible at https://app.dev.k2.holos.run/ behind the auth proxy by
default.
2024-05-06 11:10:29 -07:00
Jeff McCune
89d25be837 (#161) Wrap main router outlet in <main></main> 2024-05-06 09:16:15 -07:00
Jeff McCune
5b33e48552 (#161) Reasonably advanced form modeling the reference platform
This form goes a good way toward capturing what we need to configure the
entire reference platform.  Elements and sections are responsive to
which cloud providers are selected, which achieves my goal of modeling a
reasonably advanced form using only JSON data produced by CUE.

To write the form via the API:

    cue export ./forms/platform/ --out json \
      | jq '{platform_id: "'${platformId}'", fields: .spec.fields}' \
      | grpcurl -H "x-oidc-id-token: $(holos token)" -d @ ${host}:443 \
      holos.platform.v1alpha1.PlatformService.PutForm
2024-05-04 20:16:09 -07:00
Jeff McCune
79e8ab639a (#161) Fix the FormGroup & Refactor API
The way we were organizing fields into section broke Formly validation.
This patch fixes the problem by using the recommended approach of
[Nested Forms][1].

This patch also refactors the PlatformService API to clean it up.
GetForm / PutForm are separated from the Platform methods.  Similarly
GetModel / PutModel are separated out and are specific to get and put
the model data.

NOTE: I'm not sure we should have separated out the platform service
into it's own protobuf package.  Seems maybe unnecessary.

❯ grpcurl -H "x-oidc-id-token: $(holos token)" -d '{"platform_id":"018f36fb-e3ff-7f7f-a5d1-7ca2bf499e94"}' jeff.app.dev.k2.holos.run:443 holos.platform.v1alpha1.PlatformService.GetModel
{
  "model": {
    "org": {
      "contactEmail": "platform@openinfrastructure.co",
      "displayName": "Open Infrastructure Services LLC",
      "domain": "ois.run",
      "name": "ois"
    },
    "privacy": {
      "country": "earth",
      "regions": [
        "us-east-2",
        "us-west-2"
      ]
    },
    "terms": {
      "didAgree": true
    }
  }
}

[1]: https://formly.dev/docs/examples/other/nested-formly-forms
2024-05-04 10:14:37 -07:00
Jeff McCune
a0cc673736 (#150) Wire up select and multi select boxes
This patch wires up a Select and a Multi Select box.  This patch also
establishes a decision as it relates to Formly TypeScript / gRPC Proto3
/ CUE definitions of the form data structure.  The decision is to use
gRPC as a transport for any JSON to avoid friction trying to fit Formly
types into Proto3 messages.

Note when using google.protobuf.Value messages with bufbuild/connect-es,
we need to round trip them one last time through JSON to get the
original JSON on the other side.  This is because connect-es preserves
the type discriminators in the case and value fields of the message.

Refer to: [Accessing oneof
groups](https://github.com/bufbuild/protobuf-es/blob/main/docs/runtime_api.md#accessing-oneof-groups)

NOTE: On the wire, carry any JSON as field configs for expedience.  I
attempted to reflect FormlyFieldConfig in protobuf, but it was too time
consuming.  The loosely defined Formly json data API creates significant
friction when joined with a well defined protobuf API.  Therefore, we do
not specify anything about the Forms API, convey any valid JSON, and
leave it up to CUE and Formly on the sending and receiving side of the
API.

We use CUE to define our own holos form elements as a subset of the loose
Formly definitions.  We further hope Formly will move toward a better JSON
data API, but it's unlikely.  Consider replacing Formly entirely and
building on top of the strongly typed Angular Dyanmic Forms API.

Refer to: https://github.com/ngx-formly/ngx-formly/blob/v6.3.0/src/core/src/lib/models/fieldconfig.ts#L15
Consider: https://angular.io/guide/dynamic-form

Usage:

Generate the form from CUE

    cue export ./forms/platform/ --out json | jq -cM | pbcopy

Store the form JSON in the config_values column of the platforms table.

View the form, and submit some data. Then get the data back out for use rendering the platform:

    grpcurl -H "x-oidc-id-token: $(holos token)" -d '{"platform_id":"'${platformId}'"}' $holos holos.v1alpha1.PlatformService.GetConfig

```json
{
  "platform": {
    "spec": {
      "config": {
        "user": {
          "sections": {
            "org": {
              "fields": {
                "contactEmail": "jeff@openinfrastructure.co",
                "displayName": "Open Infrastructure Services LLC",
                "domain": "ois.run",
                "name": "ois"
              }
            },
            "privacy": {
              "fields": {
                "country": "earth",
                "regions": [
                  "us-east-2",
                  "us-west-2"
                ]
              }
            },
            "terms": {
              "fields": {
                "didAgree": true
              }
            }
          }
        }
      }
    }
  }
}
```
2024-05-03 10:42:03 -07:00
Jeff McCune
d06ecfadc8 (#150) Refactor PlatformService.GetConfig for use with CUE
Problem:
The GetConfig response value isn't directly usable with CUE without some
gymnastics.

Solution:
Refactor the protobuf definition and response output to make the user
defined and supplied config values provided by the API directly usable
in the CUE code that defines the platform.

Result:

The top level platform config is directly usable in the
`internal/platforms/bare` directory:

    grpcurl -H "x-oidc-id-token: $(holos token)" -d '{"platform_id":"'${platformID}'"}' $host \
      holos.v1alpha1.PlatformService.GetConfig \
      > platform.holos.json

Vet the user supplied data:

    cue vet ./ -d '#PlatformConfig' platform.holos.json

Build the holos component.  The ConfigMap consumes the user supplied
data:

    cue export --out yaml -t cluster=k2 ./components/configmap platform.holos.json \
      | yq .spec.components

Note the data provided by the input form is embedded into the
ConfigMap managed by Holos:

```yaml
KubernetesObjectsList:
  - metadata:
      name: platform-configmap
    apiObjectMap:
      ConfigMap:
        platform: |
          metadata:
            name: platform
            namespace: default
            labels:
              app.holos.run/managed: "true"
          data:
            platform: |
              kind: Platform
              spec:
                config:
                  user:
                    sections:
                      org:
                        fields:
                          contactEmail: jeff@openinfrastructure.co
                          displayName: Open Infrastructure Services LLC
                          domain: ois.run
                          name: ois
              apiVersion: app.holos.run/v1alpha1
              metadata:
                name: bare
                labels: {}
                annotations: {}
              holos:
                flags:
                  cluster: k2
          kind: ConfigMap
          apiVersion: v1
    Skip: false
```
2024-05-02 06:39:33 -07:00
Jeff McCune
64a117b0c3 (#150) Add PlatformService.GetConfig and refactor ConfigValues proto
Problem:
The use of google.protobuf.Any was making it awkward to work with the
data provided by the user.  The structure of the form data is defined by
the platform engineer, so the intent of Any was to wrap the data in a
way we can pass over the network and persist in the database.

The escaped JSON encoding was problematic and error prone to decode on
the other end.

Solution:
Define the Platform values as a two level map with string keys, but with
protobuf message fields "sections" and "fields" respectively.  Use
google.protobuf.Value from the struct package to encode the actual
value.

Result:
In TypeScript, google.protobuf.Value encodes and decodes easily to a
JSON value.  On the go side, connect correctly handles the value as
well.

No more ugly error prone escaping:

```
❯ grpcurl -H "x-oidc-id-token: $(holos token)" -d '{"platform_id":"'${platformId}'"}' $host holos.v1alpha1.PlatformService.GetConfig
{
  "sections": {
    "org": {
      "fields": {
        "contactEmail": "jeff@openinfrastructure.co",
        "displayName": "Open Infrastructure Services LLC",
        "domain": "ois.run",
        "name": "ois"
      }
    }
  }
}
```

This return value is intended to be directly usable in the CUE code, so
we may further nest the values into a platform.spec key.
2024-05-01 21:30:30 -07:00
Jeff McCune
cf006be9cf (#150) Add SystemService DropTables and SeedDatabase
Makes it easier to reset the database and give Gary and Nate access to
the same organization I'm in so they can provide feedback.
2024-05-01 14:30:13 -07:00
Jeff McCune
45ad3d8e63 (#150) Fix 500 error when config values aren't provided
AddPlatform was failing with a 500 error trying to decode a nil byte
slice when adding a platform without providing any values.
2024-05-01 11:31:25 -07:00
Jeff McCune
441c968c4f (#150) Look up user by iss sub, not email.
Also log when orgs are created.
2024-05-01 10:02:08 -07:00
Jeff McCune
99f2763fdf (#150) Store Platform Config Form and Values as JSON
This patch changes the backend to store the platform config form
definition and the config values supplied by the form as JSON in the
database.

The gRPC API does not change with this patch, but may need to depending
on how this works and how easy it is to evolve the data model and add
features.
2024-05-01 09:11:53 -07:00
Jeff McCune
1312395a11 (#150) Fix platforms page links
The links were hard to click.  This makes the links a much larger click
target following the example at https://material.angular.io/components/list/overview#navigation-lists
2024-05-01 08:51:29 -07:00
Jeff McCune
615f147bcb (#150) Add PutPlatformConfig to store the config values
This patch is a work in progress wiring up the form to put the values to
the holos server using grpc.

In an effort to simplify the platform configuration, the structure is a
two level map with the top level being configuration sections and the
second level being the fields associated with the config section.

To support multiple kinds of values and field controls, the values are
serialized to JSON for rpc over the network and for storage in the
database.  When they values are used, either by the UI or by the `holos
render` command, they're to be unmarshalled and in-lined into the
Platform Config data structure.

Pick back up ensuring the Platform rpc handler correctly encodes and
decodes the structure to the database.

Consider changing the config_form and config_values fields to JSON field
types in the database.  It will likely make working with this a lot
easier.

With this patch we're ready to wire up the holos render command to fetch
the platform configuration and create the end to end demo.

Here's essentially what the render command will fetch and lay down as a
json file for CUE:

```
❯ grpcurl -H "x-oidc-id-token: $(holos token)" -d '{"platform_id":"018f2c4e-ecde-7bcb-8b89-27a99e6cc7a1"}' jeff.app.dev.k2.holos.run:443 holos.v1alpha1.PlatformService.GetPlatform | jq .platform.config.values
{
  "sections": {
    "org": {
      "values": {
        "contactEmail": "\"platform@openinfrastructure.co\"",
        "displayName": "\"Open Infrastructure Services  LLC\"",
        "domain": "\"ois.run\"",
        "name": "\"ois\""
      }
    }
  }
}
```
2024-04-30 20:21:15 -07:00
Jeff McCune
d0ad3bfc69 (#150) Add Platform Detail to edit platform config
This patch adds a /platform/:id route path to a PlatformDetail
component.  The platform detail component calls the GetPlatform method
given the platform ID and renders the platform config form on the detail
tab.

The submit button is not yet wired up.

The API for adding platforms changes, allowing raw json bytes using the
RawConfig.  The raw bytes are not presented on the read path though,
calling GetPlatforms provides the platform and the config form inline in
the response.

Use the `raw_config` field instead of `config` when creating the form
data.

```
❯ grpcurl -H "x-oidc-id-token: $(holos token)" -d @ jeff.app.dev.k2.holos.run:443 holos.v1alpha1.PlatformService.AddPlatform <<EOF
{
  "platform": {
    "org_id": "018f27cd-e5ac-7f98-bfe1-2dbab208a48c",
    "name": "bare2",
    "raw_config": {
      "form": "$(cue export ./forms/platform/ --out json | jq -cM | base64 -w0)"
    }
  }
}
EOF
```
2024-04-30 14:02:49 -07:00
Jeff McCune
fe58a33747 (#150) Add holos.v1alpha1.PlatformService.GetForm
The GetForm method is intended for the Angular frontend to get
[FormlyFieldConfig][1] data for each section of the Platform config.

[1]: https://formly.dev/docs/api/core/#formlyfieldconfig

Steps to exercise for later testing:

Add the form definition to the database:

```
grpcurl -H "x-oidc-id-token: $(holos token)" -d @ jeff.app.dev.k2.holos.run:443 holos.v1alpha1.PlatformService.AddPlatform <<EOF
{
  "platform": {
    "org_id": "018f27cd-e5ac-7f98-bfe1-2dbab208a48c",
    "name": "bare${RANDOM}",
    "config": {
      "form": "$(cue export ./forms/platform/ --out json | jq -cM | base64 -w0)"
    }
  }
}
EOF
```

Get the form definition back out:

```

❯ grpcurl -H "x-oidc-id-token: $(holos token)" -d '{"platform_id":"018f2bc1-6590-7670-958a-9f3bc02b658f"}' jeff.app.dev.k2.holos.run:443 holos.v1alpha1.PlatformService.GetForm
{
  "apiVersion": "forms.holos.run/v1alpha1",
  "kind": "PlatformForm",
  "metadata": {
    "name": "bare"
  },
  "spec": {
    "sections": [
      {
        "name": "org",
        "displayName": "Organization",
        "description": "Organization config values are used to derive more specific configuration values throughout the platform.",
        "fieldConfigs": [
          {
            "key": "name",
            "type": "input",
            "props": {
              "label": "Name",
              "placeholder": "example",
              "description": "DNS label, e.g. 'example'",
              "required": true
            }
          },
          {
            "key": "domain",
            "type": "input",
            "props": {
              "label": "Domain",
              "placeholder": "example.com",
              "description": "DNS domain, e.g. 'example.com'",
              "required": true
            }
          },
          {
            "key": "displayName",
            "type": "input",
            "props": {
              "label": "Display Name",
              "placeholder": "Example Organization",
              "description": "Display name, e.g. 'Example Organization'",
              "required": true
            }
          },
          {
            "key": "contactEmail",
            "type": "input",
            "props": {
              "label": "Contact Email",
              "placeholder": "platform-team@example.com",
              "description": "Technical contact email address",
              "required": true
            }
          }
        ]
      }
    ]
  }
}
```

References

```
❯ cue export ./forms/platform/ --out yaml | yq
apiVersion: forms.holos.run/v1alpha1
kind: PlatformForm
metadata:
  name: bare
spec:
  sections:
    - name: org
      displayName: Organization
      description: Organization config values are used to derive more specific configuration values throughout the platform.
      fieldConfigs:
        - key: name
          type: input
          props:
            label: Name
            placeholder: example
            description: DNS label, e.g. 'example'
            required: true
        - key: domain
          type: input
          props:
            label: Domain
            placeholder: example.com
            description: DNS domain, e.g. 'example.com'
            required: true
        - key: displayName
          type: input
          props:
            label: Display Name
            placeholder: Example Organization
            description: Display name, e.g. 'Example Organization'
            required: true
        - key: contactEmail
          type: input
          props:
            label: Contact Email
            placeholder: platform-team@example.com
            description: Technical contact email address
            required: true
```
2024-04-29 14:24:16 -07:00
Jeff McCune
26e537e768 (#150) Add platform config form, values, cue
This patch adds 4 fields to the Platform table:

 1. Config Form represents the JSON FormlyFieldConfig for the UI.
 2. Config CUE represents the CUE file containing a definition the
    Config Values must unify with.
 3. Config Definition is the CUE definition variable name used to unify
    the values with the cue code.  Should be #PlatformSpec in most
    cases.
 4. Config Values represents the JSON values provided by the UI.

The use case is the platform engineer defines the #PlatformSpec in cue,
and provides the form field config.  The platform engineer then provides
1-3 above when adding or updating a Platform.

The UI then presents the form to the end user and provides values for 4
when the user submits the form.

This patch also refactors the AddPlatform method to accept a Platform
message.  To do so we make the id field optional since it is server
assigned.

The patch also adds a database constraint to ensure platform names are
unique within the scope of an organization.

Results:

Note how the CUE representation of the Platform Form is exported to JSON
then converted to a base64 encoded string, which is the protobuf JSON
representation of a bytes[] value.

```
grpcurl -H "x-oidc-id-token: $(holos token)" -d @ jeff.app.dev.k2.holos.run:443 holos.v1alpha1.PlatformService.AddPlatform <<EOF
{
  "platform": {
    "id": "0d3dc0c0-bbc8-41f8-8c6e-75f0476509d6",
    "org_id": "018f27cd-e5ac-7f98-bfe1-2dbab208a48c",
    "name": "bare",
    "config": {
      "form": "$(cd internal/platforms/bare && cue export ./forms/platform/ --out json | jq -cM | base64 -w0)"
    }
  }
}
EOF
```

Note the requested platform ID is ignored.

```
{
  "platforms": [
    {
      "id": "018f2af9-f7ba-772a-9db6-f985ece8fed1",
      "timestamps": {
        "createdAt": "2024-04-29T17:49:36.058379Z",
        "updatedAt": "2024-04-29T17:49:36.058379Z"
      },
      "name": "bare",
      "creator": {
        "id": "018f27cd-e591-7f98-a9d2-416167282d37"
      },
      "config": {
        "form": "eyJhcGlWZXJzaW9uIjoiZm9ybXMuaG9sb3MucnVuL3YxYWxwaGExIiwia2luZCI6IlBsYXRmb3JtRm9ybSIsIm1ldGFkYXRhIjp7Im5hbWUiOiJiYXJlIn0sInNwZWMiOnsic2VjdGlvbnMiOlt7Im5hbWUiOiJvcmciLCJkaXNwbGF5TmFtZSI6Ik9yZ2FuaXphdGlvbiIsImRlc2NyaXB0aW9uIjoiT3JnYW5pemF0aW9uIGNvbmZpZyB2YWx1ZXMgYXJlIHVzZWQgdG8gZGVyaXZlIG1vcmUgc3BlY2lmaWMgY29uZmlndXJhdGlvbiB2YWx1ZXMgdGhyb3VnaG91dCB0aGUgcGxhdGZvcm0uIiwiZmllbGRDb25maWdzIjpbeyJrZXkiOiJuYW1lIiwidHlwZSI6ImlucHV0IiwicHJvcHMiOnsibGFiZWwiOiJOYW1lIiwicGxhY2Vob2xkZXIiOiJleGFtcGxlIiwiZGVzY3JpcHRpb24iOiJETlMgbGFiZWwsIGUuZy4gJ2V4YW1wbGUnIiwicmVxdWlyZWQiOnRydWV9fSx7ImtleSI6ImRvbWFpbiIsInR5cGUiOiJpbnB1dCIsInByb3BzIjp7ImxhYmVsIjoiRG9tYWluIiwicGxhY2Vob2xkZXIiOiJleGFtcGxlLmNvbSIsImRlc2NyaXB0aW9uIjoiRE5TIGRvbWFpbiwgZS5nLiAnZXhhbXBsZS5jb20nIiwicmVxdWlyZWQiOnRydWV9fSx7ImtleSI6ImRpc3BsYXlOYW1lIiwidHlwZSI6ImlucHV0IiwicHJvcHMiOnsibGFiZWwiOiJEaXNwbGF5IE5hbWUiLCJwbGFjZWhvbGRlciI6IkV4YW1wbGUgT3JnYW5pemF0aW9uIiwiZGVzY3JpcHRpb24iOiJEaXNwbGF5IG5hbWUsIGUuZy4gJ0V4YW1wbGUgT3JnYW5pemF0aW9uJyIsInJlcXVpcmVkIjp0cnVlfX0seyJrZXkiOiJjb250YWN0RW1haWwiLCJ0eXBlIjoiaW5wdXQiLCJwcm9wcyI6eyJsYWJlbCI6IkNvbnRhY3QgRW1haWwiLCJwbGFjZWhvbGRlciI6InBsYXRmb3JtLXRlYW1AZXhhbXBsZS5jb20iLCJkZXNjcmlwdGlvbiI6IlRlY2huaWNhbCBjb250YWN0IGVtYWlsIGFkZHJlc3MiLCJyZXF1aXJlZCI6dHJ1ZX19XX1dfX0K"
      }
    }
  ]
}
```
2024-04-29 10:53:23 -07:00
Jeff McCune
ad70a6c4fe (#150) Add holos.v1alpha1.PlatformService.AddPlatform
This patch adds a basic AddPlatform method that adds a platform with a
name and a display name.

Next steps are to add fields for the Platform Config Form definition and
the Platform Config values submitted from the form.
2024-04-29 09:35:49 -07:00
Jeff McCune
22a04da6bb (#150) Add holos.v1alpha1.PlatformService.GetPlatforms
Next step: AddPlatform

Also consider extracting the queries to get the requested org_id to a
helper function.  This will likely eventually move to an interceptor
because every request is org scoped and needs authorization checks
against the org.

```
grpcurl -H "x-oidc-id-token: $(holos token)" -d '{"org_id":"018f27cd-e5ac-7f98-bfe1-2dbab208a48c"}' jeff.app.dev.k2.holos.run:443 holos.v1alpha1.PlatformService.GetPlatforms
```
2024-04-28 20:21:32 -07:00
Jeff McCune
dc97fe0ff0 (#150) Define a PlatformForm for platform design
Problem:
Platform engineers need the ability to define custom input fields for
their own platform level configuration values.  The holos web UI needs
to present the platform config values in a clean way.  The values
entered on the form need to make their way into the top level
Platform.spec field for use across all components and clusters in the
platform.

Solution:
Define a Platform Form in a forms cue package.  The output of this
definition is intended to be sent to the holos server to provide to the
web UI.

Result:
Platform engineers can define their platform config input values in
their infrastructure repository.  For example, the bare platform form
inputs are defined at `platforms/bare/forms/platform/platform-form.cue`.

This cue file produces [FormlyFieldConfig][1] output.

```console
cue export ./forms/platform/ --out yaml
```

```yaml
apiVersion: forms.holos.run/v1alpha1
kind: PlatformForm
metadata:
  name: bare
spec:
  sections:
    - name: org
      displayName: Organization
      description: Organization config values are used to derive more specific configuration values throughout the platform.
      fieldConfigs:
        - key: name
          type: input
          props:
            label: Name
            placeholder: example
            description: DNS label, e.g. 'example'
            required: true
        - key: domain
          type: input
          props:
            label: Domain
            placeholder: example.com
            description: DNS domain, e.g. 'example.com'
            required: true
        - key: displayName
          type: input
          props:
            label: Display Name
            placeholder: Example Organization
            description: Display name, e.g. 'Example Organization'
            required: true
        - key: contactEmail
          type: input
          props:
            label: Contact Email
            placeholder: platform-team@example.com
            description: Technical contact email address
            required: true
```

Next Steps:
Add a holos subcommand to produce the output and store it in the
backend.  Wire the front end to fetch the form config from the backend.

[1]: https://formly.dev/docs/api/core#formlyfieldconfig
2024-04-28 11:25:06 -07:00
Jeff McCune
9ca97c6e01 Merge pull request #148 from holos-run/jeff/147-cue-oom
(#147) Add holos render --print-instances flag
2024-04-26 16:31:14 -07:00
Jeff McCune
924653e240 (#150) Bare Platform
This patch adds a bare platform that does nothing but render a configmap
containing the platform config structure itself.

The definition of the platform structure is firming up.  The platform
designer, which may be a holos customer, is responsible for defining the
structure of the `platform.spec` output field.

Us holos developers have a reserved namespace to add configuration
fields and data in the `platform.holos` output file.

Beyond these two fields, the platform config structure has TypeMeta and
ObjectMeta fields similar to a kubernetes api object to support
versioning the platform config data, naming the platform, annotating the
platform, and labeling the platform.

The path forward from here is to:

 1. Eventually move the stable definitions into a CUE module that gets
    imported into the user's package.
 2. As a platform designer, add the organization field to the
    #PlatformSpec definition as a CUE definition.
 3. As a platform designer, add the organization field Form data
    structure as a JSON file.
 4. Add an API to upload the #PlatformSpec cue file and the
    #PlatformSpec form json file to the saas backend.
 5. Wire up Angular to pull the form json from the API and render the
    form.
 6. Wire up Angular to write the form data to a gRPC service method.
 7. Wire up the `holos cli` to read the form data from a gRPC service
    method.
 8. Tie it all together where the holos cli renders the configmap.
2024-04-26 16:14:30 -07:00
Jeff McCune
59d48f8599 (#146) Platform Config Mock Up
This patch adds a mock up of the platform config.  The goal is to use
this to connect to an anemic example platform built from `holos init`.
2024-04-26 11:29:58 -07:00
Jeff McCune
9ae45e260d (#147) Add holos render --print-instances flag
To enumerate all of the instances that could be run in separate
processes with xargs instead of run in the for loop in the Builder Run
method.
2024-04-25 13:59:10 -07:00
261 changed files with 34297 additions and 2495 deletions

View File

@@ -54,6 +54,9 @@ jobs:
- name: List keys
run: gpg -K
- name: Git diff
run: git diff
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v5
with:

1
.gitignore vendored
View File

@@ -6,3 +6,4 @@ coverage.out
*.hold/
/deploy/
.vscode/
tmp/

View File

@@ -61,10 +61,22 @@ vet: ## Vet Go code.
.PHONY: gencue
gencue: ## Generate CUE definitions
cd docs/examples && cue get go github.com/holos-run/holos/api/...
cd internal/generate/platforms && cue get go github.com/holos-run/holos/api/v1alpha1/...
.PHONY: rmgen
rmgen: ## Remove generated code
git rm -rf service/gen/ internal/frontend/holos/src/app/gen/ || true
rm -rf service/gen/ internal/frontend/holos/src/app/gen/
git rm -rf internal/ent/
rm -rf internal/ent/
git restore --staged internal/ent/generate.go internal/ent/schema/
git restore internal/ent/generate.go internal/ent/schema/
.PHONY: regenerate
regenerate: generate ## Re-generate code (delete and re-create)
.PHONY: generate
generate: ## Generate code.
generate: buf gencue ## Generate code.
go generate ./...
.PHONY: build
@@ -87,6 +99,8 @@ test: ## Run tests.
.PHONY: lint
lint: ## Run linters.
buf lint
cd internal/frontend/holos && ng lint
golangci-lint run
.PHONY: coverage
@@ -99,7 +113,7 @@ snapshot: ## Go release snapshot
.PHONY: buf
buf: ## buf generate
cd service && buf mod update
cd service && buf dep update
buf generate
.PHONY: tools

View File

@@ -38,3 +38,14 @@ func (bp *BuildPlan) Validate() error {
}
return nil
}
func (bp *BuildPlan) ResultCapacity() (count int) {
if bp == nil {
return 0
}
count = len(bp.Spec.Components.HelmChartList) +
len(bp.Spec.Components.KubernetesObjectsList) +
len(bp.Spec.Components.KustomizeBuildList) +
len(bp.Spec.Components.Resources)
return count
}

13
api/v1alpha1/form.go Normal file
View File

@@ -0,0 +1,13 @@
package v1alpha1
import object "github.com/holos-run/holos/service/gen/holos/object/v1alpha1"
// Form represents a collection of Formly json powered form.
type Form struct {
TypeMeta `json:",inline" yaml:",inline"`
Spec FormSpec `json:"spec" yaml:"spec"`
}
type FormSpec struct {
Form object.Form `json:"form" yaml:"form"`
}

22
api/v1alpha1/platform.go Normal file
View File

@@ -0,0 +1,22 @@
package v1alpha1
import "google.golang.org/protobuf/types/known/structpb"
// Platform represents a platform to manage. A Platform resource informs holos
// which components to build. The platform resource also acts as a container
// for the platform model form values provided by the PlatformService. The
// primary use case is to collect the cluster names, cluster types, platform
// model, and holos components to build into one resource.
type Platform struct {
TypeMeta `json:",inline" yaml:",inline"`
Metadata ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
Spec PlatformSpec `json:"spec,omitempty" yaml:"spec,omitempty"`
}
// PlatformSpec represents the platform build plan specification.
type PlatformSpec struct {
// Model represents the platform model holos gets from from the
// holos.platform.v1alpha1.PlatformService.GetPlatform method and provides to
// CUE using a tag.
Model structpb.Struct `json:"model,omitempty" yaml:"model,omitempty"`
}

View File

@@ -19,6 +19,14 @@ type Result struct {
accumulatedOutput string
}
// Continue returns true if Skip is true indicating the result is to be skipped over.
func (r *Result) Continue() bool {
if r == nil {
return false
}
return r.Skip
}
func (r *Result) Name() string {
return r.Metadata.Name
}
@@ -32,6 +40,11 @@ func (r *Result) KustomizationFilename(writeTo string, cluster string) string {
return filepath.Join(writeTo, "clusters", cluster, "holos", "components", r.Metadata.Name+"-kustomization.gen.yaml")
}
// KustomizationContent returns the kustomization file contents to write.
func (r *Result) KustomizationContent() string {
return r.KsContent
}
// AccumulatedOutput returns the accumulated rendered output.
func (r *Result) AccumulatedOutput() string {
return r.accumulatedOutput

View File

@@ -8,3 +8,13 @@ type TypeMeta struct {
func (tm *TypeMeta) GetKind() string {
return tm.Kind
}
func (tm *TypeMeta) GetAPIVersion() string {
return tm.Kind
}
// Discriminator is an interface to discriminate the kind api object.
type Discriminator interface {
GetKind() string
GetAPIVersion() string
}

View File

@@ -18,7 +18,3 @@ plugins:
out: internal/frontend/holos/src/app/gen
opt:
- target=ts
- plugin: connect-query
out: internal/frontend/holos/src/app/gen
opt:
- target=ts

View File

@@ -1,5 +1,3 @@
exec holos --version
# want version with no v on stdout
stdout -count=1 '^\d+\.\d+\.\d+$'
# want nothing on stderr
! stderr .

View File

@@ -0,0 +1,10 @@
{
"org_id": "018f36fb-e3f7-7f7f-a1c5-c85fb735d215",
"field_mask": {
"paths": [
"id",
"name",
"displayName"
]
}
}

View File

@@ -0,0 +1,8 @@
{
"update_mask": {
"paths": ["form"]
},
"update": {
"platform_id": "018f36fb-e3ff-7f7f-a5d1-7ca2bf499e94"
}
}

View File

@@ -0,0 +1,11 @@
{
"update_mask": {
"paths": ["model","name","display_name"]
},
"update": {
"platform_id": "018f36fb-e3ff-7f7f-a5d1-7ca2bf499e94",
"name": "bareplatform",
"display_name": "Bare Platform",
"model": {}
}
}

View File

@@ -0,0 +1,6 @@
{
"update": {
"platform_id": "018f36fb-e3ff-7f7f-a5d1-7ca2bf499e94",
"model": {}
}
}

View File

@@ -18,6 +18,7 @@ import "encoding/yaml"
Issuer?: [Name=_]: #Issuer & {metadata: name: Name}
Gateway?: [Name=_]: #Gateway & {metadata: name: Name}
ConfigMap?: [Name=_]: #ConfigMap & {metadata: name: Name}
ServiceAccount?: [Name=_]: #ServiceAccount & {metadata: name: Name}
Deployment?: [_]: #Deployment
StatefulSet?: [_]: #StatefulSet

View File

@@ -89,7 +89,8 @@ _IngressAuthProxy: {
spec: {
securityContext: seccompProfile: type: "RuntimeDefault"
containers: [{
image: "quay.io/oauth2-proxy/oauth2-proxy:v7.6.0"
// image: "quay.io/oauth3-proxy/oauth2-proxy:v7.6.0"
image: "quay.io/holos/oauth2-proxy:v7.6.0-1-g77a03ae2"
imagePullPolicy: "IfNotPresent"
name: "oauth2-proxy"
volumeMounts: [{

View File

@@ -0,0 +1,73 @@
package holos
let Namespace = "dev-holos"
let Holos = "holos"
// spec represents the output provided to holos
spec: components: KubernetesObjectsList: [
#KubernetesObjects & {
metadata: name: "dev-holos-app"
apiObjectMap: OBJECTS.apiObjectMap
},
]
// OBJECTS represents the kubernetes api objects to manage.
let OBJECTS = #APIObjects & {
apiObjects: Deployment: holos: {
metadata: {
name: Holos
namespace: Namespace
labels: app: Holos
}
spec: {
selector: matchLabels: app: Holos
template: metadata: labels: {
app: Holos
"sidecar.istio.io/inject": "true"
}
strategy: rollingUpdate: maxSurge: 1
strategy: rollingUpdate: maxUnavailable: 0
template: {
spec: {
serviceAccountName: Holos
securityContext: seccompProfile: type: "RuntimeDefault"
containers: [
{
name: Holos
image: "271053619184.dkr.ecr.us-east-2.amazonaws.com/holos-run/holos-server/holos:v0.79.0"
imagePullPolicy: "Always"
env: [
{
name: "TZ"
value: "America/Los_Angeles"
},
{
name: "DATABASE_URL"
valueFrom: secretKeyRef: {
key: "uri"
name: "holos-pguser-holos"
}
},
]
ports: [
{
containerPort: 3000
name: "http"
protocol: "TCP"
},
]
securityContext: capabilities: drop: ["ALL"]
securityContext: allowPrivilegeEscalation: false
securityContext: runAsNonRoot: true
resources: limits: {
cpu: "0.25"
memory: "256Mi"
}
resources: requests: resources.limits
},
]
}
}
}
}
}

View File

@@ -0,0 +1,129 @@
package holos
let Namespace = "dev-holos"
let Holos = "holos"
// spec represents the output provided to holos
spec: components: KubernetesObjectsList: [
#KubernetesObjects & {
metadata: name: "dev-holos-infra"
apiObjectMap: OBJECTS.apiObjectMap
},
]
let Metadata = {
name: Holos
namespace: Namespace
labels: app: Holos
}
// OBJECTS represents the kubernetes api objects to manage.
let OBJECTS = #APIObjects & {
// Postgres
// Deployment
// VirtualService
apiObjects: ServiceAccount: holos: {
metadata: Metadata
imagePullSecrets: [{name: "kube-system-ecr-image-pull-creds"}]
}
apiObjects: PostgresCluster: holos: {
apiVersion: "postgres-operator.crunchydata.com/v1beta1"
metadata: Metadata
spec: {
image: "registry.developers.crunchydata.com/crunchydata/crunchy-postgres:ubi8-16.1-0"
instances: [{
affinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: [{
podAffinityTerm: {
labelSelector: matchLabels: "postgres-operator.crunchydata.com/cluster": "holos"
topologyKey: "kubernetes.io/hostname"
}
weight: 1
}]
dataVolumeClaimSpec: {
accessModes: ["ReadWriteOnce"]
resources: requests: storage: "1Gi"
}
name: "db"
replicas: 1
}]
port: 5432
postgresVersion: 16
users: [{
databases: ["holos"]
name: "holos"
options: "SUPERUSER"
}]
backups: pgbackrest: {
global: {
"archive-async": "y"
"archive-push-queue-max": "100MiB"
"spool-path": "/pgdata/backups"
}
image: "registry.developers.crunchydata.com/crunchydata/crunchy-pgbackrest:ubi8-2.47-2"
repos: [{
name: "repo1"
volume: volumeClaimSpec: {
accessModes: ["ReadWriteOnce"]
resources: requests: storage: "1Gi"
}
}]
}
}
}
apiObjects: Service: holos: {
apiVersion: "v1"
metadata: Metadata
spec: {
type: "ClusterIP"
selector: app: "holos"
ports: [{
appProtocol: "http2"
name: "http"
port: 3000
protocol: "TCP"
targetPort: 3000
}, {
appProtocol: "http"
name: "metrics"
port: 9090
protocol: "TCP"
targetPort: 9090
}]
}
}
apiObjects: VirtualService: holos: {
apiVersion: "networking.istio.io/v1beta1"
metadata: Metadata
spec: {
gateways: ["istio-ingress/default"]
hosts: [
"app.dev.holos.run",
"app.dev.\(#ClusterName).holos.run",
]
http: [{
match: [{
uri: prefix: "/ui"
}]
name: "ui"
route: [{
destination: {
host: "holos"
port: number: 3000
}
}]
}, {
name: "api"
route: [{
destination: {
host: "holos"
port: number: 3000
}
}]
}]
}
}
}

View File

@@ -0,0 +1,92 @@
# PG Bouncer
Every few days ZITADEL fails. The problem seems to be related to pgbouncer not
being able to resolve DNS. Restarting the pgbouncer pod fixes the issue.
See [How to load-balance queries between several servers?](https://www.pgbouncer.org/faq.html#how-to-load-balance-queries-between-several-servers)
> [!NOTE]
> DNS round-robin. Use several IPs behind one DNS name. PgBouncer does not look up DNS each time a new connection is launched. Instead, it caches all IPs and does round-robin internally. Note: if there are more than 8 IPs behind one name, the DNS backend must support the EDNS0 protocol. See README for details.
## Workaround
```sh
# Get the tls based creds to bypass oidc
(cd ~/.kube && holos get secret core2-kubeconfig-admin --print-key kubeconfig.admin > core2.admin)
export KUBECONFIG=$HOME/.kube/core2.admin
# Restart pgbouncer
kubectl -n prod-iam rollout restart deployment zitadel-pgbouncer
```
## Symptom logs
```sh
kubectl -n prod-iam logs -c pgbouncer -l postgres-operator.crunchydata.com/role=pgbouncer
```
```txt
2024-05-08 17:56:11.424 UTC [7] LOG S-0x559b03f90ff0: zitadel/zitadel@10.110.109.110:5432 SSL established: TLSv1.3/TLS_AES_256_GCM_SHA384/ECDH=prime256v1
2024-05-08 17:56:11.429 UTC [7] LOG S-0x559b03f92820: zitadel/zitadel@10.110.109.110:5432 new connection to server (from 10.244.5.38:53658)
2024-05-08 17:56:11.435 UTC [7] LOG S-0x559b03f92820: zitadel/zitadel@10.110.109.110:5432 SSL established: TLSv1.3/TLS_AES_256_GCM_SHA384/ECDH=prime256v1
2024-05-08 17:56:11.476 UTC [7] LOG C-0x559b03f7a610: zitadel/zitadel@10.244.2.89:34932 closing because: client close request (age=440s)
2024-05-08 17:56:19.708 UTC [7] LOG stats: 15 xacts/s, 42 queries/s, 0 client parses/s, 0 server parses/s, 0 binds/s, in 6159 B/s, out 6124 B/s, xact 3930 us, query 869 us, wait 490 us
[msg] Nameserver 10.96.0.10:53 is back up
2024-05-08 17:57:09.366 UTC [7] LOG C-0x559b03f7a610: zitadel/zitadel@10.244.3.187:58674 login attempt: db=zitadel user=zitadel tls=TLSv1.3/TLS_AES_256_GCM_SHA384
2024-05-08 17:57:09.391 UTC [7] LOG C-0x559b03f7a610: zitadel/zitadel@10.244.3.187:58674 closing because: client close request (age=0s)
2024-05-08 17:57:19.709 UTC [7] LOG stats: 9 xacts/s, 24 queries/s, 0 client parses/s, 0 server parses/s, 0 binds/s, in 2870 B/s, out 3018 B/s, xact 4147 us, query 958 us, wait 23 us
2024-05-08 17:58:19.708 UTC [7] LOG stats: 12 xacts/s, 32 queries/s, 0 client parses/s, 0 server parses/s, 0 binds/s, in 3861 B/s, out 3533 B/s, xact 3843 us, query 853 us, wait 0 us
2024-05-08 17:56:11.411 UTC [8] LOG S-0x55a894e36650: zitadel/_crunchypgbouncer@10.110.109.110:5432 new connection to server (from 10.244.3.227:58984)
2024-05-08 17:56:11.411 UTC [8] LOG S-0x55a894e37920: zitadel/zitadel@10.110.109.110:5432 new connection to server (from 10.244.3.227:58992)
2024-05-08 17:56:11.418 UTC [8] LOG S-0x55a894e37920: zitadel/zitadel@10.110.109.110:5432 SSL established: TLSv1.3/TLS_AES_256_GCM_SHA384/ECDH=prime256v1
2024-05-08 17:56:11.420 UTC [8] LOG S-0x55a894e36650: zitadel/_crunchypgbouncer@10.110.109.110:5432 SSL established: TLSv1.3/TLS_AES_256_GCM_SHA384/ECDH=prime256v1
2024-05-08 17:56:11.438 UTC [8] LOG S-0x55a894e35b90: zitadel/zitadel@10.110.109.110:5432 new connection to server (from 10.244.3.227:59004)
2024-05-08 17:56:11.445 UTC [8] LOG S-0x55a894e35b90: zitadel/zitadel@10.110.109.110:5432 SSL established: TLSv1.3/TLS_AES_256_GCM_SHA384/ECDH=prime256v1
2024-05-08 17:56:17.148 UTC [8] LOG stats: 9 xacts/s, 27 queries/s, 0 client parses/s, 0 server parses/s, 0 binds/s, in 3236 B/s, out 2826 B/s, xact 5224 us, query 910 us, wait 1182 us
[msg] Nameserver 10.96.0.10:53 is back up
2024-05-08 17:57:17.145 UTC [8] LOG stats: 10 xacts/s, 31 queries/s, 0 client parses/s, 0 server parses/s, 0 binds/s, in 4342 B/s, out 4305 B/s, xact 4536 us, query 776 us, wait 0 us
2024-05-08 17:58:17.149 UTC [8] LOG stats: 5 xacts/s, 15 queries/s, 0 client parses/s, 0 server parses/s, 0 binds/s, in 1641 B/s, out 1582 B/s, xact 7819 us, query 1426 us, wait 0 us
```
## Relevant Configuration
`/etc/pgbouncer/pgbouncer.ini` is empty.
```
bash-4.4$ cat /etc/pgbouncer/~postgres-operator.ini
# Generated by postgres-operator. DO NOT EDIT.
# Your changes will not be saved.
[pgbouncer]
%include /etc/pgbouncer/pgbouncer.ini
[pgbouncer]
auth_file = /etc/pgbouncer/~postgres-operator/users.txt
auth_query = SELECT username, password from pgbouncer.get_auth($1)
auth_user = _crunchypgbouncer
client_tls_ca_file = /etc/pgbouncer/~postgres-operator/frontend-ca.crt
client_tls_cert_file = /etc/pgbouncer/~postgres-operator/frontend-tls.crt
client_tls_key_file = /etc/pgbouncer/~postgres-operator/frontend-tls.key
client_tls_sslmode = require
conffile = /etc/pgbouncer/~postgres-operator.ini
ignore_startup_parameters = extra_float_digits
listen_addr = *
listen_port = 5432
server_tls_ca_file = /etc/pgbouncer/~postgres-operator/backend-ca.crt
server_tls_sslmode = verify-full
unix_socket_dir =
[databases]
* = host=zitadel-primary port=5432
```
### [host](https://www.pgbouncer.org/config.html#host)
> Host name or IP address to connect to. Host names are resolved at connection time, the result is cached per dns_max_ttl parameter. When a host names resolution changes, existing server connections are automatically closed when they are released (according to the pooling mode), and new server connections immediately use the new resolution. If DNS returns several results, they are used in a round-robin manner.
### dns_max_ttl
[dns_max_ttl](https://www.pgbouncer.org/config.html#dns_max_ttl)
How long DNS lookups can be cached. The actual DNS TTL is ignored.
Default: 15.0 (seconds)

10
go.mod
View File

@@ -6,6 +6,7 @@ require (
buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go v1.33.0-20240401165935-b983156c5e99.1
connectrpc.com/connect v1.16.0
connectrpc.com/grpcreflect v1.2.0
connectrpc.com/otelconnect v0.7.0
connectrpc.com/validate v0.1.0
cuelang.org/go v0.8.0
entgo.io/ent v0.13.1
@@ -15,11 +16,13 @@ require (
github.com/fullstorydev/grpcurl v1.9.1
github.com/go-jose/go-jose/v3 v3.0.3
github.com/gofrs/uuid v4.4.0+incompatible
github.com/gogo/protobuf v1.3.2
github.com/int128/kubelogin v1.28.0
github.com/jackc/pgx/v5 v5.5.5
github.com/lmittmann/tint v1.0.4
github.com/mattn/go-isatty v0.0.20
github.com/mattn/go-runewidth v0.0.15
github.com/mennanov/fieldmask-utils v1.1.2
github.com/olekukonko/tablewriter v0.0.5
github.com/prometheus/client_golang v1.19.0
github.com/rogpeppe/go-internal v1.12.0
@@ -29,6 +32,7 @@ require (
github.com/stretchr/testify v1.9.0
golang.org/x/net v0.24.0
golang.org/x/tools v0.20.0
google.golang.org/genproto/googleapis/rpc v0.0.0-20240325203815-454cdb8f5daa
google.golang.org/protobuf v1.33.1-0.20240408130810-98873a205002
honnef.co/go/tools v0.4.7
k8s.io/api v0.29.2
@@ -43,7 +47,6 @@ require (
ariga.io/atlas v0.19.1-0.20240203083654-5948b60a8e43 // indirect
cloud.google.com/go/compute v1.23.3 // indirect
cloud.google.com/go/compute/metadata v0.2.3 // indirect
connectrpc.com/otelconnect v0.7.0 // indirect
cuelabs.dev/go/oci/ociregistry v0.0.0-20240314152124-224736b49f2e // indirect
github.com/AlecAivazis/survey/v2 v2.3.7 // indirect
github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
@@ -84,7 +87,7 @@ require (
github.com/distribution/reference v0.6.0 // indirect
github.com/docker/cli v26.0.0+incompatible // indirect
github.com/docker/distribution v2.8.3+incompatible // indirect
github.com/docker/docker v26.0.0+incompatible // indirect
github.com/docker/docker v26.0.2+incompatible // indirect
github.com/docker/docker-credential-helpers v0.8.1 // indirect
github.com/docker/go-connections v0.5.0 // indirect
github.com/docker/go-units v0.5.0 // indirect
@@ -112,7 +115,6 @@ require (
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/gobwas/glob v0.2.3 // indirect
github.com/gofrs/uuid/v5 v5.0.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/protobuf v1.5.4 // indirect
@@ -245,8 +247,8 @@ require (
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect
google.golang.org/appengine v1.6.8 // indirect
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240325203815-454cdb8f5daa // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240325203815-454cdb8f5daa // indirect
google.golang.org/grpc v1.62.1 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect

30
go.sum
View File

@@ -86,6 +86,7 @@ github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tj
github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8=
github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/antlr4-go/antlr/v4 v4.13.0 h1:lxCg3LAv+EUK6t1i0y1V6/SLeUi0eKEKdhQAlS8TVTI=
github.com/antlr4-go/antlr/v4 v4.13.0/go.mod h1:pfChB/xh/Unjila75QW7+VU4TSnWnnk9UTnmpPaOR2g=
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
@@ -115,6 +116,7 @@ github.com/census-instrumentation/opencensus-proto v0.4.1 h1:iKLQ0xPNFxR/2hzXZMr
github.com/census-instrumentation/opencensus-proto v0.4.1/go.mod h1:4T9NM4+4Vw91VeyqjLS6ao50K5bOcLKN6Q42XnYaRYw=
github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cheekybits/genny v1.0.0 h1:uGGa4nei+j20rOSeDeP5Of12XVm7TGUd4dJA9RDitfE=
@@ -144,9 +146,13 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cloudevents/sdk-go/v2 v2.15.2 h1:54+I5xQEnI73RBhWHxbI1XJcqOFOVJN85vb41+8mHUc=
github.com/cloudevents/sdk-go/v2 v2.15.2/go.mod h1:lL7kSWAE/V8VI4Wh0jbL2v/jvqsm6tjmaQBSvxcv4uE=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe h1:QQ3GSy+MqSHxm/d8nCtnAiZdYFd45cYZPs8vOOIYKfk=
github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ=
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM=
github.com/cockroachdb/apd/v3 v3.2.1 h1:U+8j7t0axsIgvQUqthuNm82HIrYXodOV2iWLWtEaIwg=
@@ -181,8 +187,8 @@ github.com/docker/cli v26.0.0+incompatible h1:90BKrx1a1HKYpSnnBFR6AgDq/FqkHxwlUy
github.com/docker/cli v26.0.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk=
github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v26.0.0+incompatible h1:Ng2qi+gdKADUa/VM+6b6YaY2nlZhk/lVJiKR/2bMudU=
github.com/docker/docker v26.0.0+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v26.0.2+incompatible h1:yGVmKUFGgcxA6PXWAokO0sQL22BrQ67cgVjko8tGdXE=
github.com/docker/docker v26.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.8.1 h1:j/eKUktUltBtMzKqmfLB0PAgqYyMHOp5vfsD1807oKo=
github.com/docker/docker-credential-helpers v0.8.1/go.mod h1:P3ci7E3lwkZg6XiHdRKft1KckHiO9a2rNtyFbZ/ry9M=
github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c=
@@ -198,6 +204,8 @@ github.com/emicklei/proto v1.10.0/go.mod h1:rn1FgRS/FANiZdD2djyH7TMA9jdRDcYQ9IEN
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
github.com/envoyproxy/go-control-plane v0.12.0 h1:4X+VP1GHd1Mhj6IB5mMeGbLCleqxjletLK6K0rbxyZI=
github.com/envoyproxy/go-control-plane v0.12.0/go.mod h1:ZBTaoJ23lqITozF0M6G4/IragXCQKCnYbmlmtHvwRG0=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
@@ -307,6 +315,7 @@ github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:W
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
@@ -356,6 +365,7 @@ github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaU
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
github.com/google/subcommands v1.0.1/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8=
@@ -374,6 +384,7 @@ github.com/gosuri/uilive v0.0.4 h1:hUEBpQDj8D8jXgtCdBu7sWsy5sbW/5GhuO8KBwJ2jyY=
github.com/gosuri/uilive v0.0.4/go.mod h1:V/epo5LjjlDE5RJUcqx8dbw+zc93y5Ya3yg8tfZ74VI=
github.com/gosuri/uiprogress v0.0.1 h1:0kpv/XY/qTmFWl/SkaJykZXrBBzwwadmW8fRb7RJSxw=
github.com/gosuri/uiprogress v0.0.1/go.mod h1:C1RTYn4Sc7iEyf6j8ft5dyoZ4212h8G1ol9QQluh5+0=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No=
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU=
github.com/guptarohit/asciigraph v0.7.1 h1:K+JWbRc04XEfv8BSZgNuvhCmpbvX4+9NYd/UxXVnAuk=
@@ -468,6 +479,8 @@ github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZ
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/mennanov/fieldmask-utils v1.1.2 h1:f5hd3hYeWdl+q2thiKYyZZmqTqn90uayWG03bca9U+E=
github.com/mennanov/fieldmask-utils v1.1.2/go.mod h1:xRqd9Fjz/gFEDYCQw7pxGouxqLhSPrkOdx2yhEAXEls=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI=
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
@@ -568,6 +581,7 @@ github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
@@ -686,6 +700,7 @@ go.opentelemetry.io/otel/sdk/metric v1.19.0 h1:EJoTO5qysMsYCa+w4UghwFV/ptQgqSL/8
go.opentelemetry.io/otel/sdk/metric v1.19.0/go.mod h1:XjG0jQyFJrv2PbMvwND7LwCEhsJzCzV5210euduKcKY=
go.opentelemetry.io/otel/trace v1.25.0 h1:tqukZGLwQYRIFtSQM2u2+yfMVTgGVeqRLPUYx1Dq6RM=
go.opentelemetry.io/otel/trace v1.25.0/go.mod h1:hCCs70XM/ljO+BeQkyFnbK28SBIJ/Emuha+ccrCRT7I=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.opentelemetry.io/proto/otlp v1.1.0 h1:2Di21piLrCqJ3U3eXGCTPHE9R8Nh+0uglSnOyxikMeI=
go.opentelemetry.io/proto/otlp v1.1.0/go.mod h1:GpBHCBWiqvVLDqmHZsoMM3C5ySeKTC7ej/RNTae6MdY=
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
@@ -833,6 +848,7 @@ golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -979,12 +995,16 @@ google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfG
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20220531173845-685668d2de03/go.mod h1:yKyY4AMRwFiC8yMMNaMi+RkCnjZJt9LoWuvhXjMs+To=
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 h1:KAeGQVN3M9nD0/bQXnr/ClcEMJ968gUXJQ9pwfSynuQ=
google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80/go.mod h1:cc8bqMqtv9gMOr0zHg2Vzff5ULhhL2IXP4sbcn32Dro=
google.golang.org/genproto/googleapis/api v0.0.0-20240325203815-454cdb8f5daa h1:Jt1XW5PaLXF1/ePZrznsh/aAUvI7Adfc3LY1dAKlzRs=
google.golang.org/genproto/googleapis/api v0.0.0-20240325203815-454cdb8f5daa/go.mod h1:K4kfzHtI0kqWA79gecJarFtDn/Mls+GxQcg3Zox91Ac=
google.golang.org/genproto/googleapis/rpc v0.0.0-20240325203815-454cdb8f5daa h1:RBgMaUMP+6soRkik4VoN8ojR2nex2TqZwjSSogic+eo=
@@ -1001,6 +1021,9 @@ google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKa
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
google.golang.org/grpc v1.62.1 h1:B4n+nfKzOICUXMgyrNd19h/I9oH0L1pizfk1d4zSgTk=
google.golang.org/grpc v1.62.1/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
@@ -1015,6 +1038,8 @@ google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGj
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.33.1-0.20240408130810-98873a205002 h1:V7Da7qt0MkY3noVANIMVBk28nOnijADeOR3i5Hcvpj4=
google.golang.org/protobuf v1.33.1-0.20240408130810-98873a205002/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
@@ -1026,6 +1051,7 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=

16
hack/setup/bare Executable file
View File

@@ -0,0 +1,16 @@
#! /bin/bash
set -euo pipefail
TOPLEVEL="$(cd $(dirname "$0") && git rev-parse --show-toplevel)"
host="jeff.app.dev.k2.holos.run:443"
read -p "Reset all data in $host? " choice
case "$choice" in
y|Y) echo "proceeding...";;
*) exit 1;;
esac
grpcurl -H "x-oidc-id-token: $(holos token)" $host holos.v1alpha1.SystemService.DropTables
grpcurl -H "x-oidc-id-token: $(holos token)" $host holos.v1alpha1.SystemService.SeedDatabase

View File

@@ -3,5 +3,6 @@ USER root
WORKDIR /app
ADD bin bin
RUN chown -R app: /app
USER app
# Kubernetes requires the user to be numeric
USER 8192
ENTRYPOINT bin/holos server

View File

@@ -1,10 +1,10 @@
// Package holos defines types for the rest of the system.
package holos
// A PathCueMod is a string representing the filesystem path of a cue module.
// It is given a unique type so the API is clear.
// A PathCueMod is a string representing the absolute filesystem path of a cue
// module. It is given a unique type so the API is clear.
type PathCueMod string
// A InstancePath is a string representing the filesystem path of a holos instance.
// It is given a unique type so the API is clear.
// A InstancePath is a string representing the absolute filesystem path of a
// holos instance. It is given a unique type so the API is clear.
type InstancePath string

275
internal/builder/builder.go Normal file
View File

@@ -0,0 +1,275 @@
// Package builder is responsible for building fully rendered kubernetes api
// objects from various input directories. A directory may contain a platform
// spec or a component spec.
package builder
import (
"bytes"
"context"
"encoding/json"
"fmt"
"os"
"path/filepath"
"cuelang.org/go/cue/build"
"cuelang.org/go/cue/cuecontext"
"cuelang.org/go/cue/load"
"github.com/holos-run/holos/api/v1alpha1"
"github.com/holos-run/holos"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/logger"
)
const (
KubernetesObjects = v1alpha1.KubernetesObjectsKind
// Helm is the value of the kind field of holos build output indicating helm
// values and helm command information.
Helm = v1alpha1.HelmChartKind
// Skip is the value when the instance should be skipped
Skip = "Skip"
// KustomizeBuild is the value of the kind field of cue output indicating holos should process the component using kustomize build to render output.
KustomizeBuild = v1alpha1.KustomizeBuildKind
)
// An Option configures a Builder
type Option func(*config)
type config struct {
args []string
cluster string
}
type Builder struct {
cfg config
}
// New returns a new *Builder configured by opts Option.
func New(opts ...Option) *Builder {
var cfg config
for _, f := range opts {
f(&cfg)
}
b := &Builder{cfg: cfg}
return b
}
// Entrypoints configures the leaf directories Builder builds.
func Entrypoints(args []string) Option {
return func(cfg *config) { cfg.args = args }
}
// Cluster configures the cluster name for the holos component instance.
func Cluster(name string) Option {
return func(cfg *config) { cfg.cluster = name }
}
// Cluster returns the cluster name of the component instance being built.
func (b *Builder) Cluster() string {
return b.cfg.cluster
}
// Instances returns the cue build instances being built.
func (b *Builder) Instances(ctx context.Context) ([]*build.Instance, error) {
log := logger.FromContext(ctx)
mod, err := b.findCueMod()
if err != nil {
return nil, errors.Wrap(err)
}
dir := string(mod)
cfg := load.Config{Dir: dir}
// Make args relative to the module directory
args := make([]string, len(b.cfg.args))
for idx, path := range b.cfg.args {
target, err := filepath.Abs(path)
if err != nil {
return nil, errors.Wrap(fmt.Errorf("could not find absolute path: %w", err))
}
relPath, err := filepath.Rel(dir, target)
if err != nil {
return nil, errors.Wrap(fmt.Errorf("invalid argument, must be relative to cue.mod: %w", err))
}
relPath = "./" + relPath
args[idx] = relPath
equiv := fmt.Sprintf("cue export --out yaml -t cluster=%v %v", b.Cluster(), relPath)
log.Debug("cue: equivalent command: " + equiv)
}
// Refer to https://github.com/cue-lang/cue/blob/v0.7.0/cmd/cue/cmd/common.go#L429
if b.Cluster() != "" {
cfg.Tags = append(cfg.Tags, "cluster="+b.Cluster())
}
log.DebugContext(ctx, fmt.Sprintf("cue: tags %v", cfg.Tags))
return load.Instances(args, &cfg), nil
}
func (b *Builder) Run(ctx context.Context) (results []*v1alpha1.Result, err error) {
log := logger.FromContext(ctx)
log.DebugContext(ctx, "cue: building instances")
instances, err := b.Instances(ctx)
if err != nil {
return nil, err
}
results = make([]*v1alpha1.Result, 0, len(instances)*8)
// Each CUE instance provides a BuildPlan
for idx, instance := range instances {
log.DebugContext(ctx, "cue: building instance", "idx", idx, "dir", instance.Dir)
r, err := b.runInstance(ctx, instance)
if err != nil {
return nil, errors.Wrap(fmt.Errorf("could not run: %w", err))
}
results = append(results, r...)
}
return results, nil
}
func (b Builder) runInstance(ctx context.Context, instance *build.Instance) (results []*v1alpha1.Result, err error) {
path := holos.InstancePath(instance.Dir)
log := logger.FromContext(ctx).With("dir", path)
if err := instance.Err; err != nil {
return nil, errors.Wrap(fmt.Errorf("could not load: %w", err))
}
cueCtx := cuecontext.New()
value := cueCtx.BuildInstance(instance)
if err := value.Err(); err != nil {
return nil, errors.Wrap(fmt.Errorf("could not build %s: %w", instance.Dir, err))
}
log.DebugContext(ctx, "cue: validating instance")
if err := value.Validate(); err != nil {
return nil, errors.Wrap(fmt.Errorf("could not validate: %w", err))
}
log.DebugContext(ctx, "cue: decoding holos build plan")
jsonBytes, err := value.MarshalJSON()
if err != nil {
return nil, errors.Wrap(fmt.Errorf("could not marshal cue instance %s: %w", instance.Dir, err))
}
decoder := json.NewDecoder(bytes.NewReader(jsonBytes))
// Discriminate the type of build plan.
tm := &v1alpha1.TypeMeta{}
err = decoder.Decode(tm)
if err != nil {
return nil, errors.Wrap(fmt.Errorf("invalid BuildPlan: %s: %w", instance.Dir, err))
}
log.DebugContext(ctx, "cue: discriminated build kind: "+tm.Kind, "kind", tm.Kind, "apiVersion", tm.APIVersion)
// New decoder for the full object
decoder = json.NewDecoder(bytes.NewReader(jsonBytes))
decoder.DisallowUnknownFields()
switch tm.Kind {
case "BuildPlan":
var bp v1alpha1.BuildPlan
if err = decoder.Decode(&bp); err != nil {
err = errors.Wrap(fmt.Errorf("could not decode BuildPlan %s: %w", instance.Dir, err))
return
}
results, err = b.buildPlan(ctx, &bp, path)
case "Platform":
var pf v1alpha1.Platform
if err = decoder.Decode(&pf); err != nil {
err = errors.Wrap(fmt.Errorf("could not decode Platform %s: %w", instance.Dir, err))
return
}
results, err = b.buildPlatform(ctx, &pf)
default:
err = errors.Wrap(fmt.Errorf("unknown kind: %v", tm.Kind))
}
return
}
func (b *Builder) buildPlatform(ctx context.Context, pf *v1alpha1.Platform) (results []*v1alpha1.Result, err error) {
log := logger.FromContext(ctx)
log.ErrorContext(ctx, "not implemented", "platform", pf)
return nil, errors.Wrap(fmt.Errorf("not implemeneted"))
}
func (b *Builder) buildPlan(ctx context.Context, buildPlan *v1alpha1.BuildPlan, path holos.InstancePath) (results []*v1alpha1.Result, err error) {
log := logger.FromContext(ctx)
if err := buildPlan.Validate(); err != nil {
log.WarnContext(ctx, "could not validate", "skipped", true, "err", err)
return nil, errors.Wrap(fmt.Errorf("could not validate %w", err))
}
if buildPlan.Spec.Disabled {
log.DebugContext(ctx, "skipped: spec.disabled is true", "skipped", true)
return
}
// TODO: concurrent renders
results = make([]*v1alpha1.Result, 0, buildPlan.ResultCapacity())
log.DebugContext(ctx, "allocated results slice", "cap", buildPlan.ResultCapacity())
for _, component := range buildPlan.Spec.Components.Resources {
if result, err := component.Render(ctx, path); err != nil {
return nil, errors.Wrap(fmt.Errorf("could not render: %w", err))
} else {
results = append(results, result)
}
}
for _, component := range buildPlan.Spec.Components.KubernetesObjectsList {
if result, err := component.Render(ctx, path); err != nil {
return nil, errors.Wrap(fmt.Errorf("could not render: %w", err))
} else {
results = append(results, result)
}
}
for _, component := range buildPlan.Spec.Components.HelmChartList {
if result, err := component.Render(ctx, path); err != nil {
return nil, errors.Wrap(fmt.Errorf("could not render: %w", err))
} else {
results = append(results, result)
}
}
for _, component := range buildPlan.Spec.Components.KustomizeBuildList {
if result, err := component.Render(ctx, path); err != nil {
return nil, errors.Wrap(fmt.Errorf("could not render: %w", err))
} else {
results = append(results, result)
}
}
log.DebugContext(ctx, "returning results", "len", len(results))
return results, nil
}
// findCueMod returns the root module location containing the cue.mod file or
// directory or an error if the builder arguments do not share a common root
// module.
func (b *Builder) findCueMod() (dir holos.PathCueMod, err error) {
for _, origPath := range b.cfg.args {
absPath, err := filepath.Abs(origPath)
if err != nil {
return "", err
}
path := holos.PathCueMod(absPath)
for {
if _, err := os.Stat(filepath.Join(string(path), "cue.mod")); err == nil {
if dir != "" && dir != path {
return "", fmt.Errorf("multiple modules not supported: %v is not %v", dir, path)
}
dir = path
break
} else if !os.IsNotExist(err) {
return "", err
}
parentPath := holos.PathCueMod(filepath.Dir(string(path)))
if parentPath == path {
return "", fmt.Errorf("no cue.mod from root to leaf: %v", origPath)
}
path = parentPath
}
}
return dir, nil
}

View File

@@ -2,12 +2,13 @@ package build
import (
"fmt"
"log/slog"
"strings"
"github.com/holos-run/holos/internal/builder"
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/holos"
"github.com/holos-run/holos/internal/internal/builder"
"github.com/spf13/cobra"
)
@@ -20,10 +21,12 @@ func makeBuildRunFunc(cfg *holos.Config) command.RunFunc {
return err
}
outs := make([]string, 0, len(results))
for _, result := range results {
if result.Skip {
for idx, result := range results {
if result == nil || result.Skip {
slog.Debug("skip result", "idx", idx, "result", result)
continue
}
slog.Debug("append result", "idx", idx, "result.kind", result.Kind)
outs = append(outs, result.AccumulatedOutput())
}
out := strings.Join(outs, "---\n")

View File

@@ -0,0 +1,47 @@
package generate
import (
"fmt"
"strings"
"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/generate"
"github.com/holos-run/holos/internal/holos"
"github.com/spf13/cobra"
)
// New returns a new generate command.
func New(cfg *holos.Config) *cobra.Command {
cmd := command.New("generate")
cmd.Aliases = []string{"gen"}
cmd.Short = "generate local resources"
cmd.Args = cobra.NoArgs
cmd.AddCommand(NewPlatform(cfg))
return cmd
}
func NewPlatform(cfg *holos.Config) *cobra.Command {
cmd := command.New("platform")
cmd.Use = "platform [flags] PLATFORM"
cmd.Short = "generate a platform from an embedded schematic"
cmd.Long = fmt.Sprintf("Embedded platforms available to generate:\n\n %s", strings.Join(generate.Platforms(), "\n "))
cmd.Args = cobra.ExactArgs(1)
cmd.RunE = func(cmd *cobra.Command, args []string) error {
ctx := cmd.Root().Context()
clientContext := holos.NewClientContext(ctx)
client := client.New(client.NewConfig(cfg))
for _, name := range args {
if err := generate.GeneratePlatform(ctx, client, clientContext.OrgID, name); err != nil {
return errors.Wrap(err)
}
}
return nil
}
return cmd
}

View File

@@ -5,9 +5,11 @@ import (
"fmt"
"log/slog"
"connectrpc.com/connect"
cue "cuelang.org/go/cue/errors"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/holos"
"google.golang.org/genproto/googleapis/rpc/errdetails"
)
// MakeMain makes a main function for the cli or tests.
@@ -25,7 +27,8 @@ func MakeMain(options ...holos.Option) func() int {
// HandleError is the top level error handler that unwraps and logs errors.
func HandleError(ctx context.Context, err error, hc *holos.Config) (exitCode int) {
log := hc.NewTopLevelLogger()
// Connect errors have codes, log them.
log := hc.NewTopLevelLogger().With("code", connect.CodeOf(err))
var cueErr cue.Error
var errAt *errors.ErrorAt
const msg = "could not execute"
@@ -39,5 +42,24 @@ func HandleError(ctx context.Context, err error, hc *holos.Config) (exitCode int
msg := cue.Details(cueErr, nil)
_, _ = fmt.Fprint(hc.Stderr(), msg)
}
// connect errors have details and codes.
// Refer to https://connectrpc.com/docs/go/errors
if connectErr := new(connect.Error); errors.As(err, &connectErr) {
for _, detail := range connectErr.Details() {
msg, valueErr := detail.Value()
if valueErr != nil {
log.WarnContext(ctx, "could not decode error detail", "err", err, "type", detail.Type(), "note", "this usually means we don't have the schema for the protobuf message type")
continue
}
if info, ok := msg.(*errdetails.ErrorInfo); ok {
logDetail := log.With("reason", info.GetReason(), "domain", info.GetDomain())
for k, v := range info.GetMetadata() {
logDetail = logDetail.With(k, v)
}
logDetail.ErrorContext(ctx, info.String())
}
}
}
return 1
}

76
internal/cli/push/push.go Normal file
View File

@@ -0,0 +1,76 @@
// Package push pushes resources to the holos api server.
package push
import (
"fmt"
"log/slog"
"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/holos-run/holos/internal/push"
"github.com/holos-run/holos/internal/server/middleware/logger"
"github.com/spf13/cobra"
)
func New(cfg *holos.Config) *cobra.Command {
cmd := command.New("push")
cmd.Short = "push resources to holos server"
cmd.Args = cobra.NoArgs
config := client.NewConfig(cfg)
cmd.PersistentFlags().AddGoFlagSet(config.ClientFlagSet())
cmd.PersistentFlags().AddGoFlagSet(config.TokenFlagSet())
cmd.AddCommand(NewPlatform(config))
return cmd
}
func NewPlatform(cfg *client.Config) *cobra.Command {
cmd := command.New("platform")
cmd.Short = "push platform resources to holos server"
cmd.Args = cobra.NoArgs
cmd.AddCommand(NewPlatformForm(cfg))
// cmd.AddCommand(NewPlatformModel(cfg))
return cmd
}
func NewPlatformForm(cfg *client.Config) *cobra.Command {
cmd := command.New("form")
cmd.Short = "push platform form to holos server"
cmd.Args = cobra.MinimumNArgs(1)
cmd.RunE = func(cmd *cobra.Command, args []string) error {
ctx := cmd.Root().Context()
if ctx == nil {
return errors.Wrap(errors.New("cannot execute: no context"))
}
ctx = logger.NewContext(ctx, logger.FromContext(ctx).With("server", cfg.Client().Server()))
rpc := client.New(cfg)
for _, name := range args {
// Get the platform metadata for the platform id.
p, err := push.LoadPlatform(ctx, name)
if err != nil {
return errors.Wrap(err)
}
// Build the form from the cue code.
form, err := push.PlatformForm(ctx, name)
if err != nil {
return errors.Wrap(err)
}
// Make the rpc call to update the platform form.
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()))
}
return nil
}
return cmd
}

View File

@@ -0,0 +1,36 @@
// Package register provides user registration via the command line.
package register
import (
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/client"
"github.com/holos-run/holos/internal/holos"
"github.com/holos-run/holos/internal/register"
"github.com/spf13/cobra"
)
// New returns a new register command.
func New(cfg *holos.Config) *cobra.Command {
cmd := command.New("register")
cmd.Short = "register with holos server"
cmd.Args = cobra.NoArgs
config := client.NewConfig(cfg)
cmd.PersistentFlags().AddGoFlagSet(config.ClientFlagSet())
cmd.PersistentFlags().AddGoFlagSet(config.TokenFlagSet())
cmd.AddCommand(NewUser(config))
return cmd
}
// NewUser returns a command to register a user with holos server.
func NewUser(cfg *client.Config) *cobra.Command {
cmd := command.New("user")
cmd.Short = "user registration workflow"
cmd.RunE = func(cmd *cobra.Command, args []string) error {
ctx := cmd.Root().Context()
return register.User(ctx, cfg)
}
return cmd
}

View File

@@ -1,52 +1,18 @@
package render
import (
"context"
"flag"
"fmt"
"github.com/holos-run/holos/internal/builder"
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/holos"
"github.com/holos-run/holos/internal/internal/builder"
"github.com/holos-run/holos/internal/logger"
"github.com/spf13/cobra"
)
func makeRenderRunFunc(cfg *holos.Config) command.RunFunc {
return func(cmd *cobra.Command, args []string) error {
if cfg.ClusterName() == "" {
return errors.Wrap(fmt.Errorf("missing cluster name"))
}
ctx := cmd.Context()
log := logger.FromContext(ctx).With("cluster", cfg.ClusterName())
build := builder.New(builder.Entrypoints(args), builder.Cluster(cfg.ClusterName()))
results, err := build.Run(cmd.Context())
if err != nil {
return errors.Wrap(err)
}
// TODO: Avoid accidental over-writes if to holos component instances result in
// the same file path. Write files into a blank temporary directory, error if a
// file exists, then move the directory into place.
for _, result := range results {
if result.Skip {
continue
}
// API Objects
path := result.Filename(cfg.WriteTo(), cfg.ClusterName())
if err := result.Save(ctx, path, result.AccumulatedOutput()); err != nil {
return errors.Wrap(err)
}
// Kustomization
path = result.KustomizationFilename(cfg.WriteTo(), cfg.ClusterName())
if err := result.Save(ctx, path, result.KsContent); err != nil {
return errors.Wrap(err)
}
log.InfoContext(ctx, "rendered "+result.Name(), "status", "ok", "action", "rendered", "name", result.Name())
}
return nil
}
}
// New returns the render subcommand for the root command
func New(cfg *holos.Config) *cobra.Command {
cmd := command.New("render [directory...]")
@@ -55,6 +21,63 @@ func New(cfg *holos.Config) *cobra.Command {
cmd.Flags().SortFlags = false
cmd.Flags().AddGoFlagSet(cfg.WriteFlagSet())
cmd.Flags().AddGoFlagSet(cfg.ClusterFlagSet())
cmd.RunE = makeRenderRunFunc(cfg)
var printInstances bool
flagSet := flag.NewFlagSet("", flag.ContinueOnError)
flagSet.BoolVar(&printInstances, "print-instances", false, "expand /... paths for xargs")
cmd.Flags().AddGoFlagSet(flagSet)
cmd.RunE = func(cmd *cobra.Command, args []string) error {
ctx := cmd.Root().Context()
log := logger.FromContext(ctx).With("cluster", cfg.ClusterName())
build := builder.New(builder.Entrypoints(args), builder.Cluster(cfg.ClusterName()))
if printInstances {
instances, err := build.Instances(ctx)
if err != nil {
return errors.Wrap(err)
}
for _, instance := range instances {
fmt.Fprintln(cmd.OutOrStdout(), instance.Dir)
}
return nil
}
results, err := build.Run(cmd.Context())
if err != nil {
return errors.Wrap(err)
}
// TODO: Avoid accidental over-writes if to holos component instances result in
// the same file path. Write files into a blank temporary directory, error if a
// file exists, then move the directory into place.
var result Result
for _, result = range results {
if result.Continue() {
continue
}
// API Objects
path := result.Filename(cfg.WriteTo(), cfg.ClusterName())
if err := result.Save(ctx, path, result.AccumulatedOutput()); err != nil {
return errors.Wrap(err)
}
// Kustomization
path = result.KustomizationFilename(cfg.WriteTo(), cfg.ClusterName())
if err := result.Save(ctx, path, result.KustomizationContent()); err != nil {
return errors.Wrap(err)
}
log.InfoContext(ctx, "rendered "+result.Name(), "status", "ok", "action", "rendered", "name", result.Name())
}
return nil
}
return cmd
}
type Result interface {
Continue() bool
Name() string
Filename(writeTo string, cluster string) string
KustomizationFilename(writeTo string, cluster string) string
Save(ctx context.Context, path string, content string) error
AccumulatedOutput() string
KustomizationContent() string
}

View File

@@ -1,26 +1,33 @@
package cli
import (
"fmt"
"log/slog"
"github.com/spf13/cobra"
"github.com/holos-run/holos/version"
"github.com/holos-run/holos/internal/holos"
"github.com/holos-run/holos/internal/logger"
"github.com/holos-run/holos/internal/server"
"github.com/holos-run/holos/internal/cli/build"
"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/generate"
"github.com/holos-run/holos/internal/cli/get"
"github.com/holos-run/holos/internal/cli/kv"
"github.com/holos-run/holos/internal/cli/login"
"github.com/holos-run/holos/internal/cli/logout"
"github.com/holos-run/holos/internal/cli/preflight"
"github.com/holos-run/holos/internal/cli/push"
"github.com/holos-run/holos/internal/cli/register"
"github.com/holos-run/holos/internal/cli/render"
"github.com/holos-run/holos/internal/cli/rpc"
"github.com/holos-run/holos/internal/cli/token"
"github.com/holos-run/holos/internal/cli/txtar"
"github.com/holos-run/holos/internal/holos"
"github.com/holos-run/holos/internal/logger"
"github.com/holos-run/holos/version"
)
// New returns a new root *cobra.Command for command line execution.
@@ -40,7 +47,7 @@ func New(cfg *holos.Config) *cobra.Command {
return err
}
log := cfg.Logger()
c.SetContext(logger.NewContext(c.Context(), log))
c.Root().SetContext(logger.NewContext(c.Context(), log))
// Set the default logger after flag parsing.
slog.SetDefault(log)
return nil
@@ -63,6 +70,11 @@ func New(cfg *holos.Config) *cobra.Command {
rootCmd.AddCommand(login.New(cfg))
rootCmd.AddCommand(logout.New(cfg))
rootCmd.AddCommand(token.New(cfg))
rootCmd.AddCommand(rpc.New(cfg))
rootCmd.AddCommand(generate.New(cfg))
rootCmd.AddCommand(register.New(cfg))
rootCmd.AddCommand(push.New(cfg))
rootCmd.AddCommand(newOrgCmd())
// Maybe not needed?
rootCmd.AddCommand(txtar.New(cfg))
@@ -78,3 +90,15 @@ func New(cfg *holos.Config) *cobra.Command {
return rootCmd
}
func newOrgCmd() (cmd *cobra.Command) {
cmd = command.New("orgid")
cmd.Short = "print the current context org id."
cmd.RunE = func(cmd *cobra.Command, args []string) error {
ctx := cmd.Root().Context()
cc := holos.NewClientContext(ctx)
_, err := fmt.Fprintln(cmd.OutOrStdout(), cc.OrgID)
return err
}
return cmd
}

70
internal/cli/rpc/rpc.go Normal file
View File

@@ -0,0 +1,70 @@
package rpc
import (
"encoding/json"
"fmt"
"connectrpc.com/connect"
"github.com/holos-run/holos/internal/cli/command"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/holos"
"github.com/holos-run/holos/internal/server/middleware/logger"
"github.com/holos-run/holos/internal/token"
platform "github.com/holos-run/holos/service/gen/holos/platform/v1alpha1"
"github.com/holos-run/holos/service/gen/holos/platform/v1alpha1/platformconnect"
"github.com/spf13/cobra"
)
// Remove these
const BarePlatformID = "018f36fb-e3ff-7f7f-a5d1-7ca2bf499e94"
type Config struct {
holos *holos.Config
client *holos.ClientConfig
token *token.Config
}
// New returns a new rpc command.
func New(cfg *holos.Config) *cobra.Command {
cmd := command.New("rpc")
cmd.Short = "remote procedure calls"
config := &Config{
holos: cfg,
client: holos.NewClientConfig(),
token: token.NewConfig(),
}
cmd.PersistentFlags().AddGoFlagSet(config.client.FlagSet())
cmd.PersistentFlags().AddGoFlagSet(config.token.FlagSet())
cmd.AddCommand(NewPlatformModel(config))
return cmd
}
func NewPlatformModel(cfg *Config) *cobra.Command {
cmd := command.New("platform-model")
cmd.Short = "get the platform model"
cmd.RunE = func(cmd *cobra.Command, args []string) error {
ctx := cmd.Root().Context()
log := logger.FromContext(ctx)
// client := platformconnect.NewPlatformServiceClient(token.NewClient(cfg.token), cfg.client.Server())
client := platformconnect.NewPlatformServiceClient(token.NewClient(cfg.token), cfg.client.Server())
// JEFFTODO - FieldMask
log.WarnContext(ctx, "JEFFTODO use the fieldmask to get only the model")
req := connect.NewRequest(&platform.GetPlatformRequest{PlatformId: BarePlatformID})
res, err := client.GetPlatform(ctx, req)
if err != nil {
return errors.Wrap(fmt.Errorf("could not get platform: %w", err))
}
if res == nil || res.Msg == nil || res.Msg.Platform == nil || res.Msg.Platform.Spec == nil {
return errors.Wrap(fmt.Errorf("response missing platform spec:\n\thave: (%+v)\n\twant: (response message platform.spec)", res))
}
encoder := json.NewEncoder(cmd.OutOrStdout())
encoder.SetIndent("", " ")
if err := encoder.Encode(res.Msg.Platform.Spec.Model); err != nil {
return errors.Wrap(fmt.Errorf("could not encode json: %w", err))
}
return err
}
return cmd
}

69
internal/client/client.go Normal file
View File

@@ -0,0 +1,69 @@
// Package client provides configuration and convenience methods for making API calls to the holos server.
package client
import (
"context"
"time"
"connectrpc.com/connect"
"github.com/holos-run/holos/internal/errors"
"github.com/holos-run/holos/internal/server/middleware/logger"
"github.com/holos-run/holos/internal/token"
object "github.com/holos-run/holos/service/gen/holos/object/v1alpha1"
"github.com/holos-run/holos/service/gen/holos/organization/v1alpha1/organizationconnect"
platform "github.com/holos-run/holos/service/gen/holos/platform/v1alpha1"
"github.com/holos-run/holos/service/gen/holos/platform/v1alpha1/platformconnect"
"github.com/holos-run/holos/service/gen/holos/user/v1alpha1/userconnect"
"google.golang.org/protobuf/types/known/fieldmaskpb"
)
func New(cfg *Config) *Client {
t := token.NewClient(cfg.Token())
s := cfg.Client().Server()
return &Client{
cfg: cfg,
usrSvc: userconnect.NewUserServiceClient(t, s),
orgSvc: organizationconnect.NewOrganizationServiceClient(t, s),
pltSvc: platformconnect.NewPlatformServiceClient(t, s),
}
}
// Client provides convenience methods for making API calls to the holos server.
type Client struct {
cfg *Config
usrSvc userconnect.UserServiceClient
pltSvc platformconnect.PlatformServiceClient
orgSvc organizationconnect.OrganizationServiceClient
}
func (c *Client) Platforms(ctx context.Context, orgID string) ([]*platform.Platform, error) {
if c == nil {
return nil, errors.New("no service client")
}
req := &platform.ListPlatformsRequest{
OrgId: orgID,
FieldMask: &fieldmaskpb.FieldMask{
Paths: []string{"id", "name", "displayName"},
},
}
resp, err := c.pltSvc.ListPlatforms(ctx, connect.NewRequest(req))
if err != nil {
return nil, err
}
return resp.Msg.GetPlatforms(), nil
}
func (c *Client) UpdateForm(ctx context.Context, platformID string, form *object.Form) error {
start := time.Now()
req := &platform.UpdatePlatformRequest{
Update: &platform.UpdatePlatformOperation{PlatformId: platformID, Form: form},
UpdateMask: &fieldmaskpb.FieldMask{Paths: []string{"form"}},
}
_, err := c.pltSvc.UpdatePlatform(ctx, connect.NewRequest(req))
if err != nil {
return errors.Wrap(err)
}
log := logger.FromContext(ctx)
log.DebugContext(ctx, "updated platform", "platform_id", platformID, "duration", time.Since(start))
return nil
}

63
internal/client/config.go Normal file
View File

@@ -0,0 +1,63 @@
// Package client provides client configuration for the holos cli.
package client
import (
"context"
"flag"
"github.com/holos-run/holos/internal/holos"
"github.com/holos-run/holos/internal/token"
)
func NewConfig(cfg *holos.Config) *Config {
return &Config{
holos: cfg,
client: holos.NewClientConfig(),
context: holos.NewClientContext(context.Background()),
token: token.NewConfig(),
}
}
type Config struct {
holos *holos.Config
client *holos.ClientConfig
context *holos.ClientContext
token *token.Config
}
func (c *Config) ClientFlagSet() *flag.FlagSet {
if c == nil {
return nil
}
return c.client.FlagSet()
}
func (c *Config) TokenFlagSet() *flag.FlagSet {
if c == nil {
return nil
}
return c.token.FlagSet()
}
func (c *Config) Token() *token.Config {
if c == nil {
return nil
}
return c.token
}
func (c *Config) Client() *holos.ClientConfig {
if c == nil {
return nil
}
return c.client
}
// Context returns the ClientContext useful to get the OrgID and UserID for rpc
// calls.
func (c *Config) Context() *holos.ClientContext {
if c == nil {
return nil
}
return c.context
}

View File

@@ -17,6 +17,7 @@ import (
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"github.com/holos-run/holos/internal/ent/organization"
"github.com/holos-run/holos/internal/ent/platform"
"github.com/holos-run/holos/internal/ent/user"
)
@@ -27,6 +28,8 @@ type Client struct {
Schema *migrate.Schema
// Organization is the client for interacting with the Organization builders.
Organization *OrganizationClient
// Platform is the client for interacting with the Platform builders.
Platform *PlatformClient
// User is the client for interacting with the User builders.
User *UserClient
}
@@ -41,6 +44,7 @@ func NewClient(opts ...Option) *Client {
func (c *Client) init() {
c.Schema = migrate.NewSchema(c.driver)
c.Organization = NewOrganizationClient(c.config)
c.Platform = NewPlatformClient(c.config)
c.User = NewUserClient(c.config)
}
@@ -135,6 +139,7 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) {
ctx: ctx,
config: cfg,
Organization: NewOrganizationClient(cfg),
Platform: NewPlatformClient(cfg),
User: NewUserClient(cfg),
}, nil
}
@@ -156,6 +161,7 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
ctx: ctx,
config: cfg,
Organization: NewOrganizationClient(cfg),
Platform: NewPlatformClient(cfg),
User: NewUserClient(cfg),
}, nil
}
@@ -186,6 +192,7 @@ func (c *Client) Close() error {
// In order to add hooks to a specific client, call: `client.Node.Use(...)`.
func (c *Client) Use(hooks ...Hook) {
c.Organization.Use(hooks...)
c.Platform.Use(hooks...)
c.User.Use(hooks...)
}
@@ -193,6 +200,7 @@ func (c *Client) Use(hooks ...Hook) {
// In order to add interceptors to a specific client, call: `client.Node.Intercept(...)`.
func (c *Client) Intercept(interceptors ...Interceptor) {
c.Organization.Intercept(interceptors...)
c.Platform.Intercept(interceptors...)
c.User.Intercept(interceptors...)
}
@@ -201,6 +209,8 @@ func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
switch m := m.(type) {
case *OrganizationMutation:
return c.Organization.mutate(ctx, m)
case *PlatformMutation:
return c.Platform.mutate(ctx, m)
case *UserMutation:
return c.User.mutate(ctx, m)
default:
@@ -332,6 +342,22 @@ func (c *OrganizationClient) QueryCreator(o *Organization) *UserQuery {
return query
}
// QueryEditor queries the editor edge of a Organization.
func (c *OrganizationClient) QueryEditor(o *Organization) *UserQuery {
query := (&UserClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := o.ID
step := sqlgraph.NewStep(
sqlgraph.From(organization.Table, organization.FieldID, id),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, organization.EditorTable, organization.EditorColumn),
)
fromV = sqlgraph.Neighbors(o.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryUsers queries the users edge of a Organization.
func (c *OrganizationClient) QueryUsers(o *Organization) *UserQuery {
query := (&UserClient{config: c.config}).Query()
@@ -348,6 +374,22 @@ func (c *OrganizationClient) QueryUsers(o *Organization) *UserQuery {
return query
}
// QueryPlatforms queries the platforms edge of a Organization.
func (c *OrganizationClient) QueryPlatforms(o *Organization) *PlatformQuery {
query := (&PlatformClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := o.ID
step := sqlgraph.NewStep(
sqlgraph.From(organization.Table, organization.FieldID, id),
sqlgraph.To(platform.Table, platform.FieldID),
sqlgraph.Edge(sqlgraph.O2M, true, organization.PlatformsTable, organization.PlatformsColumn),
)
fromV = sqlgraph.Neighbors(o.driver.Dialect(), step)
return fromV, nil
}
return query
}
// Hooks returns the client hooks.
func (c *OrganizationClient) Hooks() []Hook {
return c.hooks.Organization
@@ -373,6 +415,187 @@ func (c *OrganizationClient) mutate(ctx context.Context, m *OrganizationMutation
}
}
// PlatformClient is a client for the Platform schema.
type PlatformClient struct {
config
}
// NewPlatformClient returns a client for the Platform from the given config.
func NewPlatformClient(c config) *PlatformClient {
return &PlatformClient{config: c}
}
// Use adds a list of mutation hooks to the hooks stack.
// A call to `Use(f, g, h)` equals to `platform.Hooks(f(g(h())))`.
func (c *PlatformClient) Use(hooks ...Hook) {
c.hooks.Platform = append(c.hooks.Platform, hooks...)
}
// Intercept adds a list of query interceptors to the interceptors stack.
// A call to `Intercept(f, g, h)` equals to `platform.Intercept(f(g(h())))`.
func (c *PlatformClient) Intercept(interceptors ...Interceptor) {
c.inters.Platform = append(c.inters.Platform, interceptors...)
}
// Create returns a builder for creating a Platform entity.
func (c *PlatformClient) Create() *PlatformCreate {
mutation := newPlatformMutation(c.config, OpCreate)
return &PlatformCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// CreateBulk returns a builder for creating a bulk of Platform entities.
func (c *PlatformClient) CreateBulk(builders ...*PlatformCreate) *PlatformCreateBulk {
return &PlatformCreateBulk{config: c.config, builders: builders}
}
// MapCreateBulk creates a bulk creation builder from the given slice. For each item in the slice, the function creates
// a builder and applies setFunc on it.
func (c *PlatformClient) MapCreateBulk(slice any, setFunc func(*PlatformCreate, int)) *PlatformCreateBulk {
rv := reflect.ValueOf(slice)
if rv.Kind() != reflect.Slice {
return &PlatformCreateBulk{err: fmt.Errorf("calling to PlatformClient.MapCreateBulk with wrong type %T, need slice", slice)}
}
builders := make([]*PlatformCreate, rv.Len())
for i := 0; i < rv.Len(); i++ {
builders[i] = c.Create()
setFunc(builders[i], i)
}
return &PlatformCreateBulk{config: c.config, builders: builders}
}
// Update returns an update builder for Platform.
func (c *PlatformClient) Update() *PlatformUpdate {
mutation := newPlatformMutation(c.config, OpUpdate)
return &PlatformUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOne returns an update builder for the given entity.
func (c *PlatformClient) UpdateOne(pl *Platform) *PlatformUpdateOne {
mutation := newPlatformMutation(c.config, OpUpdateOne, withPlatform(pl))
return &PlatformUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// UpdateOneID returns an update builder for the given id.
func (c *PlatformClient) UpdateOneID(id uuid.UUID) *PlatformUpdateOne {
mutation := newPlatformMutation(c.config, OpUpdateOne, withPlatformID(id))
return &PlatformUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// Delete returns a delete builder for Platform.
func (c *PlatformClient) Delete() *PlatformDelete {
mutation := newPlatformMutation(c.config, OpDelete)
return &PlatformDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
}
// DeleteOne returns a builder for deleting the given entity.
func (c *PlatformClient) DeleteOne(pl *Platform) *PlatformDeleteOne {
return c.DeleteOneID(pl.ID)
}
// DeleteOneID returns a builder for deleting the given entity by its id.
func (c *PlatformClient) DeleteOneID(id uuid.UUID) *PlatformDeleteOne {
builder := c.Delete().Where(platform.ID(id))
builder.mutation.id = &id
builder.mutation.op = OpDeleteOne
return &PlatformDeleteOne{builder}
}
// Query returns a query builder for Platform.
func (c *PlatformClient) Query() *PlatformQuery {
return &PlatformQuery{
config: c.config,
ctx: &QueryContext{Type: TypePlatform},
inters: c.Interceptors(),
}
}
// Get returns a Platform entity by its id.
func (c *PlatformClient) Get(ctx context.Context, id uuid.UUID) (*Platform, error) {
return c.Query().Where(platform.ID(id)).Only(ctx)
}
// GetX is like Get, but panics if an error occurs.
func (c *PlatformClient) GetX(ctx context.Context, id uuid.UUID) *Platform {
obj, err := c.Get(ctx, id)
if err != nil {
panic(err)
}
return obj
}
// QueryCreator queries the creator edge of a Platform.
func (c *PlatformClient) QueryCreator(pl *Platform) *UserQuery {
query := (&UserClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := pl.ID
step := sqlgraph.NewStep(
sqlgraph.From(platform.Table, platform.FieldID, id),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, platform.CreatorTable, platform.CreatorColumn),
)
fromV = sqlgraph.Neighbors(pl.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryEditor queries the editor edge of a Platform.
func (c *PlatformClient) QueryEditor(pl *Platform) *UserQuery {
query := (&UserClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := pl.ID
step := sqlgraph.NewStep(
sqlgraph.From(platform.Table, platform.FieldID, id),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, platform.EditorTable, platform.EditorColumn),
)
fromV = sqlgraph.Neighbors(pl.driver.Dialect(), step)
return fromV, nil
}
return query
}
// QueryOrganization queries the organization edge of a Platform.
func (c *PlatformClient) QueryOrganization(pl *Platform) *OrganizationQuery {
query := (&OrganizationClient{config: c.config}).Query()
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
id := pl.ID
step := sqlgraph.NewStep(
sqlgraph.From(platform.Table, platform.FieldID, id),
sqlgraph.To(organization.Table, organization.FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, platform.OrganizationTable, platform.OrganizationColumn),
)
fromV = sqlgraph.Neighbors(pl.driver.Dialect(), step)
return fromV, nil
}
return query
}
// Hooks returns the client hooks.
func (c *PlatformClient) Hooks() []Hook {
return c.hooks.Platform
}
// Interceptors returns the client interceptors.
func (c *PlatformClient) Interceptors() []Interceptor {
return c.inters.Platform
}
func (c *PlatformClient) mutate(ctx context.Context, m *PlatformMutation) (Value, error) {
switch m.Op() {
case OpCreate:
return (&PlatformCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdate:
return (&PlatformUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpUpdateOne:
return (&PlatformUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
case OpDelete, OpDeleteOne:
return (&PlatformDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
default:
return nil, fmt.Errorf("ent: unknown Platform mutation op: %q", m.Op())
}
}
// UserClient is a client for the User schema.
type UserClient struct {
config
@@ -525,9 +748,9 @@ func (c *UserClient) mutate(ctx context.Context, m *UserMutation) (Value, error)
// hooks and interceptors per client, for fast access.
type (
hooks struct {
Organization, User []ent.Hook
Organization, Platform, User []ent.Hook
}
inters struct {
Organization, User []ent.Interceptor
Organization, Platform, User []ent.Interceptor
}
)

View File

@@ -13,6 +13,7 @@ import (
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"github.com/holos-run/holos/internal/ent/organization"
"github.com/holos-run/holos/internal/ent/platform"
"github.com/holos-run/holos/internal/ent/user"
)
@@ -75,6 +76,7 @@ func checkColumn(table, column string) error {
initCheck.Do(func() {
columnCheck = sql.NewColumnCheck(map[string]func(string) bool{
organization.Table: organization.ValidColumn,
platform.Table: platform.ValidColumn,
user.Table: user.ValidColumn,
})
})

View File

@@ -21,6 +21,18 @@ func (f OrganizationFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.OrganizationMutation", m)
}
// The PlatformFunc type is an adapter to allow the use of ordinary
// function as Platform mutator.
type PlatformFunc func(context.Context, *ent.PlatformMutation) (ent.Value, error)
// Mutate calls f(ctx, m).
func (f PlatformFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
if mv, ok := m.(*ent.PlatformMutation); ok {
return f(ctx, mv)
}
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.PlatformMutation", m)
}
// The UserFunc type is an adapter to allow the use of ordinary
// function as User mutator.
type UserFunc func(context.Context, *ent.UserMutation) (ent.Value, error)

View File

@@ -15,7 +15,8 @@ var (
{Name: "updated_at", Type: field.TypeTime},
{Name: "name", Type: field.TypeString, Unique: true},
{Name: "display_name", Type: field.TypeString},
{Name: "creator_id", Type: field.TypeUUID},
{Name: "created_by_id", Type: field.TypeUUID},
{Name: "updated_by_id", Type: field.TypeUUID},
}
// OrganizationsTable holds the schema information for the "organizations" table.
OrganizationsTable = &schema.Table{
@@ -29,6 +30,60 @@ var (
RefColumns: []*schema.Column{UsersColumns[0]},
OnDelete: schema.NoAction,
},
{
Symbol: "organizations_users_editor",
Columns: []*schema.Column{OrganizationsColumns[6]},
RefColumns: []*schema.Column{UsersColumns[0]},
OnDelete: schema.NoAction,
},
},
}
// PlatformsColumns holds the columns for the "platforms" table.
PlatformsColumns = []*schema.Column{
{Name: "id", Type: field.TypeUUID},
{Name: "created_at", Type: field.TypeTime},
{Name: "updated_at", Type: field.TypeTime},
{Name: "name", Type: field.TypeString},
{Name: "display_name", Type: field.TypeString},
{Name: "form", Type: field.TypeJSON, Nullable: true},
{Name: "model", Type: field.TypeJSON, Nullable: true},
{Name: "cue", Type: field.TypeBytes, Nullable: true},
{Name: "cue_definition", Type: field.TypeString, Nullable: true},
{Name: "created_by_id", Type: field.TypeUUID},
{Name: "updated_by_id", Type: field.TypeUUID},
{Name: "org_id", Type: field.TypeUUID},
}
// PlatformsTable holds the schema information for the "platforms" table.
PlatformsTable = &schema.Table{
Name: "platforms",
Columns: PlatformsColumns,
PrimaryKey: []*schema.Column{PlatformsColumns[0]},
ForeignKeys: []*schema.ForeignKey{
{
Symbol: "platforms_users_creator",
Columns: []*schema.Column{PlatformsColumns[9]},
RefColumns: []*schema.Column{UsersColumns[0]},
OnDelete: schema.NoAction,
},
{
Symbol: "platforms_users_editor",
Columns: []*schema.Column{PlatformsColumns[10]},
RefColumns: []*schema.Column{UsersColumns[0]},
OnDelete: schema.NoAction,
},
{
Symbol: "platforms_organizations_organization",
Columns: []*schema.Column{PlatformsColumns[11]},
RefColumns: []*schema.Column{OrganizationsColumns[0]},
OnDelete: schema.NoAction,
},
},
Indexes: []*schema.Index{
{
Name: "platform_org_id_name",
Unique: true,
Columns: []*schema.Column{PlatformsColumns[11], PlatformsColumns[3]},
},
},
}
// UsersColumns holds the columns for the "users" table.
@@ -82,6 +137,7 @@ var (
// Tables holds all the tables in the schema.
Tables = []*schema.Table{
OrganizationsTable,
PlatformsTable,
UsersTable,
OrganizationUsersTable,
}
@@ -89,6 +145,10 @@ var (
func init() {
OrganizationsTable.ForeignKeys[0].RefTable = UsersTable
OrganizationsTable.ForeignKeys[1].RefTable = UsersTable
PlatformsTable.ForeignKeys[0].RefTable = UsersTable
PlatformsTable.ForeignKeys[1].RefTable = UsersTable
PlatformsTable.ForeignKeys[2].RefTable = OrganizationsTable
OrganizationUsersTable.ForeignKeys[0].RefTable = OrganizationsTable
OrganizationUsersTable.ForeignKeys[1].RefTable = UsersTable
}

File diff suppressed because it is too large Load Diff

View File

@@ -23,12 +23,14 @@ type Organization struct {
CreatedAt time.Time `json:"created_at,omitempty"`
// UpdatedAt holds the value of the "updated_at" field.
UpdatedAt time.Time `json:"updated_at,omitempty"`
// CreatedByID holds the value of the "created_by_id" field.
CreatedByID uuid.UUID `json:"created_by_id,omitempty"`
// UpdatedByID holds the value of the "updated_by_id" field.
UpdatedByID uuid.UUID `json:"updated_by_id,omitempty"`
// Name holds the value of the "name" field.
Name string `json:"name,omitempty"`
// DisplayName holds the value of the "display_name" field.
DisplayName string `json:"display_name,omitempty"`
// CreatorID holds the value of the "creator_id" field.
CreatorID uuid.UUID `json:"creator_id,omitempty"`
// Edges holds the relations/edges for other nodes in the graph.
// The values are being populated by the OrganizationQuery when eager-loading is set.
Edges OrganizationEdges `json:"edges"`
@@ -39,11 +41,15 @@ type Organization struct {
type OrganizationEdges struct {
// Creator holds the value of the creator edge.
Creator *User `json:"creator,omitempty"`
// Editor holds the value of the editor edge.
Editor *User `json:"editor,omitempty"`
// Users holds the value of the users edge.
Users []*User `json:"users,omitempty"`
// Platforms holds the value of the platforms edge.
Platforms []*Platform `json:"platforms,omitempty"`
// loadedTypes holds the information for reporting if a
// type was loaded (or requested) in eager-loading or not.
loadedTypes [2]bool
loadedTypes [4]bool
}
// CreatorOrErr returns the Creator value or an error if the edge
@@ -57,15 +63,35 @@ func (e OrganizationEdges) CreatorOrErr() (*User, error) {
return nil, &NotLoadedError{edge: "creator"}
}
// EditorOrErr returns the Editor value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found.
func (e OrganizationEdges) EditorOrErr() (*User, error) {
if e.Editor != nil {
return e.Editor, nil
} else if e.loadedTypes[1] {
return nil, &NotFoundError{label: user.Label}
}
return nil, &NotLoadedError{edge: "editor"}
}
// UsersOrErr returns the Users value or an error if the edge
// was not loaded in eager-loading.
func (e OrganizationEdges) UsersOrErr() ([]*User, error) {
if e.loadedTypes[1] {
if e.loadedTypes[2] {
return e.Users, nil
}
return nil, &NotLoadedError{edge: "users"}
}
// PlatformsOrErr returns the Platforms value or an error if the edge
// was not loaded in eager-loading.
func (e OrganizationEdges) PlatformsOrErr() ([]*Platform, error) {
if e.loadedTypes[3] {
return e.Platforms, nil
}
return nil, &NotLoadedError{edge: "platforms"}
}
// scanValues returns the types for scanning values from sql.Rows.
func (*Organization) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
@@ -75,7 +101,7 @@ func (*Organization) scanValues(columns []string) ([]any, error) {
values[i] = new(sql.NullString)
case organization.FieldCreatedAt, organization.FieldUpdatedAt:
values[i] = new(sql.NullTime)
case organization.FieldID, organization.FieldCreatorID:
case organization.FieldID, organization.FieldCreatedByID, organization.FieldUpdatedByID:
values[i] = new(uuid.UUID)
default:
values[i] = new(sql.UnknownType)
@@ -110,6 +136,18 @@ func (o *Organization) assignValues(columns []string, values []any) error {
} else if value.Valid {
o.UpdatedAt = value.Time
}
case organization.FieldCreatedByID:
if value, ok := values[i].(*uuid.UUID); !ok {
return fmt.Errorf("unexpected type %T for field created_by_id", values[i])
} else if value != nil {
o.CreatedByID = *value
}
case organization.FieldUpdatedByID:
if value, ok := values[i].(*uuid.UUID); !ok {
return fmt.Errorf("unexpected type %T for field updated_by_id", values[i])
} else if value != nil {
o.UpdatedByID = *value
}
case organization.FieldName:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field name", values[i])
@@ -122,12 +160,6 @@ func (o *Organization) assignValues(columns []string, values []any) error {
} else if value.Valid {
o.DisplayName = value.String
}
case organization.FieldCreatorID:
if value, ok := values[i].(*uuid.UUID); !ok {
return fmt.Errorf("unexpected type %T for field creator_id", values[i])
} else if value != nil {
o.CreatorID = *value
}
default:
o.selectValues.Set(columns[i], values[i])
}
@@ -146,11 +178,21 @@ func (o *Organization) QueryCreator() *UserQuery {
return NewOrganizationClient(o.config).QueryCreator(o)
}
// QueryEditor queries the "editor" edge of the Organization entity.
func (o *Organization) QueryEditor() *UserQuery {
return NewOrganizationClient(o.config).QueryEditor(o)
}
// QueryUsers queries the "users" edge of the Organization entity.
func (o *Organization) QueryUsers() *UserQuery {
return NewOrganizationClient(o.config).QueryUsers(o)
}
// QueryPlatforms queries the "platforms" edge of the Organization entity.
func (o *Organization) QueryPlatforms() *PlatformQuery {
return NewOrganizationClient(o.config).QueryPlatforms(o)
}
// Update returns a builder for updating this Organization.
// Note that you need to call Organization.Unwrap() before calling this method if this Organization
// was returned from a transaction, and the transaction was committed or rolled back.
@@ -180,14 +222,17 @@ func (o *Organization) String() string {
builder.WriteString("updated_at=")
builder.WriteString(o.UpdatedAt.Format(time.ANSIC))
builder.WriteString(", ")
builder.WriteString("created_by_id=")
builder.WriteString(fmt.Sprintf("%v", o.CreatedByID))
builder.WriteString(", ")
builder.WriteString("updated_by_id=")
builder.WriteString(fmt.Sprintf("%v", o.UpdatedByID))
builder.WriteString(", ")
builder.WriteString("name=")
builder.WriteString(o.Name)
builder.WriteString(", ")
builder.WriteString("display_name=")
builder.WriteString(o.DisplayName)
builder.WriteString(", ")
builder.WriteString("creator_id=")
builder.WriteString(fmt.Sprintf("%v", o.CreatorID))
builder.WriteByte(')')
return builder.String()
}

View File

@@ -19,16 +19,22 @@ const (
FieldCreatedAt = "created_at"
// FieldUpdatedAt holds the string denoting the updated_at field in the database.
FieldUpdatedAt = "updated_at"
// FieldCreatedByID holds the string denoting the created_by_id field in the database.
FieldCreatedByID = "created_by_id"
// FieldUpdatedByID holds the string denoting the updated_by_id field in the database.
FieldUpdatedByID = "updated_by_id"
// FieldName holds the string denoting the name field in the database.
FieldName = "name"
// FieldDisplayName holds the string denoting the display_name field in the database.
FieldDisplayName = "display_name"
// FieldCreatorID holds the string denoting the creator_id field in the database.
FieldCreatorID = "creator_id"
// EdgeCreator holds the string denoting the creator edge name in mutations.
EdgeCreator = "creator"
// EdgeEditor holds the string denoting the editor edge name in mutations.
EdgeEditor = "editor"
// EdgeUsers holds the string denoting the users edge name in mutations.
EdgeUsers = "users"
// EdgePlatforms holds the string denoting the platforms edge name in mutations.
EdgePlatforms = "platforms"
// Table holds the table name of the organization in the database.
Table = "organizations"
// CreatorTable is the table that holds the creator relation/edge.
@@ -37,12 +43,26 @@ const (
// It exists in this package in order to avoid circular dependency with the "user" package.
CreatorInverseTable = "users"
// CreatorColumn is the table column denoting the creator relation/edge.
CreatorColumn = "creator_id"
CreatorColumn = "created_by_id"
// EditorTable is the table that holds the editor relation/edge.
EditorTable = "organizations"
// EditorInverseTable is the table name for the User entity.
// It exists in this package in order to avoid circular dependency with the "user" package.
EditorInverseTable = "users"
// EditorColumn is the table column denoting the editor relation/edge.
EditorColumn = "updated_by_id"
// UsersTable is the table that holds the users relation/edge. The primary key declared below.
UsersTable = "organization_users"
// UsersInverseTable is the table name for the User entity.
// It exists in this package in order to avoid circular dependency with the "user" package.
UsersInverseTable = "users"
// PlatformsTable is the table that holds the platforms relation/edge.
PlatformsTable = "platforms"
// PlatformsInverseTable is the table name for the Platform entity.
// It exists in this package in order to avoid circular dependency with the "platform" package.
PlatformsInverseTable = "platforms"
// PlatformsColumn is the table column denoting the platforms relation/edge.
PlatformsColumn = "org_id"
)
// Columns holds all SQL columns for organization fields.
@@ -50,9 +70,10 @@ var Columns = []string{
FieldID,
FieldCreatedAt,
FieldUpdatedAt,
FieldCreatedByID,
FieldUpdatedByID,
FieldName,
FieldDisplayName,
FieldCreatorID,
}
var (
@@ -102,6 +123,16 @@ func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc()
}
// ByCreatedByID orders the results by the created_by_id field.
func ByCreatedByID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldCreatedByID, opts...).ToFunc()
}
// ByUpdatedByID orders the results by the updated_by_id field.
func ByUpdatedByID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldUpdatedByID, opts...).ToFunc()
}
// ByName orders the results by the name field.
func ByName(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldName, opts...).ToFunc()
@@ -112,11 +143,6 @@ func ByDisplayName(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldDisplayName, opts...).ToFunc()
}
// ByCreatorID orders the results by the creator_id field.
func ByCreatorID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldCreatorID, opts...).ToFunc()
}
// ByCreatorField orders the results by creator field.
func ByCreatorField(field string, opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
@@ -124,6 +150,13 @@ func ByCreatorField(field string, opts ...sql.OrderTermOption) OrderOption {
}
}
// ByEditorField orders the results by editor field.
func ByEditorField(field string, opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newEditorStep(), sql.OrderByField(field, opts...))
}
}
// ByUsersCount orders the results by users count.
func ByUsersCount(opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
@@ -137,6 +170,20 @@ func ByUsers(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
sqlgraph.OrderByNeighborTerms(s, newUsersStep(), append([]sql.OrderTerm{term}, terms...)...)
}
}
// ByPlatformsCount orders the results by platforms count.
func ByPlatformsCount(opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborsCount(s, newPlatformsStep(), opts...)
}
}
// ByPlatforms orders the results by platforms terms.
func ByPlatforms(term sql.OrderTerm, terms ...sql.OrderTerm) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newPlatformsStep(), append([]sql.OrderTerm{term}, terms...)...)
}
}
func newCreatorStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
@@ -144,6 +191,13 @@ func newCreatorStep() *sqlgraph.Step {
sqlgraph.Edge(sqlgraph.M2O, false, CreatorTable, CreatorColumn),
)
}
func newEditorStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(EditorInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, EditorTable, EditorColumn),
)
}
func newUsersStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
@@ -151,3 +205,10 @@ func newUsersStep() *sqlgraph.Step {
sqlgraph.Edge(sqlgraph.M2M, false, UsersTable, UsersPrimaryKey...),
)
}
func newPlatformsStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(PlatformsInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.O2M, true, PlatformsTable, PlatformsColumn),
)
}

View File

@@ -66,6 +66,16 @@ func UpdatedAt(v time.Time) predicate.Organization {
return predicate.Organization(sql.FieldEQ(FieldUpdatedAt, v))
}
// CreatedByID applies equality check predicate on the "created_by_id" field. It's identical to CreatedByIDEQ.
func CreatedByID(v uuid.UUID) predicate.Organization {
return predicate.Organization(sql.FieldEQ(FieldCreatedByID, v))
}
// UpdatedByID applies equality check predicate on the "updated_by_id" field. It's identical to UpdatedByIDEQ.
func UpdatedByID(v uuid.UUID) predicate.Organization {
return predicate.Organization(sql.FieldEQ(FieldUpdatedByID, v))
}
// Name applies equality check predicate on the "name" field. It's identical to NameEQ.
func Name(v string) predicate.Organization {
return predicate.Organization(sql.FieldEQ(FieldName, v))
@@ -76,11 +86,6 @@ func DisplayName(v string) predicate.Organization {
return predicate.Organization(sql.FieldEQ(FieldDisplayName, v))
}
// CreatorID applies equality check predicate on the "creator_id" field. It's identical to CreatorIDEQ.
func CreatorID(v uuid.UUID) predicate.Organization {
return predicate.Organization(sql.FieldEQ(FieldCreatorID, v))
}
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
func CreatedAtEQ(v time.Time) predicate.Organization {
return predicate.Organization(sql.FieldEQ(FieldCreatedAt, v))
@@ -161,6 +166,46 @@ func UpdatedAtLTE(v time.Time) predicate.Organization {
return predicate.Organization(sql.FieldLTE(FieldUpdatedAt, v))
}
// CreatedByIDEQ applies the EQ predicate on the "created_by_id" field.
func CreatedByIDEQ(v uuid.UUID) predicate.Organization {
return predicate.Organization(sql.FieldEQ(FieldCreatedByID, v))
}
// CreatedByIDNEQ applies the NEQ predicate on the "created_by_id" field.
func CreatedByIDNEQ(v uuid.UUID) predicate.Organization {
return predicate.Organization(sql.FieldNEQ(FieldCreatedByID, v))
}
// CreatedByIDIn applies the In predicate on the "created_by_id" field.
func CreatedByIDIn(vs ...uuid.UUID) predicate.Organization {
return predicate.Organization(sql.FieldIn(FieldCreatedByID, vs...))
}
// CreatedByIDNotIn applies the NotIn predicate on the "created_by_id" field.
func CreatedByIDNotIn(vs ...uuid.UUID) predicate.Organization {
return predicate.Organization(sql.FieldNotIn(FieldCreatedByID, vs...))
}
// UpdatedByIDEQ applies the EQ predicate on the "updated_by_id" field.
func UpdatedByIDEQ(v uuid.UUID) predicate.Organization {
return predicate.Organization(sql.FieldEQ(FieldUpdatedByID, v))
}
// UpdatedByIDNEQ applies the NEQ predicate on the "updated_by_id" field.
func UpdatedByIDNEQ(v uuid.UUID) predicate.Organization {
return predicate.Organization(sql.FieldNEQ(FieldUpdatedByID, v))
}
// UpdatedByIDIn applies the In predicate on the "updated_by_id" field.
func UpdatedByIDIn(vs ...uuid.UUID) predicate.Organization {
return predicate.Organization(sql.FieldIn(FieldUpdatedByID, vs...))
}
// UpdatedByIDNotIn applies the NotIn predicate on the "updated_by_id" field.
func UpdatedByIDNotIn(vs ...uuid.UUID) predicate.Organization {
return predicate.Organization(sql.FieldNotIn(FieldUpdatedByID, vs...))
}
// NameEQ applies the EQ predicate on the "name" field.
func NameEQ(v string) predicate.Organization {
return predicate.Organization(sql.FieldEQ(FieldName, v))
@@ -291,26 +336,6 @@ func DisplayNameContainsFold(v string) predicate.Organization {
return predicate.Organization(sql.FieldContainsFold(FieldDisplayName, v))
}
// CreatorIDEQ applies the EQ predicate on the "creator_id" field.
func CreatorIDEQ(v uuid.UUID) predicate.Organization {
return predicate.Organization(sql.FieldEQ(FieldCreatorID, v))
}
// CreatorIDNEQ applies the NEQ predicate on the "creator_id" field.
func CreatorIDNEQ(v uuid.UUID) predicate.Organization {
return predicate.Organization(sql.FieldNEQ(FieldCreatorID, v))
}
// CreatorIDIn applies the In predicate on the "creator_id" field.
func CreatorIDIn(vs ...uuid.UUID) predicate.Organization {
return predicate.Organization(sql.FieldIn(FieldCreatorID, vs...))
}
// CreatorIDNotIn applies the NotIn predicate on the "creator_id" field.
func CreatorIDNotIn(vs ...uuid.UUID) predicate.Organization {
return predicate.Organization(sql.FieldNotIn(FieldCreatorID, vs...))
}
// HasCreator applies the HasEdge predicate on the "creator" edge.
func HasCreator() predicate.Organization {
return predicate.Organization(func(s *sql.Selector) {
@@ -334,6 +359,29 @@ func HasCreatorWith(preds ...predicate.User) predicate.Organization {
})
}
// HasEditor applies the HasEdge predicate on the "editor" edge.
func HasEditor() predicate.Organization {
return predicate.Organization(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, EditorTable, EditorColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasEditorWith applies the HasEdge predicate on the "editor" edge with a given conditions (other predicates).
func HasEditorWith(preds ...predicate.User) predicate.Organization {
return predicate.Organization(func(s *sql.Selector) {
step := newEditorStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// HasUsers applies the HasEdge predicate on the "users" edge.
func HasUsers() predicate.Organization {
return predicate.Organization(func(s *sql.Selector) {
@@ -357,6 +405,29 @@ func HasUsersWith(preds ...predicate.User) predicate.Organization {
})
}
// HasPlatforms applies the HasEdge predicate on the "platforms" edge.
func HasPlatforms() predicate.Organization {
return predicate.Organization(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.O2M, true, PlatformsTable, PlatformsColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasPlatformsWith applies the HasEdge predicate on the "platforms" edge with a given conditions (other predicates).
func HasPlatformsWith(preds ...predicate.Platform) predicate.Organization {
return predicate.Organization(func(s *sql.Selector) {
step := newPlatformsStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// And groups predicates with the AND operator between them.
func And(predicates ...predicate.Organization) predicate.Organization {
return predicate.Organization(sql.AndPredicates(predicates...))

View File

@@ -14,6 +14,7 @@ import (
"entgo.io/ent/schema/field"
"github.com/gofrs/uuid"
"github.com/holos-run/holos/internal/ent/organization"
"github.com/holos-run/holos/internal/ent/platform"
"github.com/holos-run/holos/internal/ent/user"
)
@@ -53,6 +54,18 @@ func (oc *OrganizationCreate) SetNillableUpdatedAt(t *time.Time) *OrganizationCr
return oc
}
// SetCreatedByID sets the "created_by_id" field.
func (oc *OrganizationCreate) SetCreatedByID(u uuid.UUID) *OrganizationCreate {
oc.mutation.SetCreatedByID(u)
return oc
}
// SetUpdatedByID sets the "updated_by_id" field.
func (oc *OrganizationCreate) SetUpdatedByID(u uuid.UUID) *OrganizationCreate {
oc.mutation.SetUpdatedByID(u)
return oc
}
// SetName sets the "name" field.
func (oc *OrganizationCreate) SetName(s string) *OrganizationCreate {
oc.mutation.SetName(s)
@@ -65,12 +78,6 @@ func (oc *OrganizationCreate) SetDisplayName(s string) *OrganizationCreate {
return oc
}
// SetCreatorID sets the "creator_id" field.
func (oc *OrganizationCreate) SetCreatorID(u uuid.UUID) *OrganizationCreate {
oc.mutation.SetCreatorID(u)
return oc
}
// SetID sets the "id" field.
func (oc *OrganizationCreate) SetID(u uuid.UUID) *OrganizationCreate {
oc.mutation.SetID(u)
@@ -85,11 +92,28 @@ func (oc *OrganizationCreate) SetNillableID(u *uuid.UUID) *OrganizationCreate {
return oc
}
// SetCreatorID sets the "creator" edge to the User entity by ID.
func (oc *OrganizationCreate) SetCreatorID(id uuid.UUID) *OrganizationCreate {
oc.mutation.SetCreatorID(id)
return oc
}
// SetCreator sets the "creator" edge to the User entity.
func (oc *OrganizationCreate) SetCreator(u *User) *OrganizationCreate {
return oc.SetCreatorID(u.ID)
}
// SetEditorID sets the "editor" edge to the User entity by ID.
func (oc *OrganizationCreate) SetEditorID(id uuid.UUID) *OrganizationCreate {
oc.mutation.SetEditorID(id)
return oc
}
// SetEditor sets the "editor" edge to the User entity.
func (oc *OrganizationCreate) SetEditor(u *User) *OrganizationCreate {
return oc.SetEditorID(u.ID)
}
// AddUserIDs adds the "users" edge to the User entity by IDs.
func (oc *OrganizationCreate) AddUserIDs(ids ...uuid.UUID) *OrganizationCreate {
oc.mutation.AddUserIDs(ids...)
@@ -105,6 +129,21 @@ func (oc *OrganizationCreate) AddUsers(u ...*User) *OrganizationCreate {
return oc.AddUserIDs(ids...)
}
// AddPlatformIDs adds the "platforms" edge to the Platform entity by IDs.
func (oc *OrganizationCreate) AddPlatformIDs(ids ...uuid.UUID) *OrganizationCreate {
oc.mutation.AddPlatformIDs(ids...)
return oc
}
// AddPlatforms adds the "platforms" edges to the Platform entity.
func (oc *OrganizationCreate) AddPlatforms(p ...*Platform) *OrganizationCreate {
ids := make([]uuid.UUID, len(p))
for i := range p {
ids[i] = p[i].ID
}
return oc.AddPlatformIDs(ids...)
}
// Mutation returns the OrganizationMutation object of the builder.
func (oc *OrganizationCreate) Mutation() *OrganizationMutation {
return oc.mutation
@@ -162,6 +201,12 @@ func (oc *OrganizationCreate) check() error {
if _, ok := oc.mutation.UpdatedAt(); !ok {
return &ValidationError{Name: "updated_at", err: errors.New(`ent: missing required field "Organization.updated_at"`)}
}
if _, ok := oc.mutation.CreatedByID(); !ok {
return &ValidationError{Name: "created_by_id", err: errors.New(`ent: missing required field "Organization.created_by_id"`)}
}
if _, ok := oc.mutation.UpdatedByID(); !ok {
return &ValidationError{Name: "updated_by_id", err: errors.New(`ent: missing required field "Organization.updated_by_id"`)}
}
if _, ok := oc.mutation.Name(); !ok {
return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "Organization.name"`)}
}
@@ -173,12 +218,12 @@ func (oc *OrganizationCreate) check() error {
if _, ok := oc.mutation.DisplayName(); !ok {
return &ValidationError{Name: "display_name", err: errors.New(`ent: missing required field "Organization.display_name"`)}
}
if _, ok := oc.mutation.CreatorID(); !ok {
return &ValidationError{Name: "creator_id", err: errors.New(`ent: missing required field "Organization.creator_id"`)}
}
if _, ok := oc.mutation.CreatorID(); !ok {
return &ValidationError{Name: "creator", err: errors.New(`ent: missing required edge "Organization.creator"`)}
}
if _, ok := oc.mutation.EditorID(); !ok {
return &ValidationError{Name: "editor", err: errors.New(`ent: missing required edge "Organization.editor"`)}
}
return nil
}
@@ -245,7 +290,24 @@ func (oc *OrganizationCreate) createSpec() (*Organization, *sqlgraph.CreateSpec)
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_node.CreatorID = nodes[0]
_node.CreatedByID = nodes[0]
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := oc.mutation.EditorIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: organization.EditorTable,
Columns: []string{organization.EditorColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_node.UpdatedByID = nodes[0]
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := oc.mutation.UsersIDs(); len(nodes) > 0 {
@@ -264,6 +326,22 @@ func (oc *OrganizationCreate) createSpec() (*Organization, *sqlgraph.CreateSpec)
}
_spec.Edges = append(_spec.Edges, edge)
}
if nodes := oc.mutation.PlatformsIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: organization.PlatformsTable,
Columns: []string{organization.PlatformsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(platform.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges = append(_spec.Edges, edge)
}
return _node, _spec
}
@@ -328,6 +406,18 @@ func (u *OrganizationUpsert) UpdateUpdatedAt() *OrganizationUpsert {
return u
}
// SetUpdatedByID sets the "updated_by_id" field.
func (u *OrganizationUpsert) SetUpdatedByID(v uuid.UUID) *OrganizationUpsert {
u.Set(organization.FieldUpdatedByID, v)
return u
}
// UpdateUpdatedByID sets the "updated_by_id" field to the value that was provided on create.
func (u *OrganizationUpsert) UpdateUpdatedByID() *OrganizationUpsert {
u.SetExcluded(organization.FieldUpdatedByID)
return u
}
// SetName sets the "name" field.
func (u *OrganizationUpsert) SetName(v string) *OrganizationUpsert {
u.Set(organization.FieldName, v)
@@ -352,18 +442,6 @@ func (u *OrganizationUpsert) UpdateDisplayName() *OrganizationUpsert {
return u
}
// SetCreatorID sets the "creator_id" field.
func (u *OrganizationUpsert) SetCreatorID(v uuid.UUID) *OrganizationUpsert {
u.Set(organization.FieldCreatorID, v)
return u
}
// UpdateCreatorID sets the "creator_id" field to the value that was provided on create.
func (u *OrganizationUpsert) UpdateCreatorID() *OrganizationUpsert {
u.SetExcluded(organization.FieldCreatorID)
return u
}
// UpdateNewValues updates the mutable fields using the new values that were set on create except the ID field.
// Using this option is equivalent to using:
//
@@ -384,6 +462,9 @@ func (u *OrganizationUpsertOne) UpdateNewValues() *OrganizationUpsertOne {
if _, exists := u.create.mutation.CreatedAt(); exists {
s.SetIgnore(organization.FieldCreatedAt)
}
if _, exists := u.create.mutation.CreatedByID(); exists {
s.SetIgnore(organization.FieldCreatedByID)
}
}))
return u
}
@@ -429,6 +510,20 @@ func (u *OrganizationUpsertOne) UpdateUpdatedAt() *OrganizationUpsertOne {
})
}
// SetUpdatedByID sets the "updated_by_id" field.
func (u *OrganizationUpsertOne) SetUpdatedByID(v uuid.UUID) *OrganizationUpsertOne {
return u.Update(func(s *OrganizationUpsert) {
s.SetUpdatedByID(v)
})
}
// UpdateUpdatedByID sets the "updated_by_id" field to the value that was provided on create.
func (u *OrganizationUpsertOne) UpdateUpdatedByID() *OrganizationUpsertOne {
return u.Update(func(s *OrganizationUpsert) {
s.UpdateUpdatedByID()
})
}
// SetName sets the "name" field.
func (u *OrganizationUpsertOne) SetName(v string) *OrganizationUpsertOne {
return u.Update(func(s *OrganizationUpsert) {
@@ -457,20 +552,6 @@ func (u *OrganizationUpsertOne) UpdateDisplayName() *OrganizationUpsertOne {
})
}
// SetCreatorID sets the "creator_id" field.
func (u *OrganizationUpsertOne) SetCreatorID(v uuid.UUID) *OrganizationUpsertOne {
return u.Update(func(s *OrganizationUpsert) {
s.SetCreatorID(v)
})
}
// UpdateCreatorID sets the "creator_id" field to the value that was provided on create.
func (u *OrganizationUpsertOne) UpdateCreatorID() *OrganizationUpsertOne {
return u.Update(func(s *OrganizationUpsert) {
s.UpdateCreatorID()
})
}
// Exec executes the query.
func (u *OrganizationUpsertOne) Exec(ctx context.Context) error {
if len(u.create.conflict) == 0 {
@@ -657,6 +738,9 @@ func (u *OrganizationUpsertBulk) UpdateNewValues() *OrganizationUpsertBulk {
if _, exists := b.mutation.CreatedAt(); exists {
s.SetIgnore(organization.FieldCreatedAt)
}
if _, exists := b.mutation.CreatedByID(); exists {
s.SetIgnore(organization.FieldCreatedByID)
}
}
}))
return u
@@ -703,6 +787,20 @@ func (u *OrganizationUpsertBulk) UpdateUpdatedAt() *OrganizationUpsertBulk {
})
}
// SetUpdatedByID sets the "updated_by_id" field.
func (u *OrganizationUpsertBulk) SetUpdatedByID(v uuid.UUID) *OrganizationUpsertBulk {
return u.Update(func(s *OrganizationUpsert) {
s.SetUpdatedByID(v)
})
}
// UpdateUpdatedByID sets the "updated_by_id" field to the value that was provided on create.
func (u *OrganizationUpsertBulk) UpdateUpdatedByID() *OrganizationUpsertBulk {
return u.Update(func(s *OrganizationUpsert) {
s.UpdateUpdatedByID()
})
}
// SetName sets the "name" field.
func (u *OrganizationUpsertBulk) SetName(v string) *OrganizationUpsertBulk {
return u.Update(func(s *OrganizationUpsert) {
@@ -731,20 +829,6 @@ func (u *OrganizationUpsertBulk) UpdateDisplayName() *OrganizationUpsertBulk {
})
}
// SetCreatorID sets the "creator_id" field.
func (u *OrganizationUpsertBulk) SetCreatorID(v uuid.UUID) *OrganizationUpsertBulk {
return u.Update(func(s *OrganizationUpsert) {
s.SetCreatorID(v)
})
}
// UpdateCreatorID sets the "creator_id" field to the value that was provided on create.
func (u *OrganizationUpsertBulk) UpdateCreatorID() *OrganizationUpsertBulk {
return u.Update(func(s *OrganizationUpsert) {
s.UpdateCreatorID()
})
}
// Exec executes the query.
func (u *OrganizationUpsertBulk) Exec(ctx context.Context) error {
if u.create.err != nil {

View File

@@ -13,6 +13,7 @@ import (
"entgo.io/ent/schema/field"
"github.com/gofrs/uuid"
"github.com/holos-run/holos/internal/ent/organization"
"github.com/holos-run/holos/internal/ent/platform"
"github.com/holos-run/holos/internal/ent/predicate"
"github.com/holos-run/holos/internal/ent/user"
)
@@ -20,12 +21,14 @@ import (
// OrganizationQuery is the builder for querying Organization entities.
type OrganizationQuery struct {
config
ctx *QueryContext
order []organization.OrderOption
inters []Interceptor
predicates []predicate.Organization
withCreator *UserQuery
withUsers *UserQuery
ctx *QueryContext
order []organization.OrderOption
inters []Interceptor
predicates []predicate.Organization
withCreator *UserQuery
withEditor *UserQuery
withUsers *UserQuery
withPlatforms *PlatformQuery
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
@@ -84,6 +87,28 @@ func (oq *OrganizationQuery) QueryCreator() *UserQuery {
return query
}
// QueryEditor chains the current query on the "editor" edge.
func (oq *OrganizationQuery) QueryEditor() *UserQuery {
query := (&UserClient{config: oq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := oq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := oq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(organization.Table, organization.FieldID, selector),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, organization.EditorTable, organization.EditorColumn),
)
fromU = sqlgraph.SetNeighbors(oq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// QueryUsers chains the current query on the "users" edge.
func (oq *OrganizationQuery) QueryUsers() *UserQuery {
query := (&UserClient{config: oq.config}).Query()
@@ -106,6 +131,28 @@ func (oq *OrganizationQuery) QueryUsers() *UserQuery {
return query
}
// QueryPlatforms chains the current query on the "platforms" edge.
func (oq *OrganizationQuery) QueryPlatforms() *PlatformQuery {
query := (&PlatformClient{config: oq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := oq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := oq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(organization.Table, organization.FieldID, selector),
sqlgraph.To(platform.Table, platform.FieldID),
sqlgraph.Edge(sqlgraph.O2M, true, organization.PlatformsTable, organization.PlatformsColumn),
)
fromU = sqlgraph.SetNeighbors(oq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// First returns the first Organization entity from the query.
// Returns a *NotFoundError when no Organization was found.
func (oq *OrganizationQuery) First(ctx context.Context) (*Organization, error) {
@@ -293,13 +340,15 @@ func (oq *OrganizationQuery) Clone() *OrganizationQuery {
return nil
}
return &OrganizationQuery{
config: oq.config,
ctx: oq.ctx.Clone(),
order: append([]organization.OrderOption{}, oq.order...),
inters: append([]Interceptor{}, oq.inters...),
predicates: append([]predicate.Organization{}, oq.predicates...),
withCreator: oq.withCreator.Clone(),
withUsers: oq.withUsers.Clone(),
config: oq.config,
ctx: oq.ctx.Clone(),
order: append([]organization.OrderOption{}, oq.order...),
inters: append([]Interceptor{}, oq.inters...),
predicates: append([]predicate.Organization{}, oq.predicates...),
withCreator: oq.withCreator.Clone(),
withEditor: oq.withEditor.Clone(),
withUsers: oq.withUsers.Clone(),
withPlatforms: oq.withPlatforms.Clone(),
// clone intermediate query.
sql: oq.sql.Clone(),
path: oq.path,
@@ -317,6 +366,17 @@ func (oq *OrganizationQuery) WithCreator(opts ...func(*UserQuery)) *Organization
return oq
}
// WithEditor tells the query-builder to eager-load the nodes that are connected to
// the "editor" edge. The optional arguments are used to configure the query builder of the edge.
func (oq *OrganizationQuery) WithEditor(opts ...func(*UserQuery)) *OrganizationQuery {
query := (&UserClient{config: oq.config}).Query()
for _, opt := range opts {
opt(query)
}
oq.withEditor = query
return oq
}
// WithUsers tells the query-builder to eager-load the nodes that are connected to
// the "users" edge. The optional arguments are used to configure the query builder of the edge.
func (oq *OrganizationQuery) WithUsers(opts ...func(*UserQuery)) *OrganizationQuery {
@@ -328,6 +388,17 @@ func (oq *OrganizationQuery) WithUsers(opts ...func(*UserQuery)) *OrganizationQu
return oq
}
// WithPlatforms tells the query-builder to eager-load the nodes that are connected to
// the "platforms" edge. The optional arguments are used to configure the query builder of the edge.
func (oq *OrganizationQuery) WithPlatforms(opts ...func(*PlatformQuery)) *OrganizationQuery {
query := (&PlatformClient{config: oq.config}).Query()
for _, opt := range opts {
opt(query)
}
oq.withPlatforms = query
return oq
}
// GroupBy is used to group vertices by one or more fields/columns.
// It is often used with aggregate functions, like: count, max, mean, min, sum.
//
@@ -406,9 +477,11 @@ func (oq *OrganizationQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]
var (
nodes = []*Organization{}
_spec = oq.querySpec()
loadedTypes = [2]bool{
loadedTypes = [4]bool{
oq.withCreator != nil,
oq.withEditor != nil,
oq.withUsers != nil,
oq.withPlatforms != nil,
}
)
_spec.ScanValues = func(columns []string) ([]any, error) {
@@ -435,6 +508,12 @@ func (oq *OrganizationQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]
return nil, err
}
}
if query := oq.withEditor; query != nil {
if err := oq.loadEditor(ctx, query, nodes, nil,
func(n *Organization, e *User) { n.Edges.Editor = e }); err != nil {
return nil, err
}
}
if query := oq.withUsers; query != nil {
if err := oq.loadUsers(ctx, query, nodes,
func(n *Organization) { n.Edges.Users = []*User{} },
@@ -442,6 +521,13 @@ func (oq *OrganizationQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]
return nil, err
}
}
if query := oq.withPlatforms; query != nil {
if err := oq.loadPlatforms(ctx, query, nodes,
func(n *Organization) { n.Edges.Platforms = []*Platform{} },
func(n *Organization, e *Platform) { n.Edges.Platforms = append(n.Edges.Platforms, e) }); err != nil {
return nil, err
}
}
return nodes, nil
}
@@ -449,7 +535,7 @@ func (oq *OrganizationQuery) loadCreator(ctx context.Context, query *UserQuery,
ids := make([]uuid.UUID, 0, len(nodes))
nodeids := make(map[uuid.UUID][]*Organization)
for i := range nodes {
fk := nodes[i].CreatorID
fk := nodes[i].CreatedByID
if _, ok := nodeids[fk]; !ok {
ids = append(ids, fk)
}
@@ -466,7 +552,36 @@ func (oq *OrganizationQuery) loadCreator(ctx context.Context, query *UserQuery,
for _, n := range neighbors {
nodes, ok := nodeids[n.ID]
if !ok {
return fmt.Errorf(`unexpected foreign-key "creator_id" returned %v`, n.ID)
return fmt.Errorf(`unexpected foreign-key "created_by_id" returned %v`, n.ID)
}
for i := range nodes {
assign(nodes[i], n)
}
}
return nil
}
func (oq *OrganizationQuery) loadEditor(ctx context.Context, query *UserQuery, nodes []*Organization, init func(*Organization), assign func(*Organization, *User)) error {
ids := make([]uuid.UUID, 0, len(nodes))
nodeids := make(map[uuid.UUID][]*Organization)
for i := range nodes {
fk := nodes[i].UpdatedByID
if _, ok := nodeids[fk]; !ok {
ids = append(ids, fk)
}
nodeids[fk] = append(nodeids[fk], nodes[i])
}
if len(ids) == 0 {
return nil
}
query.Where(user.IDIn(ids...))
neighbors, err := query.All(ctx)
if err != nil {
return err
}
for _, n := range neighbors {
nodes, ok := nodeids[n.ID]
if !ok {
return fmt.Errorf(`unexpected foreign-key "updated_by_id" returned %v`, n.ID)
}
for i := range nodes {
assign(nodes[i], n)
@@ -535,6 +650,36 @@ func (oq *OrganizationQuery) loadUsers(ctx context.Context, query *UserQuery, no
}
return nil
}
func (oq *OrganizationQuery) loadPlatforms(ctx context.Context, query *PlatformQuery, nodes []*Organization, init func(*Organization), assign func(*Organization, *Platform)) error {
fks := make([]driver.Value, 0, len(nodes))
nodeids := make(map[uuid.UUID]*Organization)
for i := range nodes {
fks = append(fks, nodes[i].ID)
nodeids[nodes[i].ID] = nodes[i]
if init != nil {
init(nodes[i])
}
}
if len(query.ctx.Fields) > 0 {
query.ctx.AppendFieldOnce(platform.FieldOrgID)
}
query.Where(predicate.Platform(func(s *sql.Selector) {
s.Where(sql.InValues(s.C(organization.PlatformsColumn), fks...))
}))
neighbors, err := query.All(ctx)
if err != nil {
return err
}
for _, n := range neighbors {
fk := n.OrgID
node, ok := nodeids[fk]
if !ok {
return fmt.Errorf(`unexpected referenced foreign-key "org_id" returned %v for node %v`, fk, n.ID)
}
assign(node, n)
}
return nil
}
func (oq *OrganizationQuery) sqlCount(ctx context.Context) (int, error) {
_spec := oq.querySpec()
@@ -562,7 +707,10 @@ func (oq *OrganizationQuery) querySpec() *sqlgraph.QuerySpec {
}
}
if oq.withCreator != nil {
_spec.Node.AddColumnOnce(organization.FieldCreatorID)
_spec.Node.AddColumnOnce(organization.FieldCreatedByID)
}
if oq.withEditor != nil {
_spec.Node.AddColumnOnce(organization.FieldUpdatedByID)
}
}
if ps := oq.predicates; len(ps) > 0 {

View File

@@ -13,6 +13,7 @@ import (
"entgo.io/ent/schema/field"
"github.com/gofrs/uuid"
"github.com/holos-run/holos/internal/ent/organization"
"github.com/holos-run/holos/internal/ent/platform"
"github.com/holos-run/holos/internal/ent/predicate"
"github.com/holos-run/holos/internal/ent/user"
)
@@ -36,6 +37,20 @@ func (ou *OrganizationUpdate) SetUpdatedAt(t time.Time) *OrganizationUpdate {
return ou
}
// SetUpdatedByID sets the "updated_by_id" field.
func (ou *OrganizationUpdate) SetUpdatedByID(u uuid.UUID) *OrganizationUpdate {
ou.mutation.SetUpdatedByID(u)
return ou
}
// SetNillableUpdatedByID sets the "updated_by_id" field if the given value is not nil.
func (ou *OrganizationUpdate) SetNillableUpdatedByID(u *uuid.UUID) *OrganizationUpdate {
if u != nil {
ou.SetUpdatedByID(*u)
}
return ou
}
// SetName sets the "name" field.
func (ou *OrganizationUpdate) SetName(s string) *OrganizationUpdate {
ou.mutation.SetName(s)
@@ -64,23 +79,15 @@ func (ou *OrganizationUpdate) SetNillableDisplayName(s *string) *OrganizationUpd
return ou
}
// SetCreatorID sets the "creator_id" field.
func (ou *OrganizationUpdate) SetCreatorID(u uuid.UUID) *OrganizationUpdate {
ou.mutation.SetCreatorID(u)
// SetEditorID sets the "editor" edge to the User entity by ID.
func (ou *OrganizationUpdate) SetEditorID(id uuid.UUID) *OrganizationUpdate {
ou.mutation.SetEditorID(id)
return ou
}
// SetNillableCreatorID sets the "creator_id" field if the given value is not nil.
func (ou *OrganizationUpdate) SetNillableCreatorID(u *uuid.UUID) *OrganizationUpdate {
if u != nil {
ou.SetCreatorID(*u)
}
return ou
}
// SetCreator sets the "creator" edge to the User entity.
func (ou *OrganizationUpdate) SetCreator(u *User) *OrganizationUpdate {
return ou.SetCreatorID(u.ID)
// SetEditor sets the "editor" edge to the User entity.
func (ou *OrganizationUpdate) SetEditor(u *User) *OrganizationUpdate {
return ou.SetEditorID(u.ID)
}
// AddUserIDs adds the "users" edge to the User entity by IDs.
@@ -98,14 +105,29 @@ func (ou *OrganizationUpdate) AddUsers(u ...*User) *OrganizationUpdate {
return ou.AddUserIDs(ids...)
}
// AddPlatformIDs adds the "platforms" edge to the Platform entity by IDs.
func (ou *OrganizationUpdate) AddPlatformIDs(ids ...uuid.UUID) *OrganizationUpdate {
ou.mutation.AddPlatformIDs(ids...)
return ou
}
// AddPlatforms adds the "platforms" edges to the Platform entity.
func (ou *OrganizationUpdate) AddPlatforms(p ...*Platform) *OrganizationUpdate {
ids := make([]uuid.UUID, len(p))
for i := range p {
ids[i] = p[i].ID
}
return ou.AddPlatformIDs(ids...)
}
// Mutation returns the OrganizationMutation object of the builder.
func (ou *OrganizationUpdate) Mutation() *OrganizationMutation {
return ou.mutation
}
// ClearCreator clears the "creator" edge to the User entity.
func (ou *OrganizationUpdate) ClearCreator() *OrganizationUpdate {
ou.mutation.ClearCreator()
// ClearEditor clears the "editor" edge to the User entity.
func (ou *OrganizationUpdate) ClearEditor() *OrganizationUpdate {
ou.mutation.ClearEditor()
return ou
}
@@ -130,6 +152,27 @@ func (ou *OrganizationUpdate) RemoveUsers(u ...*User) *OrganizationUpdate {
return ou.RemoveUserIDs(ids...)
}
// ClearPlatforms clears all "platforms" edges to the Platform entity.
func (ou *OrganizationUpdate) ClearPlatforms() *OrganizationUpdate {
ou.mutation.ClearPlatforms()
return ou
}
// RemovePlatformIDs removes the "platforms" edge to Platform entities by IDs.
func (ou *OrganizationUpdate) RemovePlatformIDs(ids ...uuid.UUID) *OrganizationUpdate {
ou.mutation.RemovePlatformIDs(ids...)
return ou
}
// RemovePlatforms removes "platforms" edges to Platform entities.
func (ou *OrganizationUpdate) RemovePlatforms(p ...*Platform) *OrganizationUpdate {
ids := make([]uuid.UUID, len(p))
for i := range p {
ids[i] = p[i].ID
}
return ou.RemovePlatformIDs(ids...)
}
// Save executes the query and returns the number of nodes affected by the update operation.
func (ou *OrganizationUpdate) Save(ctx context.Context) (int, error) {
ou.defaults()
@@ -176,6 +219,9 @@ func (ou *OrganizationUpdate) check() error {
if _, ok := ou.mutation.CreatorID(); ou.mutation.CreatorCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "Organization.creator"`)
}
if _, ok := ou.mutation.EditorID(); ou.mutation.EditorCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "Organization.editor"`)
}
return nil
}
@@ -200,12 +246,12 @@ func (ou *OrganizationUpdate) sqlSave(ctx context.Context) (n int, err error) {
if value, ok := ou.mutation.DisplayName(); ok {
_spec.SetField(organization.FieldDisplayName, field.TypeString, value)
}
if ou.mutation.CreatorCleared() {
if ou.mutation.EditorCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: organization.CreatorTable,
Columns: []string{organization.CreatorColumn},
Table: organization.EditorTable,
Columns: []string{organization.EditorColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeUUID),
@@ -213,12 +259,12 @@ func (ou *OrganizationUpdate) sqlSave(ctx context.Context) (n int, err error) {
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := ou.mutation.CreatorIDs(); len(nodes) > 0 {
if nodes := ou.mutation.EditorIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: organization.CreatorTable,
Columns: []string{organization.CreatorColumn},
Table: organization.EditorTable,
Columns: []string{organization.EditorColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeUUID),
@@ -274,6 +320,51 @@ func (ou *OrganizationUpdate) sqlSave(ctx context.Context) (n int, err error) {
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if ou.mutation.PlatformsCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: organization.PlatformsTable,
Columns: []string{organization.PlatformsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(platform.FieldID, field.TypeUUID),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := ou.mutation.RemovedPlatformsIDs(); len(nodes) > 0 && !ou.mutation.PlatformsCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: organization.PlatformsTable,
Columns: []string{organization.PlatformsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(platform.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := ou.mutation.PlatformsIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: organization.PlatformsTable,
Columns: []string{organization.PlatformsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(platform.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if n, err = sqlgraph.UpdateNodes(ctx, ou.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{organization.Label}
@@ -300,6 +391,20 @@ func (ouo *OrganizationUpdateOne) SetUpdatedAt(t time.Time) *OrganizationUpdateO
return ouo
}
// SetUpdatedByID sets the "updated_by_id" field.
func (ouo *OrganizationUpdateOne) SetUpdatedByID(u uuid.UUID) *OrganizationUpdateOne {
ouo.mutation.SetUpdatedByID(u)
return ouo
}
// SetNillableUpdatedByID sets the "updated_by_id" field if the given value is not nil.
func (ouo *OrganizationUpdateOne) SetNillableUpdatedByID(u *uuid.UUID) *OrganizationUpdateOne {
if u != nil {
ouo.SetUpdatedByID(*u)
}
return ouo
}
// SetName sets the "name" field.
func (ouo *OrganizationUpdateOne) SetName(s string) *OrganizationUpdateOne {
ouo.mutation.SetName(s)
@@ -328,23 +433,15 @@ func (ouo *OrganizationUpdateOne) SetNillableDisplayName(s *string) *Organizatio
return ouo
}
// SetCreatorID sets the "creator_id" field.
func (ouo *OrganizationUpdateOne) SetCreatorID(u uuid.UUID) *OrganizationUpdateOne {
ouo.mutation.SetCreatorID(u)
// SetEditorID sets the "editor" edge to the User entity by ID.
func (ouo *OrganizationUpdateOne) SetEditorID(id uuid.UUID) *OrganizationUpdateOne {
ouo.mutation.SetEditorID(id)
return ouo
}
// SetNillableCreatorID sets the "creator_id" field if the given value is not nil.
func (ouo *OrganizationUpdateOne) SetNillableCreatorID(u *uuid.UUID) *OrganizationUpdateOne {
if u != nil {
ouo.SetCreatorID(*u)
}
return ouo
}
// SetCreator sets the "creator" edge to the User entity.
func (ouo *OrganizationUpdateOne) SetCreator(u *User) *OrganizationUpdateOne {
return ouo.SetCreatorID(u.ID)
// SetEditor sets the "editor" edge to the User entity.
func (ouo *OrganizationUpdateOne) SetEditor(u *User) *OrganizationUpdateOne {
return ouo.SetEditorID(u.ID)
}
// AddUserIDs adds the "users" edge to the User entity by IDs.
@@ -362,14 +459,29 @@ func (ouo *OrganizationUpdateOne) AddUsers(u ...*User) *OrganizationUpdateOne {
return ouo.AddUserIDs(ids...)
}
// AddPlatformIDs adds the "platforms" edge to the Platform entity by IDs.
func (ouo *OrganizationUpdateOne) AddPlatformIDs(ids ...uuid.UUID) *OrganizationUpdateOne {
ouo.mutation.AddPlatformIDs(ids...)
return ouo
}
// AddPlatforms adds the "platforms" edges to the Platform entity.
func (ouo *OrganizationUpdateOne) AddPlatforms(p ...*Platform) *OrganizationUpdateOne {
ids := make([]uuid.UUID, len(p))
for i := range p {
ids[i] = p[i].ID
}
return ouo.AddPlatformIDs(ids...)
}
// Mutation returns the OrganizationMutation object of the builder.
func (ouo *OrganizationUpdateOne) Mutation() *OrganizationMutation {
return ouo.mutation
}
// ClearCreator clears the "creator" edge to the User entity.
func (ouo *OrganizationUpdateOne) ClearCreator() *OrganizationUpdateOne {
ouo.mutation.ClearCreator()
// ClearEditor clears the "editor" edge to the User entity.
func (ouo *OrganizationUpdateOne) ClearEditor() *OrganizationUpdateOne {
ouo.mutation.ClearEditor()
return ouo
}
@@ -394,6 +506,27 @@ func (ouo *OrganizationUpdateOne) RemoveUsers(u ...*User) *OrganizationUpdateOne
return ouo.RemoveUserIDs(ids...)
}
// ClearPlatforms clears all "platforms" edges to the Platform entity.
func (ouo *OrganizationUpdateOne) ClearPlatforms() *OrganizationUpdateOne {
ouo.mutation.ClearPlatforms()
return ouo
}
// RemovePlatformIDs removes the "platforms" edge to Platform entities by IDs.
func (ouo *OrganizationUpdateOne) RemovePlatformIDs(ids ...uuid.UUID) *OrganizationUpdateOne {
ouo.mutation.RemovePlatformIDs(ids...)
return ouo
}
// RemovePlatforms removes "platforms" edges to Platform entities.
func (ouo *OrganizationUpdateOne) RemovePlatforms(p ...*Platform) *OrganizationUpdateOne {
ids := make([]uuid.UUID, len(p))
for i := range p {
ids[i] = p[i].ID
}
return ouo.RemovePlatformIDs(ids...)
}
// Where appends a list predicates to the OrganizationUpdate builder.
func (ouo *OrganizationUpdateOne) Where(ps ...predicate.Organization) *OrganizationUpdateOne {
ouo.mutation.Where(ps...)
@@ -453,6 +586,9 @@ func (ouo *OrganizationUpdateOne) check() error {
if _, ok := ouo.mutation.CreatorID(); ouo.mutation.CreatorCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "Organization.creator"`)
}
if _, ok := ouo.mutation.EditorID(); ouo.mutation.EditorCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "Organization.editor"`)
}
return nil
}
@@ -494,12 +630,12 @@ func (ouo *OrganizationUpdateOne) sqlSave(ctx context.Context) (_node *Organizat
if value, ok := ouo.mutation.DisplayName(); ok {
_spec.SetField(organization.FieldDisplayName, field.TypeString, value)
}
if ouo.mutation.CreatorCleared() {
if ouo.mutation.EditorCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: organization.CreatorTable,
Columns: []string{organization.CreatorColumn},
Table: organization.EditorTable,
Columns: []string{organization.EditorColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeUUID),
@@ -507,12 +643,12 @@ func (ouo *OrganizationUpdateOne) sqlSave(ctx context.Context) (_node *Organizat
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := ouo.mutation.CreatorIDs(); len(nodes) > 0 {
if nodes := ouo.mutation.EditorIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: organization.CreatorTable,
Columns: []string{organization.CreatorColumn},
Table: organization.EditorTable,
Columns: []string{organization.EditorColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeUUID),
@@ -568,6 +704,51 @@ func (ouo *OrganizationUpdateOne) sqlSave(ctx context.Context) (_node *Organizat
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if ouo.mutation.PlatformsCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: organization.PlatformsTable,
Columns: []string{organization.PlatformsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(platform.FieldID, field.TypeUUID),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := ouo.mutation.RemovedPlatformsIDs(); len(nodes) > 0 && !ouo.mutation.PlatformsCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: organization.PlatformsTable,
Columns: []string{organization.PlatformsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(platform.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := ouo.mutation.PlatformsIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.O2M,
Inverse: true,
Table: organization.PlatformsTable,
Columns: []string{organization.PlatformsColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(platform.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
_node = &Organization{config: ouo.config}
_spec.Assign = _node.assignValues
_spec.ScanValues = _node.scanValues

291
internal/ent/platform.go Normal file
View File

@@ -0,0 +1,291 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"encoding/json"
"fmt"
"strings"
"time"
"entgo.io/ent"
"entgo.io/ent/dialect/sql"
"github.com/gofrs/uuid"
"github.com/holos-run/holos/internal/ent/organization"
"github.com/holos-run/holos/internal/ent/platform"
"github.com/holos-run/holos/internal/ent/user"
storage "github.com/holos-run/holos/service/gen/holos/storage/v1alpha1"
)
// Platform is the model entity for the Platform schema.
type Platform struct {
config `json:"-"`
// ID of the ent.
ID uuid.UUID `json:"id,omitempty"`
// CreatedAt holds the value of the "created_at" field.
CreatedAt time.Time `json:"created_at,omitempty"`
// UpdatedAt holds the value of the "updated_at" field.
UpdatedAt time.Time `json:"updated_at,omitempty"`
// CreatedByID holds the value of the "created_by_id" field.
CreatedByID uuid.UUID `json:"created_by_id,omitempty"`
// UpdatedByID holds the value of the "updated_by_id" field.
UpdatedByID uuid.UUID `json:"updated_by_id,omitempty"`
// OrgID holds the value of the "org_id" field.
OrgID uuid.UUID `json:"org_id,omitempty"`
// Name holds the value of the "name" field.
Name string `json:"name,omitempty"`
// DisplayName holds the value of the "display_name" field.
DisplayName string `json:"display_name,omitempty"`
// JSON representation of FormlyFormConfig[] refer to https://github.com/holos-run/holos/issues/161
Form *storage.Form `json:"form,omitempty"`
// JSON representation of the form model which holds user input values refer to https://github.com/holos-run/holos/issues/161
Model *storage.Model `json:"model,omitempty"`
// CUE definition to vet the model against e.g. #PlatformConfig
Cue []byte `json:"cue,omitempty"`
// The definition name to vet config_values against config_cue e.g. '#PlatformSpec'
CueDefinition string `json:"cue_definition,omitempty"`
// Edges holds the relations/edges for other nodes in the graph.
// The values are being populated by the PlatformQuery when eager-loading is set.
Edges PlatformEdges `json:"edges"`
selectValues sql.SelectValues
}
// PlatformEdges holds the relations/edges for other nodes in the graph.
type PlatformEdges struct {
// Creator holds the value of the creator edge.
Creator *User `json:"creator,omitempty"`
// Editor holds the value of the editor edge.
Editor *User `json:"editor,omitempty"`
// Organization holds the value of the organization edge.
Organization *Organization `json:"organization,omitempty"`
// loadedTypes holds the information for reporting if a
// type was loaded (or requested) in eager-loading or not.
loadedTypes [3]bool
}
// CreatorOrErr returns the Creator value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found.
func (e PlatformEdges) CreatorOrErr() (*User, error) {
if e.Creator != nil {
return e.Creator, nil
} else if e.loadedTypes[0] {
return nil, &NotFoundError{label: user.Label}
}
return nil, &NotLoadedError{edge: "creator"}
}
// EditorOrErr returns the Editor value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found.
func (e PlatformEdges) EditorOrErr() (*User, error) {
if e.Editor != nil {
return e.Editor, nil
} else if e.loadedTypes[1] {
return nil, &NotFoundError{label: user.Label}
}
return nil, &NotLoadedError{edge: "editor"}
}
// OrganizationOrErr returns the Organization value or an error if the edge
// was not loaded in eager-loading, or loaded but was not found.
func (e PlatformEdges) OrganizationOrErr() (*Organization, error) {
if e.Organization != nil {
return e.Organization, nil
} else if e.loadedTypes[2] {
return nil, &NotFoundError{label: organization.Label}
}
return nil, &NotLoadedError{edge: "organization"}
}
// scanValues returns the types for scanning values from sql.Rows.
func (*Platform) scanValues(columns []string) ([]any, error) {
values := make([]any, len(columns))
for i := range columns {
switch columns[i] {
case platform.FieldForm, platform.FieldModel, platform.FieldCue:
values[i] = new([]byte)
case platform.FieldName, platform.FieldDisplayName, platform.FieldCueDefinition:
values[i] = new(sql.NullString)
case platform.FieldCreatedAt, platform.FieldUpdatedAt:
values[i] = new(sql.NullTime)
case platform.FieldID, platform.FieldCreatedByID, platform.FieldUpdatedByID, platform.FieldOrgID:
values[i] = new(uuid.UUID)
default:
values[i] = new(sql.UnknownType)
}
}
return values, nil
}
// assignValues assigns the values that were returned from sql.Rows (after scanning)
// to the Platform fields.
func (pl *Platform) assignValues(columns []string, values []any) error {
if m, n := len(values), len(columns); m < n {
return fmt.Errorf("mismatch number of scan values: %d != %d", m, n)
}
for i := range columns {
switch columns[i] {
case platform.FieldID:
if value, ok := values[i].(*uuid.UUID); !ok {
return fmt.Errorf("unexpected type %T for field id", values[i])
} else if value != nil {
pl.ID = *value
}
case platform.FieldCreatedAt:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field created_at", values[i])
} else if value.Valid {
pl.CreatedAt = value.Time
}
case platform.FieldUpdatedAt:
if value, ok := values[i].(*sql.NullTime); !ok {
return fmt.Errorf("unexpected type %T for field updated_at", values[i])
} else if value.Valid {
pl.UpdatedAt = value.Time
}
case platform.FieldCreatedByID:
if value, ok := values[i].(*uuid.UUID); !ok {
return fmt.Errorf("unexpected type %T for field created_by_id", values[i])
} else if value != nil {
pl.CreatedByID = *value
}
case platform.FieldUpdatedByID:
if value, ok := values[i].(*uuid.UUID); !ok {
return fmt.Errorf("unexpected type %T for field updated_by_id", values[i])
} else if value != nil {
pl.UpdatedByID = *value
}
case platform.FieldOrgID:
if value, ok := values[i].(*uuid.UUID); !ok {
return fmt.Errorf("unexpected type %T for field org_id", values[i])
} else if value != nil {
pl.OrgID = *value
}
case platform.FieldName:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field name", values[i])
} else if value.Valid {
pl.Name = value.String
}
case platform.FieldDisplayName:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field display_name", values[i])
} else if value.Valid {
pl.DisplayName = value.String
}
case platform.FieldForm:
if value, ok := values[i].(*[]byte); !ok {
return fmt.Errorf("unexpected type %T for field form", values[i])
} else if value != nil && len(*value) > 0 {
if err := json.Unmarshal(*value, &pl.Form); err != nil {
return fmt.Errorf("unmarshal field form: %w", err)
}
}
case platform.FieldModel:
if value, ok := values[i].(*[]byte); !ok {
return fmt.Errorf("unexpected type %T for field model", values[i])
} else if value != nil && len(*value) > 0 {
if err := json.Unmarshal(*value, &pl.Model); err != nil {
return fmt.Errorf("unmarshal field model: %w", err)
}
}
case platform.FieldCue:
if value, ok := values[i].(*[]byte); !ok {
return fmt.Errorf("unexpected type %T for field cue", values[i])
} else if value != nil {
pl.Cue = *value
}
case platform.FieldCueDefinition:
if value, ok := values[i].(*sql.NullString); !ok {
return fmt.Errorf("unexpected type %T for field cue_definition", values[i])
} else if value.Valid {
pl.CueDefinition = value.String
}
default:
pl.selectValues.Set(columns[i], values[i])
}
}
return nil
}
// Value returns the ent.Value that was dynamically selected and assigned to the Platform.
// This includes values selected through modifiers, order, etc.
func (pl *Platform) Value(name string) (ent.Value, error) {
return pl.selectValues.Get(name)
}
// QueryCreator queries the "creator" edge of the Platform entity.
func (pl *Platform) QueryCreator() *UserQuery {
return NewPlatformClient(pl.config).QueryCreator(pl)
}
// QueryEditor queries the "editor" edge of the Platform entity.
func (pl *Platform) QueryEditor() *UserQuery {
return NewPlatformClient(pl.config).QueryEditor(pl)
}
// QueryOrganization queries the "organization" edge of the Platform entity.
func (pl *Platform) QueryOrganization() *OrganizationQuery {
return NewPlatformClient(pl.config).QueryOrganization(pl)
}
// Update returns a builder for updating this Platform.
// Note that you need to call Platform.Unwrap() before calling this method if this Platform
// was returned from a transaction, and the transaction was committed or rolled back.
func (pl *Platform) Update() *PlatformUpdateOne {
return NewPlatformClient(pl.config).UpdateOne(pl)
}
// Unwrap unwraps the Platform entity that was returned from a transaction after it was closed,
// so that all future queries will be executed through the driver which created the transaction.
func (pl *Platform) Unwrap() *Platform {
_tx, ok := pl.config.driver.(*txDriver)
if !ok {
panic("ent: Platform is not a transactional entity")
}
pl.config.driver = _tx.drv
return pl
}
// String implements the fmt.Stringer.
func (pl *Platform) String() string {
var builder strings.Builder
builder.WriteString("Platform(")
builder.WriteString(fmt.Sprintf("id=%v, ", pl.ID))
builder.WriteString("created_at=")
builder.WriteString(pl.CreatedAt.Format(time.ANSIC))
builder.WriteString(", ")
builder.WriteString("updated_at=")
builder.WriteString(pl.UpdatedAt.Format(time.ANSIC))
builder.WriteString(", ")
builder.WriteString("created_by_id=")
builder.WriteString(fmt.Sprintf("%v", pl.CreatedByID))
builder.WriteString(", ")
builder.WriteString("updated_by_id=")
builder.WriteString(fmt.Sprintf("%v", pl.UpdatedByID))
builder.WriteString(", ")
builder.WriteString("org_id=")
builder.WriteString(fmt.Sprintf("%v", pl.OrgID))
builder.WriteString(", ")
builder.WriteString("name=")
builder.WriteString(pl.Name)
builder.WriteString(", ")
builder.WriteString("display_name=")
builder.WriteString(pl.DisplayName)
builder.WriteString(", ")
builder.WriteString("form=")
builder.WriteString(fmt.Sprintf("%v", pl.Form))
builder.WriteString(", ")
builder.WriteString("model=")
builder.WriteString(fmt.Sprintf("%v", pl.Model))
builder.WriteString(", ")
builder.WriteString("cue=")
builder.WriteString(fmt.Sprintf("%v", pl.Cue))
builder.WriteString(", ")
builder.WriteString("cue_definition=")
builder.WriteString(pl.CueDefinition)
builder.WriteByte(')')
return builder.String()
}
// Platforms is a parsable slice of Platform.
type Platforms []*Platform

View File

@@ -0,0 +1,198 @@
// Code generated by ent, DO NOT EDIT.
package platform
import (
"time"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"github.com/gofrs/uuid"
)
const (
// Label holds the string label denoting the platform type in the database.
Label = "platform"
// FieldID holds the string denoting the id field in the database.
FieldID = "id"
// FieldCreatedAt holds the string denoting the created_at field in the database.
FieldCreatedAt = "created_at"
// FieldUpdatedAt holds the string denoting the updated_at field in the database.
FieldUpdatedAt = "updated_at"
// FieldCreatedByID holds the string denoting the created_by_id field in the database.
FieldCreatedByID = "created_by_id"
// FieldUpdatedByID holds the string denoting the updated_by_id field in the database.
FieldUpdatedByID = "updated_by_id"
// FieldOrgID holds the string denoting the org_id field in the database.
FieldOrgID = "org_id"
// FieldName holds the string denoting the name field in the database.
FieldName = "name"
// FieldDisplayName holds the string denoting the display_name field in the database.
FieldDisplayName = "display_name"
// FieldForm holds the string denoting the form field in the database.
FieldForm = "form"
// FieldModel holds the string denoting the model field in the database.
FieldModel = "model"
// FieldCue holds the string denoting the cue field in the database.
FieldCue = "cue"
// FieldCueDefinition holds the string denoting the cue_definition field in the database.
FieldCueDefinition = "cue_definition"
// EdgeCreator holds the string denoting the creator edge name in mutations.
EdgeCreator = "creator"
// EdgeEditor holds the string denoting the editor edge name in mutations.
EdgeEditor = "editor"
// EdgeOrganization holds the string denoting the organization edge name in mutations.
EdgeOrganization = "organization"
// Table holds the table name of the platform in the database.
Table = "platforms"
// CreatorTable is the table that holds the creator relation/edge.
CreatorTable = "platforms"
// CreatorInverseTable is the table name for the User entity.
// It exists in this package in order to avoid circular dependency with the "user" package.
CreatorInverseTable = "users"
// CreatorColumn is the table column denoting the creator relation/edge.
CreatorColumn = "created_by_id"
// EditorTable is the table that holds the editor relation/edge.
EditorTable = "platforms"
// EditorInverseTable is the table name for the User entity.
// It exists in this package in order to avoid circular dependency with the "user" package.
EditorInverseTable = "users"
// EditorColumn is the table column denoting the editor relation/edge.
EditorColumn = "updated_by_id"
// OrganizationTable is the table that holds the organization relation/edge.
OrganizationTable = "platforms"
// OrganizationInverseTable is the table name for the Organization entity.
// It exists in this package in order to avoid circular dependency with the "organization" package.
OrganizationInverseTable = "organizations"
// OrganizationColumn is the table column denoting the organization relation/edge.
OrganizationColumn = "org_id"
)
// Columns holds all SQL columns for platform fields.
var Columns = []string{
FieldID,
FieldCreatedAt,
FieldUpdatedAt,
FieldCreatedByID,
FieldUpdatedByID,
FieldOrgID,
FieldName,
FieldDisplayName,
FieldForm,
FieldModel,
FieldCue,
FieldCueDefinition,
}
// ValidColumn reports if the column name is valid (part of the table columns).
func ValidColumn(column string) bool {
for i := range Columns {
if column == Columns[i] {
return true
}
}
return false
}
var (
// DefaultCreatedAt holds the default value on creation for the "created_at" field.
DefaultCreatedAt func() time.Time
// DefaultUpdatedAt holds the default value on creation for the "updated_at" field.
DefaultUpdatedAt func() time.Time
// UpdateDefaultUpdatedAt holds the default value on update for the "updated_at" field.
UpdateDefaultUpdatedAt func() time.Time
// NameValidator is a validator for the "name" field. It is called by the builders before save.
NameValidator func(string) error
// DefaultID holds the default value on creation for the "id" field.
DefaultID func() uuid.UUID
)
// OrderOption defines the ordering options for the Platform queries.
type OrderOption func(*sql.Selector)
// ByID orders the results by the id field.
func ByID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldID, opts...).ToFunc()
}
// ByCreatedAt orders the results by the created_at field.
func ByCreatedAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldCreatedAt, opts...).ToFunc()
}
// ByUpdatedAt orders the results by the updated_at field.
func ByUpdatedAt(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldUpdatedAt, opts...).ToFunc()
}
// ByCreatedByID orders the results by the created_by_id field.
func ByCreatedByID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldCreatedByID, opts...).ToFunc()
}
// ByUpdatedByID orders the results by the updated_by_id field.
func ByUpdatedByID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldUpdatedByID, opts...).ToFunc()
}
// ByOrgID orders the results by the org_id field.
func ByOrgID(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldOrgID, opts...).ToFunc()
}
// ByName orders the results by the name field.
func ByName(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldName, opts...).ToFunc()
}
// ByDisplayName orders the results by the display_name field.
func ByDisplayName(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldDisplayName, opts...).ToFunc()
}
// ByCueDefinition orders the results by the cue_definition field.
func ByCueDefinition(opts ...sql.OrderTermOption) OrderOption {
return sql.OrderByField(FieldCueDefinition, opts...).ToFunc()
}
// ByCreatorField orders the results by creator field.
func ByCreatorField(field string, opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newCreatorStep(), sql.OrderByField(field, opts...))
}
}
// ByEditorField orders the results by editor field.
func ByEditorField(field string, opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newEditorStep(), sql.OrderByField(field, opts...))
}
}
// ByOrganizationField orders the results by organization field.
func ByOrganizationField(field string, opts ...sql.OrderTermOption) OrderOption {
return func(s *sql.Selector) {
sqlgraph.OrderByNeighborTerms(s, newOrganizationStep(), sql.OrderByField(field, opts...))
}
}
func newCreatorStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(CreatorInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, CreatorTable, CreatorColumn),
)
}
func newEditorStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(EditorInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, EditorTable, EditorColumn),
)
}
func newOrganizationStep() *sqlgraph.Step {
return sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.To(OrganizationInverseTable, FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, OrganizationTable, OrganizationColumn),
)
}

View File

@@ -0,0 +1,601 @@
// Code generated by ent, DO NOT EDIT.
package platform
import (
"time"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"github.com/gofrs/uuid"
"github.com/holos-run/holos/internal/ent/predicate"
)
// ID filters vertices based on their ID field.
func ID(id uuid.UUID) predicate.Platform {
return predicate.Platform(sql.FieldEQ(FieldID, id))
}
// IDEQ applies the EQ predicate on the ID field.
func IDEQ(id uuid.UUID) predicate.Platform {
return predicate.Platform(sql.FieldEQ(FieldID, id))
}
// IDNEQ applies the NEQ predicate on the ID field.
func IDNEQ(id uuid.UUID) predicate.Platform {
return predicate.Platform(sql.FieldNEQ(FieldID, id))
}
// IDIn applies the In predicate on the ID field.
func IDIn(ids ...uuid.UUID) predicate.Platform {
return predicate.Platform(sql.FieldIn(FieldID, ids...))
}
// IDNotIn applies the NotIn predicate on the ID field.
func IDNotIn(ids ...uuid.UUID) predicate.Platform {
return predicate.Platform(sql.FieldNotIn(FieldID, ids...))
}
// IDGT applies the GT predicate on the ID field.
func IDGT(id uuid.UUID) predicate.Platform {
return predicate.Platform(sql.FieldGT(FieldID, id))
}
// IDGTE applies the GTE predicate on the ID field.
func IDGTE(id uuid.UUID) predicate.Platform {
return predicate.Platform(sql.FieldGTE(FieldID, id))
}
// IDLT applies the LT predicate on the ID field.
func IDLT(id uuid.UUID) predicate.Platform {
return predicate.Platform(sql.FieldLT(FieldID, id))
}
// IDLTE applies the LTE predicate on the ID field.
func IDLTE(id uuid.UUID) predicate.Platform {
return predicate.Platform(sql.FieldLTE(FieldID, id))
}
// CreatedAt applies equality check predicate on the "created_at" field. It's identical to CreatedAtEQ.
func CreatedAt(v time.Time) predicate.Platform {
return predicate.Platform(sql.FieldEQ(FieldCreatedAt, v))
}
// UpdatedAt applies equality check predicate on the "updated_at" field. It's identical to UpdatedAtEQ.
func UpdatedAt(v time.Time) predicate.Platform {
return predicate.Platform(sql.FieldEQ(FieldUpdatedAt, v))
}
// CreatedByID applies equality check predicate on the "created_by_id" field. It's identical to CreatedByIDEQ.
func CreatedByID(v uuid.UUID) predicate.Platform {
return predicate.Platform(sql.FieldEQ(FieldCreatedByID, v))
}
// UpdatedByID applies equality check predicate on the "updated_by_id" field. It's identical to UpdatedByIDEQ.
func UpdatedByID(v uuid.UUID) predicate.Platform {
return predicate.Platform(sql.FieldEQ(FieldUpdatedByID, v))
}
// OrgID applies equality check predicate on the "org_id" field. It's identical to OrgIDEQ.
func OrgID(v uuid.UUID) predicate.Platform {
return predicate.Platform(sql.FieldEQ(FieldOrgID, v))
}
// Name applies equality check predicate on the "name" field. It's identical to NameEQ.
func Name(v string) predicate.Platform {
return predicate.Platform(sql.FieldEQ(FieldName, v))
}
// DisplayName applies equality check predicate on the "display_name" field. It's identical to DisplayNameEQ.
func DisplayName(v string) predicate.Platform {
return predicate.Platform(sql.FieldEQ(FieldDisplayName, v))
}
// Cue applies equality check predicate on the "cue" field. It's identical to CueEQ.
func Cue(v []byte) predicate.Platform {
return predicate.Platform(sql.FieldEQ(FieldCue, v))
}
// CueDefinition applies equality check predicate on the "cue_definition" field. It's identical to CueDefinitionEQ.
func CueDefinition(v string) predicate.Platform {
return predicate.Platform(sql.FieldEQ(FieldCueDefinition, v))
}
// CreatedAtEQ applies the EQ predicate on the "created_at" field.
func CreatedAtEQ(v time.Time) predicate.Platform {
return predicate.Platform(sql.FieldEQ(FieldCreatedAt, v))
}
// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
func CreatedAtNEQ(v time.Time) predicate.Platform {
return predicate.Platform(sql.FieldNEQ(FieldCreatedAt, v))
}
// CreatedAtIn applies the In predicate on the "created_at" field.
func CreatedAtIn(vs ...time.Time) predicate.Platform {
return predicate.Platform(sql.FieldIn(FieldCreatedAt, vs...))
}
// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
func CreatedAtNotIn(vs ...time.Time) predicate.Platform {
return predicate.Platform(sql.FieldNotIn(FieldCreatedAt, vs...))
}
// CreatedAtGT applies the GT predicate on the "created_at" field.
func CreatedAtGT(v time.Time) predicate.Platform {
return predicate.Platform(sql.FieldGT(FieldCreatedAt, v))
}
// CreatedAtGTE applies the GTE predicate on the "created_at" field.
func CreatedAtGTE(v time.Time) predicate.Platform {
return predicate.Platform(sql.FieldGTE(FieldCreatedAt, v))
}
// CreatedAtLT applies the LT predicate on the "created_at" field.
func CreatedAtLT(v time.Time) predicate.Platform {
return predicate.Platform(sql.FieldLT(FieldCreatedAt, v))
}
// CreatedAtLTE applies the LTE predicate on the "created_at" field.
func CreatedAtLTE(v time.Time) predicate.Platform {
return predicate.Platform(sql.FieldLTE(FieldCreatedAt, v))
}
// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
func UpdatedAtEQ(v time.Time) predicate.Platform {
return predicate.Platform(sql.FieldEQ(FieldUpdatedAt, v))
}
// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
func UpdatedAtNEQ(v time.Time) predicate.Platform {
return predicate.Platform(sql.FieldNEQ(FieldUpdatedAt, v))
}
// UpdatedAtIn applies the In predicate on the "updated_at" field.
func UpdatedAtIn(vs ...time.Time) predicate.Platform {
return predicate.Platform(sql.FieldIn(FieldUpdatedAt, vs...))
}
// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
func UpdatedAtNotIn(vs ...time.Time) predicate.Platform {
return predicate.Platform(sql.FieldNotIn(FieldUpdatedAt, vs...))
}
// UpdatedAtGT applies the GT predicate on the "updated_at" field.
func UpdatedAtGT(v time.Time) predicate.Platform {
return predicate.Platform(sql.FieldGT(FieldUpdatedAt, v))
}
// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
func UpdatedAtGTE(v time.Time) predicate.Platform {
return predicate.Platform(sql.FieldGTE(FieldUpdatedAt, v))
}
// UpdatedAtLT applies the LT predicate on the "updated_at" field.
func UpdatedAtLT(v time.Time) predicate.Platform {
return predicate.Platform(sql.FieldLT(FieldUpdatedAt, v))
}
// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
func UpdatedAtLTE(v time.Time) predicate.Platform {
return predicate.Platform(sql.FieldLTE(FieldUpdatedAt, v))
}
// CreatedByIDEQ applies the EQ predicate on the "created_by_id" field.
func CreatedByIDEQ(v uuid.UUID) predicate.Platform {
return predicate.Platform(sql.FieldEQ(FieldCreatedByID, v))
}
// CreatedByIDNEQ applies the NEQ predicate on the "created_by_id" field.
func CreatedByIDNEQ(v uuid.UUID) predicate.Platform {
return predicate.Platform(sql.FieldNEQ(FieldCreatedByID, v))
}
// CreatedByIDIn applies the In predicate on the "created_by_id" field.
func CreatedByIDIn(vs ...uuid.UUID) predicate.Platform {
return predicate.Platform(sql.FieldIn(FieldCreatedByID, vs...))
}
// CreatedByIDNotIn applies the NotIn predicate on the "created_by_id" field.
func CreatedByIDNotIn(vs ...uuid.UUID) predicate.Platform {
return predicate.Platform(sql.FieldNotIn(FieldCreatedByID, vs...))
}
// UpdatedByIDEQ applies the EQ predicate on the "updated_by_id" field.
func UpdatedByIDEQ(v uuid.UUID) predicate.Platform {
return predicate.Platform(sql.FieldEQ(FieldUpdatedByID, v))
}
// UpdatedByIDNEQ applies the NEQ predicate on the "updated_by_id" field.
func UpdatedByIDNEQ(v uuid.UUID) predicate.Platform {
return predicate.Platform(sql.FieldNEQ(FieldUpdatedByID, v))
}
// UpdatedByIDIn applies the In predicate on the "updated_by_id" field.
func UpdatedByIDIn(vs ...uuid.UUID) predicate.Platform {
return predicate.Platform(sql.FieldIn(FieldUpdatedByID, vs...))
}
// UpdatedByIDNotIn applies the NotIn predicate on the "updated_by_id" field.
func UpdatedByIDNotIn(vs ...uuid.UUID) predicate.Platform {
return predicate.Platform(sql.FieldNotIn(FieldUpdatedByID, vs...))
}
// OrgIDEQ applies the EQ predicate on the "org_id" field.
func OrgIDEQ(v uuid.UUID) predicate.Platform {
return predicate.Platform(sql.FieldEQ(FieldOrgID, v))
}
// OrgIDNEQ applies the NEQ predicate on the "org_id" field.
func OrgIDNEQ(v uuid.UUID) predicate.Platform {
return predicate.Platform(sql.FieldNEQ(FieldOrgID, v))
}
// OrgIDIn applies the In predicate on the "org_id" field.
func OrgIDIn(vs ...uuid.UUID) predicate.Platform {
return predicate.Platform(sql.FieldIn(FieldOrgID, vs...))
}
// OrgIDNotIn applies the NotIn predicate on the "org_id" field.
func OrgIDNotIn(vs ...uuid.UUID) predicate.Platform {
return predicate.Platform(sql.FieldNotIn(FieldOrgID, vs...))
}
// NameEQ applies the EQ predicate on the "name" field.
func NameEQ(v string) predicate.Platform {
return predicate.Platform(sql.FieldEQ(FieldName, v))
}
// NameNEQ applies the NEQ predicate on the "name" field.
func NameNEQ(v string) predicate.Platform {
return predicate.Platform(sql.FieldNEQ(FieldName, v))
}
// NameIn applies the In predicate on the "name" field.
func NameIn(vs ...string) predicate.Platform {
return predicate.Platform(sql.FieldIn(FieldName, vs...))
}
// NameNotIn applies the NotIn predicate on the "name" field.
func NameNotIn(vs ...string) predicate.Platform {
return predicate.Platform(sql.FieldNotIn(FieldName, vs...))
}
// NameGT applies the GT predicate on the "name" field.
func NameGT(v string) predicate.Platform {
return predicate.Platform(sql.FieldGT(FieldName, v))
}
// NameGTE applies the GTE predicate on the "name" field.
func NameGTE(v string) predicate.Platform {
return predicate.Platform(sql.FieldGTE(FieldName, v))
}
// NameLT applies the LT predicate on the "name" field.
func NameLT(v string) predicate.Platform {
return predicate.Platform(sql.FieldLT(FieldName, v))
}
// NameLTE applies the LTE predicate on the "name" field.
func NameLTE(v string) predicate.Platform {
return predicate.Platform(sql.FieldLTE(FieldName, v))
}
// NameContains applies the Contains predicate on the "name" field.
func NameContains(v string) predicate.Platform {
return predicate.Platform(sql.FieldContains(FieldName, v))
}
// NameHasPrefix applies the HasPrefix predicate on the "name" field.
func NameHasPrefix(v string) predicate.Platform {
return predicate.Platform(sql.FieldHasPrefix(FieldName, v))
}
// NameHasSuffix applies the HasSuffix predicate on the "name" field.
func NameHasSuffix(v string) predicate.Platform {
return predicate.Platform(sql.FieldHasSuffix(FieldName, v))
}
// NameEqualFold applies the EqualFold predicate on the "name" field.
func NameEqualFold(v string) predicate.Platform {
return predicate.Platform(sql.FieldEqualFold(FieldName, v))
}
// NameContainsFold applies the ContainsFold predicate on the "name" field.
func NameContainsFold(v string) predicate.Platform {
return predicate.Platform(sql.FieldContainsFold(FieldName, v))
}
// DisplayNameEQ applies the EQ predicate on the "display_name" field.
func DisplayNameEQ(v string) predicate.Platform {
return predicate.Platform(sql.FieldEQ(FieldDisplayName, v))
}
// DisplayNameNEQ applies the NEQ predicate on the "display_name" field.
func DisplayNameNEQ(v string) predicate.Platform {
return predicate.Platform(sql.FieldNEQ(FieldDisplayName, v))
}
// DisplayNameIn applies the In predicate on the "display_name" field.
func DisplayNameIn(vs ...string) predicate.Platform {
return predicate.Platform(sql.FieldIn(FieldDisplayName, vs...))
}
// DisplayNameNotIn applies the NotIn predicate on the "display_name" field.
func DisplayNameNotIn(vs ...string) predicate.Platform {
return predicate.Platform(sql.FieldNotIn(FieldDisplayName, vs...))
}
// DisplayNameGT applies the GT predicate on the "display_name" field.
func DisplayNameGT(v string) predicate.Platform {
return predicate.Platform(sql.FieldGT(FieldDisplayName, v))
}
// DisplayNameGTE applies the GTE predicate on the "display_name" field.
func DisplayNameGTE(v string) predicate.Platform {
return predicate.Platform(sql.FieldGTE(FieldDisplayName, v))
}
// DisplayNameLT applies the LT predicate on the "display_name" field.
func DisplayNameLT(v string) predicate.Platform {
return predicate.Platform(sql.FieldLT(FieldDisplayName, v))
}
// DisplayNameLTE applies the LTE predicate on the "display_name" field.
func DisplayNameLTE(v string) predicate.Platform {
return predicate.Platform(sql.FieldLTE(FieldDisplayName, v))
}
// DisplayNameContains applies the Contains predicate on the "display_name" field.
func DisplayNameContains(v string) predicate.Platform {
return predicate.Platform(sql.FieldContains(FieldDisplayName, v))
}
// DisplayNameHasPrefix applies the HasPrefix predicate on the "display_name" field.
func DisplayNameHasPrefix(v string) predicate.Platform {
return predicate.Platform(sql.FieldHasPrefix(FieldDisplayName, v))
}
// DisplayNameHasSuffix applies the HasSuffix predicate on the "display_name" field.
func DisplayNameHasSuffix(v string) predicate.Platform {
return predicate.Platform(sql.FieldHasSuffix(FieldDisplayName, v))
}
// DisplayNameEqualFold applies the EqualFold predicate on the "display_name" field.
func DisplayNameEqualFold(v string) predicate.Platform {
return predicate.Platform(sql.FieldEqualFold(FieldDisplayName, v))
}
// DisplayNameContainsFold applies the ContainsFold predicate on the "display_name" field.
func DisplayNameContainsFold(v string) predicate.Platform {
return predicate.Platform(sql.FieldContainsFold(FieldDisplayName, v))
}
// FormIsNil applies the IsNil predicate on the "form" field.
func FormIsNil() predicate.Platform {
return predicate.Platform(sql.FieldIsNull(FieldForm))
}
// FormNotNil applies the NotNil predicate on the "form" field.
func FormNotNil() predicate.Platform {
return predicate.Platform(sql.FieldNotNull(FieldForm))
}
// ModelIsNil applies the IsNil predicate on the "model" field.
func ModelIsNil() predicate.Platform {
return predicate.Platform(sql.FieldIsNull(FieldModel))
}
// ModelNotNil applies the NotNil predicate on the "model" field.
func ModelNotNil() predicate.Platform {
return predicate.Platform(sql.FieldNotNull(FieldModel))
}
// CueEQ applies the EQ predicate on the "cue" field.
func CueEQ(v []byte) predicate.Platform {
return predicate.Platform(sql.FieldEQ(FieldCue, v))
}
// CueNEQ applies the NEQ predicate on the "cue" field.
func CueNEQ(v []byte) predicate.Platform {
return predicate.Platform(sql.FieldNEQ(FieldCue, v))
}
// CueIn applies the In predicate on the "cue" field.
func CueIn(vs ...[]byte) predicate.Platform {
return predicate.Platform(sql.FieldIn(FieldCue, vs...))
}
// CueNotIn applies the NotIn predicate on the "cue" field.
func CueNotIn(vs ...[]byte) predicate.Platform {
return predicate.Platform(sql.FieldNotIn(FieldCue, vs...))
}
// CueGT applies the GT predicate on the "cue" field.
func CueGT(v []byte) predicate.Platform {
return predicate.Platform(sql.FieldGT(FieldCue, v))
}
// CueGTE applies the GTE predicate on the "cue" field.
func CueGTE(v []byte) predicate.Platform {
return predicate.Platform(sql.FieldGTE(FieldCue, v))
}
// CueLT applies the LT predicate on the "cue" field.
func CueLT(v []byte) predicate.Platform {
return predicate.Platform(sql.FieldLT(FieldCue, v))
}
// CueLTE applies the LTE predicate on the "cue" field.
func CueLTE(v []byte) predicate.Platform {
return predicate.Platform(sql.FieldLTE(FieldCue, v))
}
// CueIsNil applies the IsNil predicate on the "cue" field.
func CueIsNil() predicate.Platform {
return predicate.Platform(sql.FieldIsNull(FieldCue))
}
// CueNotNil applies the NotNil predicate on the "cue" field.
func CueNotNil() predicate.Platform {
return predicate.Platform(sql.FieldNotNull(FieldCue))
}
// CueDefinitionEQ applies the EQ predicate on the "cue_definition" field.
func CueDefinitionEQ(v string) predicate.Platform {
return predicate.Platform(sql.FieldEQ(FieldCueDefinition, v))
}
// CueDefinitionNEQ applies the NEQ predicate on the "cue_definition" field.
func CueDefinitionNEQ(v string) predicate.Platform {
return predicate.Platform(sql.FieldNEQ(FieldCueDefinition, v))
}
// CueDefinitionIn applies the In predicate on the "cue_definition" field.
func CueDefinitionIn(vs ...string) predicate.Platform {
return predicate.Platform(sql.FieldIn(FieldCueDefinition, vs...))
}
// CueDefinitionNotIn applies the NotIn predicate on the "cue_definition" field.
func CueDefinitionNotIn(vs ...string) predicate.Platform {
return predicate.Platform(sql.FieldNotIn(FieldCueDefinition, vs...))
}
// CueDefinitionGT applies the GT predicate on the "cue_definition" field.
func CueDefinitionGT(v string) predicate.Platform {
return predicate.Platform(sql.FieldGT(FieldCueDefinition, v))
}
// CueDefinitionGTE applies the GTE predicate on the "cue_definition" field.
func CueDefinitionGTE(v string) predicate.Platform {
return predicate.Platform(sql.FieldGTE(FieldCueDefinition, v))
}
// CueDefinitionLT applies the LT predicate on the "cue_definition" field.
func CueDefinitionLT(v string) predicate.Platform {
return predicate.Platform(sql.FieldLT(FieldCueDefinition, v))
}
// CueDefinitionLTE applies the LTE predicate on the "cue_definition" field.
func CueDefinitionLTE(v string) predicate.Platform {
return predicate.Platform(sql.FieldLTE(FieldCueDefinition, v))
}
// CueDefinitionContains applies the Contains predicate on the "cue_definition" field.
func CueDefinitionContains(v string) predicate.Platform {
return predicate.Platform(sql.FieldContains(FieldCueDefinition, v))
}
// CueDefinitionHasPrefix applies the HasPrefix predicate on the "cue_definition" field.
func CueDefinitionHasPrefix(v string) predicate.Platform {
return predicate.Platform(sql.FieldHasPrefix(FieldCueDefinition, v))
}
// CueDefinitionHasSuffix applies the HasSuffix predicate on the "cue_definition" field.
func CueDefinitionHasSuffix(v string) predicate.Platform {
return predicate.Platform(sql.FieldHasSuffix(FieldCueDefinition, v))
}
// CueDefinitionIsNil applies the IsNil predicate on the "cue_definition" field.
func CueDefinitionIsNil() predicate.Platform {
return predicate.Platform(sql.FieldIsNull(FieldCueDefinition))
}
// CueDefinitionNotNil applies the NotNil predicate on the "cue_definition" field.
func CueDefinitionNotNil() predicate.Platform {
return predicate.Platform(sql.FieldNotNull(FieldCueDefinition))
}
// CueDefinitionEqualFold applies the EqualFold predicate on the "cue_definition" field.
func CueDefinitionEqualFold(v string) predicate.Platform {
return predicate.Platform(sql.FieldEqualFold(FieldCueDefinition, v))
}
// CueDefinitionContainsFold applies the ContainsFold predicate on the "cue_definition" field.
func CueDefinitionContainsFold(v string) predicate.Platform {
return predicate.Platform(sql.FieldContainsFold(FieldCueDefinition, v))
}
// HasCreator applies the HasEdge predicate on the "creator" edge.
func HasCreator() predicate.Platform {
return predicate.Platform(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, CreatorTable, CreatorColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasCreatorWith applies the HasEdge predicate on the "creator" edge with a given conditions (other predicates).
func HasCreatorWith(preds ...predicate.User) predicate.Platform {
return predicate.Platform(func(s *sql.Selector) {
step := newCreatorStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// HasEditor applies the HasEdge predicate on the "editor" edge.
func HasEditor() predicate.Platform {
return predicate.Platform(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, EditorTable, EditorColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasEditorWith applies the HasEdge predicate on the "editor" edge with a given conditions (other predicates).
func HasEditorWith(preds ...predicate.User) predicate.Platform {
return predicate.Platform(func(s *sql.Selector) {
step := newEditorStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// HasOrganization applies the HasEdge predicate on the "organization" edge.
func HasOrganization() predicate.Platform {
return predicate.Platform(func(s *sql.Selector) {
step := sqlgraph.NewStep(
sqlgraph.From(Table, FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, OrganizationTable, OrganizationColumn),
)
sqlgraph.HasNeighbors(s, step)
})
}
// HasOrganizationWith applies the HasEdge predicate on the "organization" edge with a given conditions (other predicates).
func HasOrganizationWith(preds ...predicate.Organization) predicate.Platform {
return predicate.Platform(func(s *sql.Selector) {
step := newOrganizationStep()
sqlgraph.HasNeighborsWith(s, step, func(s *sql.Selector) {
for _, p := range preds {
p(s)
}
})
})
}
// And groups predicates with the AND operator between them.
func And(predicates ...predicate.Platform) predicate.Platform {
return predicate.Platform(sql.AndPredicates(predicates...))
}
// Or groups predicates with the OR operator between them.
func Or(predicates ...predicate.Platform) predicate.Platform {
return predicate.Platform(sql.OrPredicates(predicates...))
}
// Not applies the not operator on the given predicate.
func Not(p predicate.Platform) predicate.Platform {
return predicate.Platform(sql.NotPredicates(p))
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,88 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/holos-run/holos/internal/ent/platform"
"github.com/holos-run/holos/internal/ent/predicate"
)
// PlatformDelete is the builder for deleting a Platform entity.
type PlatformDelete struct {
config
hooks []Hook
mutation *PlatformMutation
}
// Where appends a list predicates to the PlatformDelete builder.
func (pd *PlatformDelete) Where(ps ...predicate.Platform) *PlatformDelete {
pd.mutation.Where(ps...)
return pd
}
// Exec executes the deletion query and returns how many vertices were deleted.
func (pd *PlatformDelete) Exec(ctx context.Context) (int, error) {
return withHooks(ctx, pd.sqlExec, pd.mutation, pd.hooks)
}
// ExecX is like Exec, but panics if an error occurs.
func (pd *PlatformDelete) ExecX(ctx context.Context) int {
n, err := pd.Exec(ctx)
if err != nil {
panic(err)
}
return n
}
func (pd *PlatformDelete) sqlExec(ctx context.Context) (int, error) {
_spec := sqlgraph.NewDeleteSpec(platform.Table, sqlgraph.NewFieldSpec(platform.FieldID, field.TypeUUID))
if ps := pd.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
affected, err := sqlgraph.DeleteNodes(ctx, pd.driver, _spec)
if err != nil && sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
pd.mutation.done = true
return affected, err
}
// PlatformDeleteOne is the builder for deleting a single Platform entity.
type PlatformDeleteOne struct {
pd *PlatformDelete
}
// Where appends a list predicates to the PlatformDelete builder.
func (pdo *PlatformDeleteOne) Where(ps ...predicate.Platform) *PlatformDeleteOne {
pdo.pd.mutation.Where(ps...)
return pdo
}
// Exec executes the deletion query.
func (pdo *PlatformDeleteOne) Exec(ctx context.Context) error {
n, err := pdo.pd.Exec(ctx)
switch {
case err != nil:
return err
case n == 0:
return &NotFoundError{platform.Label}
default:
return nil
}
}
// ExecX is like Exec, but panics if an error occurs.
func (pdo *PlatformDeleteOne) ExecX(ctx context.Context) {
if err := pdo.Exec(ctx); err != nil {
panic(err)
}
}

View File

@@ -0,0 +1,755 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"fmt"
"math"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/gofrs/uuid"
"github.com/holos-run/holos/internal/ent/organization"
"github.com/holos-run/holos/internal/ent/platform"
"github.com/holos-run/holos/internal/ent/predicate"
"github.com/holos-run/holos/internal/ent/user"
)
// PlatformQuery is the builder for querying Platform entities.
type PlatformQuery struct {
config
ctx *QueryContext
order []platform.OrderOption
inters []Interceptor
predicates []predicate.Platform
withCreator *UserQuery
withEditor *UserQuery
withOrganization *OrganizationQuery
// intermediate query (i.e. traversal path).
sql *sql.Selector
path func(context.Context) (*sql.Selector, error)
}
// Where adds a new predicate for the PlatformQuery builder.
func (pq *PlatformQuery) Where(ps ...predicate.Platform) *PlatformQuery {
pq.predicates = append(pq.predicates, ps...)
return pq
}
// Limit the number of records to be returned by this query.
func (pq *PlatformQuery) Limit(limit int) *PlatformQuery {
pq.ctx.Limit = &limit
return pq
}
// Offset to start from.
func (pq *PlatformQuery) Offset(offset int) *PlatformQuery {
pq.ctx.Offset = &offset
return pq
}
// Unique configures the query builder to filter duplicate records on query.
// By default, unique is set to true, and can be disabled using this method.
func (pq *PlatformQuery) Unique(unique bool) *PlatformQuery {
pq.ctx.Unique = &unique
return pq
}
// Order specifies how the records should be ordered.
func (pq *PlatformQuery) Order(o ...platform.OrderOption) *PlatformQuery {
pq.order = append(pq.order, o...)
return pq
}
// QueryCreator chains the current query on the "creator" edge.
func (pq *PlatformQuery) QueryCreator() *UserQuery {
query := (&UserClient{config: pq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := pq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := pq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(platform.Table, platform.FieldID, selector),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, platform.CreatorTable, platform.CreatorColumn),
)
fromU = sqlgraph.SetNeighbors(pq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// QueryEditor chains the current query on the "editor" edge.
func (pq *PlatformQuery) QueryEditor() *UserQuery {
query := (&UserClient{config: pq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := pq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := pq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(platform.Table, platform.FieldID, selector),
sqlgraph.To(user.Table, user.FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, platform.EditorTable, platform.EditorColumn),
)
fromU = sqlgraph.SetNeighbors(pq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// QueryOrganization chains the current query on the "organization" edge.
func (pq *PlatformQuery) QueryOrganization() *OrganizationQuery {
query := (&OrganizationClient{config: pq.config}).Query()
query.path = func(ctx context.Context) (fromU *sql.Selector, err error) {
if err := pq.prepareQuery(ctx); err != nil {
return nil, err
}
selector := pq.sqlQuery(ctx)
if err := selector.Err(); err != nil {
return nil, err
}
step := sqlgraph.NewStep(
sqlgraph.From(platform.Table, platform.FieldID, selector),
sqlgraph.To(organization.Table, organization.FieldID),
sqlgraph.Edge(sqlgraph.M2O, false, platform.OrganizationTable, platform.OrganizationColumn),
)
fromU = sqlgraph.SetNeighbors(pq.driver.Dialect(), step)
return fromU, nil
}
return query
}
// First returns the first Platform entity from the query.
// Returns a *NotFoundError when no Platform was found.
func (pq *PlatformQuery) First(ctx context.Context) (*Platform, error) {
nodes, err := pq.Limit(1).All(setContextOp(ctx, pq.ctx, "First"))
if err != nil {
return nil, err
}
if len(nodes) == 0 {
return nil, &NotFoundError{platform.Label}
}
return nodes[0], nil
}
// FirstX is like First, but panics if an error occurs.
func (pq *PlatformQuery) FirstX(ctx context.Context) *Platform {
node, err := pq.First(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return node
}
// FirstID returns the first Platform ID from the query.
// Returns a *NotFoundError when no Platform ID was found.
func (pq *PlatformQuery) FirstID(ctx context.Context) (id uuid.UUID, err error) {
var ids []uuid.UUID
if ids, err = pq.Limit(1).IDs(setContextOp(ctx, pq.ctx, "FirstID")); err != nil {
return
}
if len(ids) == 0 {
err = &NotFoundError{platform.Label}
return
}
return ids[0], nil
}
// FirstIDX is like FirstID, but panics if an error occurs.
func (pq *PlatformQuery) FirstIDX(ctx context.Context) uuid.UUID {
id, err := pq.FirstID(ctx)
if err != nil && !IsNotFound(err) {
panic(err)
}
return id
}
// Only returns a single Platform entity found by the query, ensuring it only returns one.
// Returns a *NotSingularError when more than one Platform entity is found.
// Returns a *NotFoundError when no Platform entities are found.
func (pq *PlatformQuery) Only(ctx context.Context) (*Platform, error) {
nodes, err := pq.Limit(2).All(setContextOp(ctx, pq.ctx, "Only"))
if err != nil {
return nil, err
}
switch len(nodes) {
case 1:
return nodes[0], nil
case 0:
return nil, &NotFoundError{platform.Label}
default:
return nil, &NotSingularError{platform.Label}
}
}
// OnlyX is like Only, but panics if an error occurs.
func (pq *PlatformQuery) OnlyX(ctx context.Context) *Platform {
node, err := pq.Only(ctx)
if err != nil {
panic(err)
}
return node
}
// OnlyID is like Only, but returns the only Platform ID in the query.
// Returns a *NotSingularError when more than one Platform ID is found.
// Returns a *NotFoundError when no entities are found.
func (pq *PlatformQuery) OnlyID(ctx context.Context) (id uuid.UUID, err error) {
var ids []uuid.UUID
if ids, err = pq.Limit(2).IDs(setContextOp(ctx, pq.ctx, "OnlyID")); err != nil {
return
}
switch len(ids) {
case 1:
id = ids[0]
case 0:
err = &NotFoundError{platform.Label}
default:
err = &NotSingularError{platform.Label}
}
return
}
// OnlyIDX is like OnlyID, but panics if an error occurs.
func (pq *PlatformQuery) OnlyIDX(ctx context.Context) uuid.UUID {
id, err := pq.OnlyID(ctx)
if err != nil {
panic(err)
}
return id
}
// All executes the query and returns a list of Platforms.
func (pq *PlatformQuery) All(ctx context.Context) ([]*Platform, error) {
ctx = setContextOp(ctx, pq.ctx, "All")
if err := pq.prepareQuery(ctx); err != nil {
return nil, err
}
qr := querierAll[[]*Platform, *PlatformQuery]()
return withInterceptors[[]*Platform](ctx, pq, qr, pq.inters)
}
// AllX is like All, but panics if an error occurs.
func (pq *PlatformQuery) AllX(ctx context.Context) []*Platform {
nodes, err := pq.All(ctx)
if err != nil {
panic(err)
}
return nodes
}
// IDs executes the query and returns a list of Platform IDs.
func (pq *PlatformQuery) IDs(ctx context.Context) (ids []uuid.UUID, err error) {
if pq.ctx.Unique == nil && pq.path != nil {
pq.Unique(true)
}
ctx = setContextOp(ctx, pq.ctx, "IDs")
if err = pq.Select(platform.FieldID).Scan(ctx, &ids); err != nil {
return nil, err
}
return ids, nil
}
// IDsX is like IDs, but panics if an error occurs.
func (pq *PlatformQuery) IDsX(ctx context.Context) []uuid.UUID {
ids, err := pq.IDs(ctx)
if err != nil {
panic(err)
}
return ids
}
// Count returns the count of the given query.
func (pq *PlatformQuery) Count(ctx context.Context) (int, error) {
ctx = setContextOp(ctx, pq.ctx, "Count")
if err := pq.prepareQuery(ctx); err != nil {
return 0, err
}
return withInterceptors[int](ctx, pq, querierCount[*PlatformQuery](), pq.inters)
}
// CountX is like Count, but panics if an error occurs.
func (pq *PlatformQuery) CountX(ctx context.Context) int {
count, err := pq.Count(ctx)
if err != nil {
panic(err)
}
return count
}
// Exist returns true if the query has elements in the graph.
func (pq *PlatformQuery) Exist(ctx context.Context) (bool, error) {
ctx = setContextOp(ctx, pq.ctx, "Exist")
switch _, err := pq.FirstID(ctx); {
case IsNotFound(err):
return false, nil
case err != nil:
return false, fmt.Errorf("ent: check existence: %w", err)
default:
return true, nil
}
}
// ExistX is like Exist, but panics if an error occurs.
func (pq *PlatformQuery) ExistX(ctx context.Context) bool {
exist, err := pq.Exist(ctx)
if err != nil {
panic(err)
}
return exist
}
// Clone returns a duplicate of the PlatformQuery builder, including all associated steps. It can be
// used to prepare common query builders and use them differently after the clone is made.
func (pq *PlatformQuery) Clone() *PlatformQuery {
if pq == nil {
return nil
}
return &PlatformQuery{
config: pq.config,
ctx: pq.ctx.Clone(),
order: append([]platform.OrderOption{}, pq.order...),
inters: append([]Interceptor{}, pq.inters...),
predicates: append([]predicate.Platform{}, pq.predicates...),
withCreator: pq.withCreator.Clone(),
withEditor: pq.withEditor.Clone(),
withOrganization: pq.withOrganization.Clone(),
// clone intermediate query.
sql: pq.sql.Clone(),
path: pq.path,
}
}
// WithCreator tells the query-builder to eager-load the nodes that are connected to
// the "creator" edge. The optional arguments are used to configure the query builder of the edge.
func (pq *PlatformQuery) WithCreator(opts ...func(*UserQuery)) *PlatformQuery {
query := (&UserClient{config: pq.config}).Query()
for _, opt := range opts {
opt(query)
}
pq.withCreator = query
return pq
}
// WithEditor tells the query-builder to eager-load the nodes that are connected to
// the "editor" edge. The optional arguments are used to configure the query builder of the edge.
func (pq *PlatformQuery) WithEditor(opts ...func(*UserQuery)) *PlatformQuery {
query := (&UserClient{config: pq.config}).Query()
for _, opt := range opts {
opt(query)
}
pq.withEditor = query
return pq
}
// WithOrganization tells the query-builder to eager-load the nodes that are connected to
// the "organization" edge. The optional arguments are used to configure the query builder of the edge.
func (pq *PlatformQuery) WithOrganization(opts ...func(*OrganizationQuery)) *PlatformQuery {
query := (&OrganizationClient{config: pq.config}).Query()
for _, opt := range opts {
opt(query)
}
pq.withOrganization = query
return pq
}
// GroupBy is used to group vertices by one or more fields/columns.
// It is often used with aggregate functions, like: count, max, mean, min, sum.
//
// Example:
//
// var v []struct {
// CreatedAt time.Time `json:"created_at,omitempty"`
// Count int `json:"count,omitempty"`
// }
//
// client.Platform.Query().
// GroupBy(platform.FieldCreatedAt).
// Aggregate(ent.Count()).
// Scan(ctx, &v)
func (pq *PlatformQuery) GroupBy(field string, fields ...string) *PlatformGroupBy {
pq.ctx.Fields = append([]string{field}, fields...)
grbuild := &PlatformGroupBy{build: pq}
grbuild.flds = &pq.ctx.Fields
grbuild.label = platform.Label
grbuild.scan = grbuild.Scan
return grbuild
}
// Select allows the selection one or more fields/columns for the given query,
// instead of selecting all fields in the entity.
//
// Example:
//
// var v []struct {
// CreatedAt time.Time `json:"created_at,omitempty"`
// }
//
// client.Platform.Query().
// Select(platform.FieldCreatedAt).
// Scan(ctx, &v)
func (pq *PlatformQuery) Select(fields ...string) *PlatformSelect {
pq.ctx.Fields = append(pq.ctx.Fields, fields...)
sbuild := &PlatformSelect{PlatformQuery: pq}
sbuild.label = platform.Label
sbuild.flds, sbuild.scan = &pq.ctx.Fields, sbuild.Scan
return sbuild
}
// Aggregate returns a PlatformSelect configured with the given aggregations.
func (pq *PlatformQuery) Aggregate(fns ...AggregateFunc) *PlatformSelect {
return pq.Select().Aggregate(fns...)
}
func (pq *PlatformQuery) prepareQuery(ctx context.Context) error {
for _, inter := range pq.inters {
if inter == nil {
return fmt.Errorf("ent: uninitialized interceptor (forgotten import ent/runtime?)")
}
if trv, ok := inter.(Traverser); ok {
if err := trv.Traverse(ctx, pq); err != nil {
return err
}
}
}
for _, f := range pq.ctx.Fields {
if !platform.ValidColumn(f) {
return &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
}
}
if pq.path != nil {
prev, err := pq.path(ctx)
if err != nil {
return err
}
pq.sql = prev
}
return nil
}
func (pq *PlatformQuery) sqlAll(ctx context.Context, hooks ...queryHook) ([]*Platform, error) {
var (
nodes = []*Platform{}
_spec = pq.querySpec()
loadedTypes = [3]bool{
pq.withCreator != nil,
pq.withEditor != nil,
pq.withOrganization != nil,
}
)
_spec.ScanValues = func(columns []string) ([]any, error) {
return (*Platform).scanValues(nil, columns)
}
_spec.Assign = func(columns []string, values []any) error {
node := &Platform{config: pq.config}
nodes = append(nodes, node)
node.Edges.loadedTypes = loadedTypes
return node.assignValues(columns, values)
}
for i := range hooks {
hooks[i](ctx, _spec)
}
if err := sqlgraph.QueryNodes(ctx, pq.driver, _spec); err != nil {
return nil, err
}
if len(nodes) == 0 {
return nodes, nil
}
if query := pq.withCreator; query != nil {
if err := pq.loadCreator(ctx, query, nodes, nil,
func(n *Platform, e *User) { n.Edges.Creator = e }); err != nil {
return nil, err
}
}
if query := pq.withEditor; query != nil {
if err := pq.loadEditor(ctx, query, nodes, nil,
func(n *Platform, e *User) { n.Edges.Editor = e }); err != nil {
return nil, err
}
}
if query := pq.withOrganization; query != nil {
if err := pq.loadOrganization(ctx, query, nodes, nil,
func(n *Platform, e *Organization) { n.Edges.Organization = e }); err != nil {
return nil, err
}
}
return nodes, nil
}
func (pq *PlatformQuery) loadCreator(ctx context.Context, query *UserQuery, nodes []*Platform, init func(*Platform), assign func(*Platform, *User)) error {
ids := make([]uuid.UUID, 0, len(nodes))
nodeids := make(map[uuid.UUID][]*Platform)
for i := range nodes {
fk := nodes[i].CreatedByID
if _, ok := nodeids[fk]; !ok {
ids = append(ids, fk)
}
nodeids[fk] = append(nodeids[fk], nodes[i])
}
if len(ids) == 0 {
return nil
}
query.Where(user.IDIn(ids...))
neighbors, err := query.All(ctx)
if err != nil {
return err
}
for _, n := range neighbors {
nodes, ok := nodeids[n.ID]
if !ok {
return fmt.Errorf(`unexpected foreign-key "created_by_id" returned %v`, n.ID)
}
for i := range nodes {
assign(nodes[i], n)
}
}
return nil
}
func (pq *PlatformQuery) loadEditor(ctx context.Context, query *UserQuery, nodes []*Platform, init func(*Platform), assign func(*Platform, *User)) error {
ids := make([]uuid.UUID, 0, len(nodes))
nodeids := make(map[uuid.UUID][]*Platform)
for i := range nodes {
fk := nodes[i].UpdatedByID
if _, ok := nodeids[fk]; !ok {
ids = append(ids, fk)
}
nodeids[fk] = append(nodeids[fk], nodes[i])
}
if len(ids) == 0 {
return nil
}
query.Where(user.IDIn(ids...))
neighbors, err := query.All(ctx)
if err != nil {
return err
}
for _, n := range neighbors {
nodes, ok := nodeids[n.ID]
if !ok {
return fmt.Errorf(`unexpected foreign-key "updated_by_id" returned %v`, n.ID)
}
for i := range nodes {
assign(nodes[i], n)
}
}
return nil
}
func (pq *PlatformQuery) loadOrganization(ctx context.Context, query *OrganizationQuery, nodes []*Platform, init func(*Platform), assign func(*Platform, *Organization)) error {
ids := make([]uuid.UUID, 0, len(nodes))
nodeids := make(map[uuid.UUID][]*Platform)
for i := range nodes {
fk := nodes[i].OrgID
if _, ok := nodeids[fk]; !ok {
ids = append(ids, fk)
}
nodeids[fk] = append(nodeids[fk], nodes[i])
}
if len(ids) == 0 {
return nil
}
query.Where(organization.IDIn(ids...))
neighbors, err := query.All(ctx)
if err != nil {
return err
}
for _, n := range neighbors {
nodes, ok := nodeids[n.ID]
if !ok {
return fmt.Errorf(`unexpected foreign-key "org_id" returned %v`, n.ID)
}
for i := range nodes {
assign(nodes[i], n)
}
}
return nil
}
func (pq *PlatformQuery) sqlCount(ctx context.Context) (int, error) {
_spec := pq.querySpec()
_spec.Node.Columns = pq.ctx.Fields
if len(pq.ctx.Fields) > 0 {
_spec.Unique = pq.ctx.Unique != nil && *pq.ctx.Unique
}
return sqlgraph.CountNodes(ctx, pq.driver, _spec)
}
func (pq *PlatformQuery) querySpec() *sqlgraph.QuerySpec {
_spec := sqlgraph.NewQuerySpec(platform.Table, platform.Columns, sqlgraph.NewFieldSpec(platform.FieldID, field.TypeUUID))
_spec.From = pq.sql
if unique := pq.ctx.Unique; unique != nil {
_spec.Unique = *unique
} else if pq.path != nil {
_spec.Unique = true
}
if fields := pq.ctx.Fields; len(fields) > 0 {
_spec.Node.Columns = make([]string, 0, len(fields))
_spec.Node.Columns = append(_spec.Node.Columns, platform.FieldID)
for i := range fields {
if fields[i] != platform.FieldID {
_spec.Node.Columns = append(_spec.Node.Columns, fields[i])
}
}
if pq.withCreator != nil {
_spec.Node.AddColumnOnce(platform.FieldCreatedByID)
}
if pq.withEditor != nil {
_spec.Node.AddColumnOnce(platform.FieldUpdatedByID)
}
if pq.withOrganization != nil {
_spec.Node.AddColumnOnce(platform.FieldOrgID)
}
}
if ps := pq.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if limit := pq.ctx.Limit; limit != nil {
_spec.Limit = *limit
}
if offset := pq.ctx.Offset; offset != nil {
_spec.Offset = *offset
}
if ps := pq.order; len(ps) > 0 {
_spec.Order = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
return _spec
}
func (pq *PlatformQuery) sqlQuery(ctx context.Context) *sql.Selector {
builder := sql.Dialect(pq.driver.Dialect())
t1 := builder.Table(platform.Table)
columns := pq.ctx.Fields
if len(columns) == 0 {
columns = platform.Columns
}
selector := builder.Select(t1.Columns(columns...)...).From(t1)
if pq.sql != nil {
selector = pq.sql
selector.Select(selector.Columns(columns...)...)
}
if pq.ctx.Unique != nil && *pq.ctx.Unique {
selector.Distinct()
}
for _, p := range pq.predicates {
p(selector)
}
for _, p := range pq.order {
p(selector)
}
if offset := pq.ctx.Offset; offset != nil {
// limit is mandatory for offset clause. We start
// with default value, and override it below if needed.
selector.Offset(*offset).Limit(math.MaxInt32)
}
if limit := pq.ctx.Limit; limit != nil {
selector.Limit(*limit)
}
return selector
}
// PlatformGroupBy is the group-by builder for Platform entities.
type PlatformGroupBy struct {
selector
build *PlatformQuery
}
// Aggregate adds the given aggregation functions to the group-by query.
func (pgb *PlatformGroupBy) Aggregate(fns ...AggregateFunc) *PlatformGroupBy {
pgb.fns = append(pgb.fns, fns...)
return pgb
}
// Scan applies the selector query and scans the result into the given value.
func (pgb *PlatformGroupBy) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, pgb.build.ctx, "GroupBy")
if err := pgb.build.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*PlatformQuery, *PlatformGroupBy](ctx, pgb.build, pgb, pgb.build.inters, v)
}
func (pgb *PlatformGroupBy) sqlScan(ctx context.Context, root *PlatformQuery, v any) error {
selector := root.sqlQuery(ctx).Select()
aggregation := make([]string, 0, len(pgb.fns))
for _, fn := range pgb.fns {
aggregation = append(aggregation, fn(selector))
}
if len(selector.SelectedColumns()) == 0 {
columns := make([]string, 0, len(*pgb.flds)+len(pgb.fns))
for _, f := range *pgb.flds {
columns = append(columns, selector.C(f))
}
columns = append(columns, aggregation...)
selector.Select(columns...)
}
selector.GroupBy(selector.Columns(*pgb.flds...)...)
if err := selector.Err(); err != nil {
return err
}
rows := &sql.Rows{}
query, args := selector.Query()
if err := pgb.build.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}
// PlatformSelect is the builder for selecting fields of Platform entities.
type PlatformSelect struct {
*PlatformQuery
selector
}
// Aggregate adds the given aggregation functions to the selector query.
func (ps *PlatformSelect) Aggregate(fns ...AggregateFunc) *PlatformSelect {
ps.fns = append(ps.fns, fns...)
return ps
}
// Scan applies the selector query and scans the result into the given value.
func (ps *PlatformSelect) Scan(ctx context.Context, v any) error {
ctx = setContextOp(ctx, ps.ctx, "Select")
if err := ps.prepareQuery(ctx); err != nil {
return err
}
return scanWithInterceptors[*PlatformQuery, *PlatformSelect](ctx, ps.PlatformQuery, ps, ps.inters, v)
}
func (ps *PlatformSelect) sqlScan(ctx context.Context, root *PlatformQuery, v any) error {
selector := root.sqlQuery(ctx)
aggregation := make([]string, 0, len(ps.fns))
for _, fn := range ps.fns {
aggregation = append(aggregation, fn(selector))
}
switch n := len(*ps.selector.flds); {
case n == 0 && len(aggregation) > 0:
selector.Select(aggregation...)
case n != 0 && len(aggregation) > 0:
selector.AppendSelect(aggregation...)
}
rows := &sql.Rows{}
query, args := selector.Query()
if err := ps.driver.Query(ctx, query, args, rows); err != nil {
return err
}
defer rows.Close()
return sql.ScanSlice(rows, v)
}

View File

@@ -0,0 +1,728 @@
// Code generated by ent, DO NOT EDIT.
package ent
import (
"context"
"errors"
"fmt"
"time"
"entgo.io/ent/dialect/sql"
"entgo.io/ent/dialect/sql/sqlgraph"
"entgo.io/ent/schema/field"
"github.com/gofrs/uuid"
"github.com/holos-run/holos/internal/ent/organization"
"github.com/holos-run/holos/internal/ent/platform"
"github.com/holos-run/holos/internal/ent/predicate"
"github.com/holos-run/holos/internal/ent/user"
storage "github.com/holos-run/holos/service/gen/holos/storage/v1alpha1"
)
// PlatformUpdate is the builder for updating Platform entities.
type PlatformUpdate struct {
config
hooks []Hook
mutation *PlatformMutation
}
// Where appends a list predicates to the PlatformUpdate builder.
func (pu *PlatformUpdate) Where(ps ...predicate.Platform) *PlatformUpdate {
pu.mutation.Where(ps...)
return pu
}
// SetUpdatedAt sets the "updated_at" field.
func (pu *PlatformUpdate) SetUpdatedAt(t time.Time) *PlatformUpdate {
pu.mutation.SetUpdatedAt(t)
return pu
}
// SetUpdatedByID sets the "updated_by_id" field.
func (pu *PlatformUpdate) SetUpdatedByID(u uuid.UUID) *PlatformUpdate {
pu.mutation.SetUpdatedByID(u)
return pu
}
// SetNillableUpdatedByID sets the "updated_by_id" field if the given value is not nil.
func (pu *PlatformUpdate) SetNillableUpdatedByID(u *uuid.UUID) *PlatformUpdate {
if u != nil {
pu.SetUpdatedByID(*u)
}
return pu
}
// SetOrgID sets the "org_id" field.
func (pu *PlatformUpdate) SetOrgID(u uuid.UUID) *PlatformUpdate {
pu.mutation.SetOrgID(u)
return pu
}
// SetNillableOrgID sets the "org_id" field if the given value is not nil.
func (pu *PlatformUpdate) SetNillableOrgID(u *uuid.UUID) *PlatformUpdate {
if u != nil {
pu.SetOrgID(*u)
}
return pu
}
// SetName sets the "name" field.
func (pu *PlatformUpdate) SetName(s string) *PlatformUpdate {
pu.mutation.SetName(s)
return pu
}
// SetNillableName sets the "name" field if the given value is not nil.
func (pu *PlatformUpdate) SetNillableName(s *string) *PlatformUpdate {
if s != nil {
pu.SetName(*s)
}
return pu
}
// SetDisplayName sets the "display_name" field.
func (pu *PlatformUpdate) SetDisplayName(s string) *PlatformUpdate {
pu.mutation.SetDisplayName(s)
return pu
}
// SetNillableDisplayName sets the "display_name" field if the given value is not nil.
func (pu *PlatformUpdate) SetNillableDisplayName(s *string) *PlatformUpdate {
if s != nil {
pu.SetDisplayName(*s)
}
return pu
}
// SetForm sets the "form" field.
func (pu *PlatformUpdate) SetForm(s *storage.Form) *PlatformUpdate {
pu.mutation.SetForm(s)
return pu
}
// ClearForm clears the value of the "form" field.
func (pu *PlatformUpdate) ClearForm() *PlatformUpdate {
pu.mutation.ClearForm()
return pu
}
// SetModel sets the "model" field.
func (pu *PlatformUpdate) SetModel(s *storage.Model) *PlatformUpdate {
pu.mutation.SetModel(s)
return pu
}
// ClearModel clears the value of the "model" field.
func (pu *PlatformUpdate) ClearModel() *PlatformUpdate {
pu.mutation.ClearModel()
return pu
}
// SetCue sets the "cue" field.
func (pu *PlatformUpdate) SetCue(b []byte) *PlatformUpdate {
pu.mutation.SetCue(b)
return pu
}
// ClearCue clears the value of the "cue" field.
func (pu *PlatformUpdate) ClearCue() *PlatformUpdate {
pu.mutation.ClearCue()
return pu
}
// SetCueDefinition sets the "cue_definition" field.
func (pu *PlatformUpdate) SetCueDefinition(s string) *PlatformUpdate {
pu.mutation.SetCueDefinition(s)
return pu
}
// SetNillableCueDefinition sets the "cue_definition" field if the given value is not nil.
func (pu *PlatformUpdate) SetNillableCueDefinition(s *string) *PlatformUpdate {
if s != nil {
pu.SetCueDefinition(*s)
}
return pu
}
// ClearCueDefinition clears the value of the "cue_definition" field.
func (pu *PlatformUpdate) ClearCueDefinition() *PlatformUpdate {
pu.mutation.ClearCueDefinition()
return pu
}
// SetEditorID sets the "editor" edge to the User entity by ID.
func (pu *PlatformUpdate) SetEditorID(id uuid.UUID) *PlatformUpdate {
pu.mutation.SetEditorID(id)
return pu
}
// SetEditor sets the "editor" edge to the User entity.
func (pu *PlatformUpdate) SetEditor(u *User) *PlatformUpdate {
return pu.SetEditorID(u.ID)
}
// SetOrganizationID sets the "organization" edge to the Organization entity by ID.
func (pu *PlatformUpdate) SetOrganizationID(id uuid.UUID) *PlatformUpdate {
pu.mutation.SetOrganizationID(id)
return pu
}
// SetOrganization sets the "organization" edge to the Organization entity.
func (pu *PlatformUpdate) SetOrganization(o *Organization) *PlatformUpdate {
return pu.SetOrganizationID(o.ID)
}
// Mutation returns the PlatformMutation object of the builder.
func (pu *PlatformUpdate) Mutation() *PlatformMutation {
return pu.mutation
}
// ClearEditor clears the "editor" edge to the User entity.
func (pu *PlatformUpdate) ClearEditor() *PlatformUpdate {
pu.mutation.ClearEditor()
return pu
}
// ClearOrganization clears the "organization" edge to the Organization entity.
func (pu *PlatformUpdate) ClearOrganization() *PlatformUpdate {
pu.mutation.ClearOrganization()
return pu
}
// Save executes the query and returns the number of nodes affected by the update operation.
func (pu *PlatformUpdate) Save(ctx context.Context) (int, error) {
pu.defaults()
return withHooks(ctx, pu.sqlSave, pu.mutation, pu.hooks)
}
// SaveX is like Save, but panics if an error occurs.
func (pu *PlatformUpdate) SaveX(ctx context.Context) int {
affected, err := pu.Save(ctx)
if err != nil {
panic(err)
}
return affected
}
// Exec executes the query.
func (pu *PlatformUpdate) Exec(ctx context.Context) error {
_, err := pu.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (pu *PlatformUpdate) ExecX(ctx context.Context) {
if err := pu.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (pu *PlatformUpdate) defaults() {
if _, ok := pu.mutation.UpdatedAt(); !ok {
v := platform.UpdateDefaultUpdatedAt()
pu.mutation.SetUpdatedAt(v)
}
}
// check runs all checks and user-defined validators on the builder.
func (pu *PlatformUpdate) check() error {
if v, ok := pu.mutation.Name(); ok {
if err := platform.NameValidator(v); err != nil {
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "Platform.name": %w`, err)}
}
}
if _, ok := pu.mutation.CreatorID(); pu.mutation.CreatorCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "Platform.creator"`)
}
if _, ok := pu.mutation.EditorID(); pu.mutation.EditorCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "Platform.editor"`)
}
if _, ok := pu.mutation.OrganizationID(); pu.mutation.OrganizationCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "Platform.organization"`)
}
return nil
}
func (pu *PlatformUpdate) sqlSave(ctx context.Context) (n int, err error) {
if err := pu.check(); err != nil {
return n, err
}
_spec := sqlgraph.NewUpdateSpec(platform.Table, platform.Columns, sqlgraph.NewFieldSpec(platform.FieldID, field.TypeUUID))
if ps := pu.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if value, ok := pu.mutation.UpdatedAt(); ok {
_spec.SetField(platform.FieldUpdatedAt, field.TypeTime, value)
}
if value, ok := pu.mutation.Name(); ok {
_spec.SetField(platform.FieldName, field.TypeString, value)
}
if value, ok := pu.mutation.DisplayName(); ok {
_spec.SetField(platform.FieldDisplayName, field.TypeString, value)
}
if value, ok := pu.mutation.Form(); ok {
_spec.SetField(platform.FieldForm, field.TypeJSON, value)
}
if pu.mutation.FormCleared() {
_spec.ClearField(platform.FieldForm, field.TypeJSON)
}
if value, ok := pu.mutation.Model(); ok {
_spec.SetField(platform.FieldModel, field.TypeJSON, value)
}
if pu.mutation.ModelCleared() {
_spec.ClearField(platform.FieldModel, field.TypeJSON)
}
if value, ok := pu.mutation.Cue(); ok {
_spec.SetField(platform.FieldCue, field.TypeBytes, value)
}
if pu.mutation.CueCleared() {
_spec.ClearField(platform.FieldCue, field.TypeBytes)
}
if value, ok := pu.mutation.CueDefinition(); ok {
_spec.SetField(platform.FieldCueDefinition, field.TypeString, value)
}
if pu.mutation.CueDefinitionCleared() {
_spec.ClearField(platform.FieldCueDefinition, field.TypeString)
}
if pu.mutation.EditorCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: platform.EditorTable,
Columns: []string{platform.EditorColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeUUID),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := pu.mutation.EditorIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: platform.EditorTable,
Columns: []string{platform.EditorColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if pu.mutation.OrganizationCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: platform.OrganizationTable,
Columns: []string{platform.OrganizationColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(organization.FieldID, field.TypeUUID),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := pu.mutation.OrganizationIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: platform.OrganizationTable,
Columns: []string{platform.OrganizationColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(organization.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if n, err = sqlgraph.UpdateNodes(ctx, pu.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{platform.Label}
} else if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
return 0, err
}
pu.mutation.done = true
return n, nil
}
// PlatformUpdateOne is the builder for updating a single Platform entity.
type PlatformUpdateOne struct {
config
fields []string
hooks []Hook
mutation *PlatformMutation
}
// SetUpdatedAt sets the "updated_at" field.
func (puo *PlatformUpdateOne) SetUpdatedAt(t time.Time) *PlatformUpdateOne {
puo.mutation.SetUpdatedAt(t)
return puo
}
// SetUpdatedByID sets the "updated_by_id" field.
func (puo *PlatformUpdateOne) SetUpdatedByID(u uuid.UUID) *PlatformUpdateOne {
puo.mutation.SetUpdatedByID(u)
return puo
}
// SetNillableUpdatedByID sets the "updated_by_id" field if the given value is not nil.
func (puo *PlatformUpdateOne) SetNillableUpdatedByID(u *uuid.UUID) *PlatformUpdateOne {
if u != nil {
puo.SetUpdatedByID(*u)
}
return puo
}
// SetOrgID sets the "org_id" field.
func (puo *PlatformUpdateOne) SetOrgID(u uuid.UUID) *PlatformUpdateOne {
puo.mutation.SetOrgID(u)
return puo
}
// SetNillableOrgID sets the "org_id" field if the given value is not nil.
func (puo *PlatformUpdateOne) SetNillableOrgID(u *uuid.UUID) *PlatformUpdateOne {
if u != nil {
puo.SetOrgID(*u)
}
return puo
}
// SetName sets the "name" field.
func (puo *PlatformUpdateOne) SetName(s string) *PlatformUpdateOne {
puo.mutation.SetName(s)
return puo
}
// SetNillableName sets the "name" field if the given value is not nil.
func (puo *PlatformUpdateOne) SetNillableName(s *string) *PlatformUpdateOne {
if s != nil {
puo.SetName(*s)
}
return puo
}
// SetDisplayName sets the "display_name" field.
func (puo *PlatformUpdateOne) SetDisplayName(s string) *PlatformUpdateOne {
puo.mutation.SetDisplayName(s)
return puo
}
// SetNillableDisplayName sets the "display_name" field if the given value is not nil.
func (puo *PlatformUpdateOne) SetNillableDisplayName(s *string) *PlatformUpdateOne {
if s != nil {
puo.SetDisplayName(*s)
}
return puo
}
// SetForm sets the "form" field.
func (puo *PlatformUpdateOne) SetForm(s *storage.Form) *PlatformUpdateOne {
puo.mutation.SetForm(s)
return puo
}
// ClearForm clears the value of the "form" field.
func (puo *PlatformUpdateOne) ClearForm() *PlatformUpdateOne {
puo.mutation.ClearForm()
return puo
}
// SetModel sets the "model" field.
func (puo *PlatformUpdateOne) SetModel(s *storage.Model) *PlatformUpdateOne {
puo.mutation.SetModel(s)
return puo
}
// ClearModel clears the value of the "model" field.
func (puo *PlatformUpdateOne) ClearModel() *PlatformUpdateOne {
puo.mutation.ClearModel()
return puo
}
// SetCue sets the "cue" field.
func (puo *PlatformUpdateOne) SetCue(b []byte) *PlatformUpdateOne {
puo.mutation.SetCue(b)
return puo
}
// ClearCue clears the value of the "cue" field.
func (puo *PlatformUpdateOne) ClearCue() *PlatformUpdateOne {
puo.mutation.ClearCue()
return puo
}
// SetCueDefinition sets the "cue_definition" field.
func (puo *PlatformUpdateOne) SetCueDefinition(s string) *PlatformUpdateOne {
puo.mutation.SetCueDefinition(s)
return puo
}
// SetNillableCueDefinition sets the "cue_definition" field if the given value is not nil.
func (puo *PlatformUpdateOne) SetNillableCueDefinition(s *string) *PlatformUpdateOne {
if s != nil {
puo.SetCueDefinition(*s)
}
return puo
}
// ClearCueDefinition clears the value of the "cue_definition" field.
func (puo *PlatformUpdateOne) ClearCueDefinition() *PlatformUpdateOne {
puo.mutation.ClearCueDefinition()
return puo
}
// SetEditorID sets the "editor" edge to the User entity by ID.
func (puo *PlatformUpdateOne) SetEditorID(id uuid.UUID) *PlatformUpdateOne {
puo.mutation.SetEditorID(id)
return puo
}
// SetEditor sets the "editor" edge to the User entity.
func (puo *PlatformUpdateOne) SetEditor(u *User) *PlatformUpdateOne {
return puo.SetEditorID(u.ID)
}
// SetOrganizationID sets the "organization" edge to the Organization entity by ID.
func (puo *PlatformUpdateOne) SetOrganizationID(id uuid.UUID) *PlatformUpdateOne {
puo.mutation.SetOrganizationID(id)
return puo
}
// SetOrganization sets the "organization" edge to the Organization entity.
func (puo *PlatformUpdateOne) SetOrganization(o *Organization) *PlatformUpdateOne {
return puo.SetOrganizationID(o.ID)
}
// Mutation returns the PlatformMutation object of the builder.
func (puo *PlatformUpdateOne) Mutation() *PlatformMutation {
return puo.mutation
}
// ClearEditor clears the "editor" edge to the User entity.
func (puo *PlatformUpdateOne) ClearEditor() *PlatformUpdateOne {
puo.mutation.ClearEditor()
return puo
}
// ClearOrganization clears the "organization" edge to the Organization entity.
func (puo *PlatformUpdateOne) ClearOrganization() *PlatformUpdateOne {
puo.mutation.ClearOrganization()
return puo
}
// Where appends a list predicates to the PlatformUpdate builder.
func (puo *PlatformUpdateOne) Where(ps ...predicate.Platform) *PlatformUpdateOne {
puo.mutation.Where(ps...)
return puo
}
// Select allows selecting one or more fields (columns) of the returned entity.
// The default is selecting all fields defined in the entity schema.
func (puo *PlatformUpdateOne) Select(field string, fields ...string) *PlatformUpdateOne {
puo.fields = append([]string{field}, fields...)
return puo
}
// Save executes the query and returns the updated Platform entity.
func (puo *PlatformUpdateOne) Save(ctx context.Context) (*Platform, error) {
puo.defaults()
return withHooks(ctx, puo.sqlSave, puo.mutation, puo.hooks)
}
// SaveX is like Save, but panics if an error occurs.
func (puo *PlatformUpdateOne) SaveX(ctx context.Context) *Platform {
node, err := puo.Save(ctx)
if err != nil {
panic(err)
}
return node
}
// Exec executes the query on the entity.
func (puo *PlatformUpdateOne) Exec(ctx context.Context) error {
_, err := puo.Save(ctx)
return err
}
// ExecX is like Exec, but panics if an error occurs.
func (puo *PlatformUpdateOne) ExecX(ctx context.Context) {
if err := puo.Exec(ctx); err != nil {
panic(err)
}
}
// defaults sets the default values of the builder before save.
func (puo *PlatformUpdateOne) defaults() {
if _, ok := puo.mutation.UpdatedAt(); !ok {
v := platform.UpdateDefaultUpdatedAt()
puo.mutation.SetUpdatedAt(v)
}
}
// check runs all checks and user-defined validators on the builder.
func (puo *PlatformUpdateOne) check() error {
if v, ok := puo.mutation.Name(); ok {
if err := platform.NameValidator(v); err != nil {
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "Platform.name": %w`, err)}
}
}
if _, ok := puo.mutation.CreatorID(); puo.mutation.CreatorCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "Platform.creator"`)
}
if _, ok := puo.mutation.EditorID(); puo.mutation.EditorCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "Platform.editor"`)
}
if _, ok := puo.mutation.OrganizationID(); puo.mutation.OrganizationCleared() && !ok {
return errors.New(`ent: clearing a required unique edge "Platform.organization"`)
}
return nil
}
func (puo *PlatformUpdateOne) sqlSave(ctx context.Context) (_node *Platform, err error) {
if err := puo.check(); err != nil {
return _node, err
}
_spec := sqlgraph.NewUpdateSpec(platform.Table, platform.Columns, sqlgraph.NewFieldSpec(platform.FieldID, field.TypeUUID))
id, ok := puo.mutation.ID()
if !ok {
return nil, &ValidationError{Name: "id", err: errors.New(`ent: missing "Platform.id" for update`)}
}
_spec.Node.ID.Value = id
if fields := puo.fields; len(fields) > 0 {
_spec.Node.Columns = make([]string, 0, len(fields))
_spec.Node.Columns = append(_spec.Node.Columns, platform.FieldID)
for _, f := range fields {
if !platform.ValidColumn(f) {
return nil, &ValidationError{Name: f, err: fmt.Errorf("ent: invalid field %q for query", f)}
}
if f != platform.FieldID {
_spec.Node.Columns = append(_spec.Node.Columns, f)
}
}
}
if ps := puo.mutation.predicates; len(ps) > 0 {
_spec.Predicate = func(selector *sql.Selector) {
for i := range ps {
ps[i](selector)
}
}
}
if value, ok := puo.mutation.UpdatedAt(); ok {
_spec.SetField(platform.FieldUpdatedAt, field.TypeTime, value)
}
if value, ok := puo.mutation.Name(); ok {
_spec.SetField(platform.FieldName, field.TypeString, value)
}
if value, ok := puo.mutation.DisplayName(); ok {
_spec.SetField(platform.FieldDisplayName, field.TypeString, value)
}
if value, ok := puo.mutation.Form(); ok {
_spec.SetField(platform.FieldForm, field.TypeJSON, value)
}
if puo.mutation.FormCleared() {
_spec.ClearField(platform.FieldForm, field.TypeJSON)
}
if value, ok := puo.mutation.Model(); ok {
_spec.SetField(platform.FieldModel, field.TypeJSON, value)
}
if puo.mutation.ModelCleared() {
_spec.ClearField(platform.FieldModel, field.TypeJSON)
}
if value, ok := puo.mutation.Cue(); ok {
_spec.SetField(platform.FieldCue, field.TypeBytes, value)
}
if puo.mutation.CueCleared() {
_spec.ClearField(platform.FieldCue, field.TypeBytes)
}
if value, ok := puo.mutation.CueDefinition(); ok {
_spec.SetField(platform.FieldCueDefinition, field.TypeString, value)
}
if puo.mutation.CueDefinitionCleared() {
_spec.ClearField(platform.FieldCueDefinition, field.TypeString)
}
if puo.mutation.EditorCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: platform.EditorTable,
Columns: []string{platform.EditorColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeUUID),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := puo.mutation.EditorIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: platform.EditorTable,
Columns: []string{platform.EditorColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(user.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
if puo.mutation.OrganizationCleared() {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: platform.OrganizationTable,
Columns: []string{platform.OrganizationColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(organization.FieldID, field.TypeUUID),
},
}
_spec.Edges.Clear = append(_spec.Edges.Clear, edge)
}
if nodes := puo.mutation.OrganizationIDs(); len(nodes) > 0 {
edge := &sqlgraph.EdgeSpec{
Rel: sqlgraph.M2O,
Inverse: false,
Table: platform.OrganizationTable,
Columns: []string{platform.OrganizationColumn},
Bidi: false,
Target: &sqlgraph.EdgeTarget{
IDSpec: sqlgraph.NewFieldSpec(organization.FieldID, field.TypeUUID),
},
}
for _, k := range nodes {
edge.Target.Nodes = append(edge.Target.Nodes, k)
}
_spec.Edges.Add = append(_spec.Edges.Add, edge)
}
_node = &Platform{config: puo.config}
_spec.Assign = _node.assignValues
_spec.ScanValues = _node.scanValues
if err = sqlgraph.UpdateNode(ctx, puo.driver, _spec); err != nil {
if _, ok := err.(*sqlgraph.NotFoundError); ok {
err = &NotFoundError{platform.Label}
} else if sqlgraph.IsConstraintError(err) {
err = &ConstraintError{msg: err.Error(), wrap: err}
}
return nil, err
}
puo.mutation.done = true
return _node, nil
}

View File

@@ -9,5 +9,8 @@ import (
// Organization is the predicate function for organization builders.
type Organization func(*sql.Selector)
// Platform is the predicate function for platform builders.
type Platform func(*sql.Selector)
// User is the predicate function for user builders.
type User func(*sql.Selector)

View File

@@ -7,6 +7,7 @@ import (
"github.com/gofrs/uuid"
"github.com/holos-run/holos/internal/ent/organization"
"github.com/holos-run/holos/internal/ent/platform"
"github.com/holos-run/holos/internal/ent/schema"
"github.com/holos-run/holos/internal/ent/user"
)
@@ -40,6 +41,31 @@ func init() {
organizationDescID := organizationMixinFields0[0].Descriptor()
// organization.DefaultID holds the default value on creation for the id field.
organization.DefaultID = organizationDescID.Default.(func() uuid.UUID)
platformMixin := schema.Platform{}.Mixin()
platformMixinFields0 := platformMixin[0].Fields()
_ = platformMixinFields0
platformMixinFields1 := platformMixin[1].Fields()
_ = platformMixinFields1
platformFields := schema.Platform{}.Fields()
_ = platformFields
// platformDescCreatedAt is the schema descriptor for created_at field.
platformDescCreatedAt := platformMixinFields1[0].Descriptor()
// platform.DefaultCreatedAt holds the default value on creation for the created_at field.
platform.DefaultCreatedAt = platformDescCreatedAt.Default.(func() time.Time)
// platformDescUpdatedAt is the schema descriptor for updated_at field.
platformDescUpdatedAt := platformMixinFields1[1].Descriptor()
// platform.DefaultUpdatedAt holds the default value on creation for the updated_at field.
platform.DefaultUpdatedAt = platformDescUpdatedAt.Default.(func() time.Time)
// platform.UpdateDefaultUpdatedAt holds the default value on update for the updated_at field.
platform.UpdateDefaultUpdatedAt = platformDescUpdatedAt.UpdateDefault.(func() time.Time)
// platformDescName is the schema descriptor for name field.
platformDescName := platformFields[1].Descriptor()
// platform.NameValidator is a validator for the "name" field. It is called by the builders before save.
platform.NameValidator = platformDescName.Validators[0].(func(string) error)
// platformDescID is the schema descriptor for id field.
platformDescID := platformMixinFields0[0].Descriptor()
// platform.DefaultID holds the default value on creation for the id field.
platform.DefaultID = platformDescID.Default.(func() uuid.UUID)
userMixin := schema.User{}.Mixin()
userMixinFields0 := userMixin[0].Fields()
_ = userMixinFields0

View File

@@ -4,6 +4,7 @@ import (
"time"
"entgo.io/ent"
"entgo.io/ent/schema/edge"
"entgo.io/ent/schema/field"
"entgo.io/ent/schema/mixin"
"github.com/gofrs/uuid"
@@ -13,23 +14,25 @@ func newUUID() uuid.UUID {
return uuid.Must(uuid.NewV7())
}
type BaseMixin struct {
// IDMixin mixes in an id field with a server generated default. All resource
// objects in the storage system should be identified by a uuid.
type IDMixin struct {
mixin.Schema
}
func (BaseMixin) Fields() []ent.Field {
func (IDMixin) Fields() []ent.Field {
return []ent.Field{
// id represents the identity of the entity.
field.UUID("id", uuid.UUID{}).Default(newUUID),
}
}
// TimeMixin adds created_at and updated_at fields.
type TimeMixin struct {
// TimestampMixin adds created_at and updated_at fields.
type TimestampMixin struct {
mixin.Schema
}
func (TimeMixin) Fields() []ent.Field {
func (TimestampMixin) Fields() []ent.Field {
return []ent.Field{
field.Time("created_at").
Immutable().
@@ -39,3 +42,30 @@ func (TimeMixin) Fields() []ent.Field {
UpdateDefault(time.Now),
}
}
// EditorMixin adds created_by_id and updated_by_id fields representing the user
// who created or last modified the resource.
type EditorMixin struct {
mixin.Schema
}
func (EditorMixin) Fields() []ent.Field {
return []ent.Field{
field.UUID("created_by_id", uuid.UUID{}).Immutable(),
field.UUID("updated_by_id", uuid.UUID{}),
}
}
func (EditorMixin) Edges() []ent.Edge {
return []ent.Edge{
edge.To("creator", User.Type).
Field("created_by_id").
Immutable().
Unique().
Required(),
edge.To("editor", User.Type).
Field("updated_by_id").
Unique().
Required(),
}
}

View File

@@ -4,7 +4,6 @@ import (
"entgo.io/ent"
"entgo.io/ent/schema/edge"
"entgo.io/ent/schema/field"
"github.com/gofrs/uuid"
)
// Organization represents an organization account.
@@ -14,8 +13,9 @@ type Organization struct {
func (Organization) Mixin() []ent.Mixin {
return []ent.Mixin{
BaseMixin{},
TimeMixin{},
IDMixin{},
TimestampMixin{},
EditorMixin{},
}
}
@@ -23,16 +23,13 @@ func (Organization) Fields() []ent.Field {
return []ent.Field{
field.String("name").NotEmpty().Unique(),
field.String("display_name"),
field.UUID("creator_id", uuid.UUID{}),
}
}
func (Organization) Edges() []ent.Edge {
return []ent.Edge{
edge.To("creator", User.Type).
Field("creator_id").
Unique().
Required(),
edge.To("users", User.Type),
edge.From("platforms", Platform.Type).
Ref("organization"),
}
}

View File

@@ -0,0 +1,58 @@
package schema
import (
"entgo.io/ent"
"entgo.io/ent/schema/edge"
"entgo.io/ent/schema/field"
"entgo.io/ent/schema/index"
"github.com/gofrs/uuid"
storage "github.com/holos-run/holos/service/gen/holos/storage/v1alpha1"
)
type Platform struct {
ent.Schema
}
func (Platform) Mixin() []ent.Mixin {
return []ent.Mixin{
IDMixin{},
TimestampMixin{},
EditorMixin{},
}
}
func (Platform) Fields() []ent.Field {
return []ent.Field{
field.UUID("org_id", uuid.UUID{}),
field.String("name").NotEmpty(),
field.String("display_name"),
field.JSON("form", &storage.Form{}).
Optional().
Comment("JSON representation of FormlyFormConfig[] refer to https://github.com/holos-run/holos/issues/161"),
field.JSON("model", &storage.Model{}).
Optional().
Comment("JSON representation of the form model which holds user input values refer to https://github.com/holos-run/holos/issues/161"),
field.Bytes("cue").
Optional().
Comment("CUE definition to vet the model against e.g. #PlatformConfig"),
field.String("cue_definition").
Optional().
Comment("The definition name to vet config_values against config_cue e.g. '#PlatformSpec'"),
}
}
func (Platform) Edges() []ent.Edge {
return []ent.Edge{
edge.To("organization", Organization.Type).
Field("org_id").
Unique().
Required(),
}
}
func (Platform) Indexes() []ent.Index {
return []ent.Index{
// One org cannot have two platforms with the same name.
index.Fields("org_id", "name").Unique(),
}
}

View File

@@ -16,8 +16,8 @@ type User struct {
func (User) Mixin() []ent.Mixin {
return []ent.Mixin{
BaseMixin{},
TimeMixin{},
IDMixin{},
TimestampMixin{},
}
}

View File

@@ -14,6 +14,8 @@ type Tx struct {
config
// Organization is the client for interacting with the Organization builders.
Organization *OrganizationClient
// Platform is the client for interacting with the Platform builders.
Platform *PlatformClient
// User is the client for interacting with the User builders.
User *UserClient
@@ -148,6 +150,7 @@ func (tx *Tx) Client() *Client {
func (tx *Tx) init() {
tx.Organization = NewOrganizationClient(tx.config)
tx.Platform = NewPlatformClient(tx.config)
tx.User = NewUserClient(tx.config)
}

View File

@@ -0,0 +1,47 @@
{
"root": true,
"ignorePatterns": [
"projects/**/*"
],
"overrides": [
{
"files": [
"*.ts"
],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@angular-eslint/recommended",
"plugin:@angular-eslint/template/process-inline-templates"
],
"rules": {
"@angular-eslint/directive-selector": [
"error",
{
"type": "attribute",
"prefix": "app",
"style": "camelCase"
}
],
"@angular-eslint/component-selector": [
"error",
{
"type": "element",
"prefix": "app",
"style": "kebab-case"
}
]
}
},
{
"files": [
"*.html"
],
"extends": [
"plugin:@angular-eslint/template/recommended",
"plugin:@angular-eslint/template/accessibility"
],
"rules": {}
}
]
}

View File

@@ -40,3 +40,6 @@ testem.log
# System files
.DS_Store
Thumbs.db
# NX?
/.nx/

View File

@@ -45,7 +45,7 @@
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
@@ -100,8 +100,23 @@
],
"scripts": []
}
},
"lint": {
"builder": "@angular-eslint/builder:lint",
"options": {
"lintFilePatterns": [
"src/**/*.ts",
"src/**/*.html"
]
}
}
}
}
},
"cli": {
"schematicCollections": [
"@angular-eslint/schematics"
],
"analytics": false
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -6,7 +6,8 @@
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
"test": "ng test",
"lint": "ng lint"
},
"private": true,
"dependencies": {
@@ -22,21 +23,32 @@
"@angular/router": "^17.3.0",
"@bufbuild/protobuf": "^1.9.0",
"@connectrpc/connect": "^1.4.0",
"@connectrpc/connect-query": "^1.3.1",
"@connectrpc/connect-query": "^1.4.0",
"@connectrpc/connect-web": "^1.4.0",
"@ngx-formly/core": "^6.3.0",
"@ngx-formly/material": "^6.3.0",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.3"
},
"devDependencies": {
"@angular-devkit/build-angular": "^17.3.4",
"@angular-eslint/builder": "17.3.0",
"@angular-eslint/eslint-plugin": "17.3.0",
"@angular-eslint/eslint-plugin-template": "17.3.0",
"@angular-eslint/schematics": "17.3.0",
"@angular-eslint/template-parser": "17.3.0",
"@angular/cli": "^17.3.4",
"@angular/compiler-cli": "^17.3.0",
"@bufbuild/buf": "^1.31.0",
"@bufbuild/buf": "^1.32.0",
"@bufbuild/protoc-gen-es": "^1.9.0",
"@connectrpc/protoc-gen-connect-es": "^1.4.0",
"@connectrpc/protoc-gen-connect-query": "^1.3.1",
"@connectrpc/protoc-gen-connect-query": "^1.4.0",
"@ngx-formly/schematics": "^6.3.0",
"@types/jasmine": "~5.1.0",
"@typescript-eslint/eslint-plugin": "7.2.0",
"@typescript-eslint/parser": "7.2.0",
"eslint": "^8.57.0",
"jasmine-core": "~5.1.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",

View File

@@ -1,25 +1,33 @@
import { ApplicationConfig, importProvidersFrom } from '@angular/core';
import { provideRouter } from '@angular/router';
import { provideRouter, withComponentInputBinding } from '@angular/router';
import { FormlyModule } from '@ngx-formly/core';
// import { provideHttpClient, withFetch } from '@angular/common/http';
import { routes } from './app.routes';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
import { ConnectModule } from '../connect/connect.module';
import { provideClient } from "../connect/client.provider";
import { UserService } from './gen/holos/v1alpha1/user_connect';
import { OrganizationService } from './gen/holos/v1alpha1/organization_connect';
import { UserService } from './gen/holos/user/v1alpha1/user_service_connect';
import { OrganizationService } from './gen/holos/organization/v1alpha1/organization_service_connect';
import { PlatformService } from './gen/holos/platform/v1alpha1/platform_service_connect';
import { HolosPanelWrapperComponent } from '../wrappers/holos-panel-wrapper/holos-panel-wrapper.component';
import { SystemService } from './gen/holos/system/v1alpha1/system_service_connect';
export const appConfig: ApplicationConfig = {
providers: [
provideRouter(routes),
provideRouter(routes, withComponentInputBinding()),
provideAnimationsAsync(),
// provideHttpClient(withFetch()),
provideClient(UserService),
provideClient(OrganizationService),
provideClient(PlatformService),
provideClient(SystemService),
importProvidersFrom(
ConnectModule.forRoot({
baseUrl: window.location.origin
}),
FormlyModule.forRoot({
wrappers: [{ name: 'holos-panel', component: HolosPanelWrapperComponent }],
}),
),
]
};

View File

@@ -1,11 +1,13 @@
import { Routes } from '@angular/router';
import { HomeComponent } from './home/home.component';
import { ClusterListComponent } from './cluster-list/cluster-list.component';
import { ErrorNotFoundComponent } from './error-not-found/error-not-found.component';
import { PlatformsComponent } from './views/platforms/platforms.component'
import { PlatformDetailComponent } from './views/platform-detail/platform-detail.component';
export const routes: Routes = [
{ path: 'platform/:id', component: PlatformDetailComponent },
{ path: 'platforms', component: PlatformsComponent },
{ path: 'home', component: HomeComponent },
{ path: 'clusters', component: ClusterListComponent },
{ path: '', redirectTo: '/home', pathMatch: 'full' },
{ path: '', redirectTo: '/platforms', pathMatch: 'full' },
{ path: '**', component: ErrorNotFoundComponent },
];

View File

@@ -1,26 +0,0 @@
<div class="grid-container">
<h1 class="mat-h1">Clusters</h1>
<mat-grid-list cols="2" rowHeight="350px">
@for (card of cards | async; track card) {
<mat-grid-tile [colspan]="card.cols" [rowspan]="card.rows">
<mat-card class="dashboard-card">
<mat-card-header>
<mat-card-title>
{{card.title}}
<button mat-icon-button class="more-button" [matMenuTriggerFor]="menu" aria-label="Toggle menu">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu #menu="matMenu" xPosition="before">
<button mat-menu-item>Expand</button>
<button mat-menu-item>Remove</button>
</mat-menu>
</mat-card-title>
</mat-card-header>
<mat-card-content class="dashboard-card-content">
<div>Card Content Here</div>
</mat-card-content>
</mat-card>
</mat-grid-tile>
}
</mat-grid-list>
</div>

View File

@@ -1,21 +0,0 @@
.grid-container {
margin: 20px;
}
.dashboard-card {
position: absolute;
top: 15px;
left: 15px;
right: 15px;
bottom: 15px;
}
.more-button {
position: absolute;
top: 5px;
right: 10px;
}
.dashboard-card-content {
text-align: center;
}

View File

@@ -1,25 +0,0 @@
import { waitForAsync, ComponentFixture, TestBed } from '@angular/core/testing';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { ClusterListComponent } from './cluster-list.component';
describe('ClusterListComponent', () => {
let component: ClusterListComponent;
let fixture: ComponentFixture<ClusterListComponent>;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [NoopAnimationsModule]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ClusterListComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should compile', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -1,48 +0,0 @@
import { Component, inject } from '@angular/core';
import { Breakpoints, BreakpointObserver } from '@angular/cdk/layout';
import { map } from 'rxjs/operators';
import { AsyncPipe } from '@angular/common';
import { MatGridListModule } from '@angular/material/grid-list';
import { MatMenuModule } from '@angular/material/menu';
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
import { MatCardModule } from '@angular/material/card';
@Component({
selector: 'app-cluster-list',
templateUrl: './cluster-list.component.html',
styleUrl: './cluster-list.component.scss',
standalone: true,
imports: [
AsyncPipe,
MatGridListModule,
MatMenuModule,
MatIconModule,
MatButtonModule,
MatCardModule
]
})
export class ClusterListComponent {
private breakpointObserver = inject(BreakpointObserver);
/** Based on the screen size, switch from standard to one column per row */
cards = this.breakpointObserver.observe(Breakpoints.Handset).pipe(
map(({ matches }) => {
if (matches) {
return [
{ title: 'Card 1', cols: 1, rows: 1 },
{ title: 'Card 2', cols: 1, rows: 1 },
{ title: 'Card 3', cols: 1, rows: 1 },
{ title: 'Card 4', cols: 1, rows: 1 }
];
}
return [
{ title: 'Card 1', cols: 2, rows: 1 },
{ title: 'Card 2', cols: 1, rows: 1 },
{ title: 'Card 3', cols: 1, rows: 2 },
{ title: 'Card 4', cols: 1, rows: 1 }
];
})
);
}

View File

@@ -0,0 +1,369 @@
// @generated by protoc-gen-es v1.9.0 with parameter "target=ts"
// @generated from file holos/object/v1alpha1/object.proto (package holos.object.v1alpha1, syntax proto3)
/* eslint-disable */
// @ts-nocheck
import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf";
import { Message, proto3, Struct, Timestamp } from "@bufbuild/protobuf";
/**
* @generated from message holos.object.v1alpha1.Detail
*/
export class Detail extends Message<Detail> {
/**
* Created by entity
*
* @generated from field: optional holos.object.v1alpha1.ResourceEditor created_by = 1;
*/
createdBy?: ResourceEditor;
/**
* Created at timestamp
*
* @generated from field: google.protobuf.Timestamp created_at = 2;
*/
createdAt?: Timestamp;
/**
* Updated by entity
*
* @generated from field: optional holos.object.v1alpha1.ResourceEditor updated_by = 3;
*/
updatedBy?: ResourceEditor;
/**
* Updated at timestamp
*
* @generated from field: google.protobuf.Timestamp updated_at = 4;
*/
updatedAt?: Timestamp;
constructor(data?: PartialMessage<Detail>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.object.v1alpha1.Detail";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "created_by", kind: "message", T: ResourceEditor, opt: true },
{ no: 2, name: "created_at", kind: "message", T: Timestamp },
{ no: 3, name: "updated_by", kind: "message", T: ResourceEditor, opt: true },
{ no: 4, name: "updated_at", kind: "message", T: Timestamp },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): Detail {
return new Detail().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): Detail {
return new Detail().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): Detail {
return new Detail().fromJsonString(jsonString, options);
}
static equals(a: Detail | PlainMessage<Detail> | undefined, b: Detail | PlainMessage<Detail> | undefined): boolean {
return proto3.util.equals(Detail, a, b);
}
}
/**
* Subject represents the oidc iss and sub claims which uniquely identify a subject.
*
* @generated from message holos.object.v1alpha1.Subject
*/
export class Subject extends Message<Subject> {
/**
* iss represents the oidc id token iss claim. Limits defined at
* https://openid.net/specs/openid-authentication-1_1.html#limits
*
* @generated from field: string iss = 1;
*/
iss = "";
/**
* sub represents the oidc id token sub claim.
*
* @generated from field: string sub = 2;
*/
sub = "";
constructor(data?: PartialMessage<Subject>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.object.v1alpha1.Subject";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "iss", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 2, name: "sub", kind: "scalar", T: 9 /* ScalarType.STRING */ },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): Subject {
return new Subject().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): Subject {
return new Subject().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): Subject {
return new Subject().fromJsonString(jsonString, options);
}
static equals(a: Subject | PlainMessage<Subject> | undefined, b: Subject | PlainMessage<Subject> | undefined): boolean {
return proto3.util.equals(Subject, a, b);
}
}
/**
* UserRef refers to a User by uuid, email, or by the oidc iss and sub claims.
*
* @generated from message holos.object.v1alpha1.UserRef
*/
export class UserRef extends Message<UserRef> {
/**
* @generated from oneof holos.object.v1alpha1.UserRef.user
*/
user: {
/**
* @generated from field: string user_id = 1;
*/
value: string;
case: "userId";
} | {
/**
* @generated from field: string email = 2;
*/
value: string;
case: "email";
} | {
/**
* @generated from field: holos.object.v1alpha1.Subject subject = 3;
*/
value: Subject;
case: "subject";
} | { case: undefined; value?: undefined } = { case: undefined };
constructor(data?: PartialMessage<UserRef>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.object.v1alpha1.UserRef";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "user_id", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "user" },
{ no: 2, name: "email", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "user" },
{ no: 3, name: "subject", kind: "message", T: Subject, oneof: "user" },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): UserRef {
return new UserRef().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): UserRef {
return new UserRef().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): UserRef {
return new UserRef().fromJsonString(jsonString, options);
}
static equals(a: UserRef | PlainMessage<UserRef> | undefined, b: UserRef | PlainMessage<UserRef> | undefined): boolean {
return proto3.util.equals(UserRef, a, b);
}
}
/**
* Organization represents the ways in which a organization may be uniquely identified in the system.
*
* @generated from message holos.object.v1alpha1.OrganizationRef
*/
export class OrganizationRef extends Message<OrganizationRef> {
/**
* @generated from oneof holos.object.v1alpha1.OrganizationRef.org
*/
org: {
/**
* @generated from field: string org_id = 1;
*/
value: string;
case: "orgId";
} | {
/**
* @generated from field: string org_name = 2;
*/
value: string;
case: "orgName";
} | { case: undefined; value?: undefined } = { case: undefined };
constructor(data?: PartialMessage<OrganizationRef>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.object.v1alpha1.OrganizationRef";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "org_id", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "org" },
{ no: 2, name: "org_name", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "org" },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): OrganizationRef {
return new OrganizationRef().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): OrganizationRef {
return new OrganizationRef().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): OrganizationRef {
return new OrganizationRef().fromJsonString(jsonString, options);
}
static equals(a: OrganizationRef | PlainMessage<OrganizationRef> | undefined, b: OrganizationRef | PlainMessage<OrganizationRef> | undefined): boolean {
return proto3.util.equals(OrganizationRef, a, b);
}
}
/**
* ResourceEditor represents the entity that most recently created or edited a resource.
*
* @generated from message holos.object.v1alpha1.ResourceEditor
*/
export class ResourceEditor extends Message<ResourceEditor> {
/**
* @generated from oneof holos.object.v1alpha1.ResourceEditor.editor
*/
editor: {
/**
* @generated from field: string user_id = 1;
*/
value: string;
case: "userId";
} | { case: undefined; value?: undefined } = { case: undefined };
constructor(data?: PartialMessage<ResourceEditor>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.object.v1alpha1.ResourceEditor";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "user_id", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "editor" },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): ResourceEditor {
return new ResourceEditor().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): ResourceEditor {
return new ResourceEditor().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): ResourceEditor {
return new ResourceEditor().fromJsonString(jsonString, options);
}
static equals(a: ResourceEditor | PlainMessage<ResourceEditor> | undefined, b: ResourceEditor | PlainMessage<ResourceEditor> | undefined): boolean {
return proto3.util.equals(ResourceEditor, a, b);
}
}
/**
* @generated from message holos.object.v1alpha1.ResourceOwner
*/
export class ResourceOwner extends Message<ResourceOwner> {
/**
* @generated from oneof holos.object.v1alpha1.ResourceOwner.resource_owner
*/
resourceOwner: {
/**
* @generated from field: string org_id = 1;
*/
value: string;
case: "orgId";
} | {
/**
* @generated from field: string user_id = 2;
*/
value: string;
case: "userId";
} | { case: undefined; value?: undefined } = { case: undefined };
constructor(data?: PartialMessage<ResourceOwner>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.object.v1alpha1.ResourceOwner";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "org_id", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "resource_owner" },
{ no: 2, name: "user_id", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "resource_owner" },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): ResourceOwner {
return new ResourceOwner().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): ResourceOwner {
return new ResourceOwner().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): ResourceOwner {
return new ResourceOwner().fromJsonString(jsonString, options);
}
static equals(a: ResourceOwner | PlainMessage<ResourceOwner> | undefined, b: ResourceOwner | PlainMessage<ResourceOwner> | undefined): boolean {
return proto3.util.equals(ResourceOwner, a, b);
}
}
/**
* Form represents a Formly json powered form.
*
* @generated from message holos.object.v1alpha1.Form
*/
export class Form extends Message<Form> {
/**
* fields represents FormlyFieldConfig[] encoded as an array of JSON objects
* organized by section.
*
* @generated from field: repeated google.protobuf.Struct field_configs = 1;
*/
fieldConfigs: Struct[] = [];
constructor(data?: PartialMessage<Form>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.object.v1alpha1.Form";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "field_configs", kind: "message", T: Struct, repeated: true },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): Form {
return new Form().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): Form {
return new Form().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): Form {
return new Form().fromJsonString(jsonString, options);
}
static equals(a: Form | PlainMessage<Form> | undefined, b: Form | PlainMessage<Form> | undefined): boolean {
return proto3.util.equals(Form, a, b);
}
}

View File

@@ -0,0 +1,68 @@
// @generated by protoc-gen-es v1.9.0 with parameter "target=ts"
// @generated from file holos/organization/v1alpha1/organization.proto (package holos.organization.v1alpha1, syntax proto3)
/* eslint-disable */
// @ts-nocheck
import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf";
import { Message, proto3 } from "@bufbuild/protobuf";
import { Detail } from "../../object/v1alpha1/object_pb.js";
/**
* @generated from message holos.organization.v1alpha1.Organization
*/
export class Organization extends Message<Organization> {
/**
* Unique id assigned by the server.
*
* @generated from field: optional string org_id = 1;
*/
orgId?: string;
/**
* Name is the organization name as a dns label.
*
* @generated from field: string name = 2;
*/
name = "";
/**
* @generated from field: optional string display_name = 3;
*/
displayName?: string;
/**
* @generated from field: optional holos.object.v1alpha1.Detail detail = 4;
*/
detail?: Detail;
constructor(data?: PartialMessage<Organization>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.organization.v1alpha1.Organization";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "org_id", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
{ no: 2, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 3, name: "display_name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
{ no: 4, name: "detail", kind: "message", T: Detail, opt: true },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): Organization {
return new Organization().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): Organization {
return new Organization().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): Organization {
return new Organization().fromJsonString(jsonString, options);
}
static equals(a: Organization | PlainMessage<Organization> | undefined, b: Organization | PlainMessage<Organization> | undefined): boolean {
return proto3.util.equals(Organization, a, b);
}
}

View File

@@ -0,0 +1,35 @@
// @generated by protoc-gen-connect-es v1.4.0 with parameter "target=ts"
// @generated from file holos/organization/v1alpha1/organization_service.proto (package holos.organization.v1alpha1, syntax proto3)
/* eslint-disable */
// @ts-nocheck
import { CreateOrganizationRequest, CreateOrganizationResponse, ListOrganizationsRequest, ListOrganizationsResponse } from "./organization_service_pb.js";
import { MethodKind } from "@bufbuild/protobuf";
/**
* @generated from service holos.organization.v1alpha1.OrganizationService
*/
export const OrganizationService = {
typeName: "holos.organization.v1alpha1.OrganizationService",
methods: {
/**
* @generated from rpc holos.organization.v1alpha1.OrganizationService.CreateOrganization
*/
createOrganization: {
name: "CreateOrganization",
I: CreateOrganizationRequest,
O: CreateOrganizationResponse,
kind: MethodKind.Unary,
},
/**
* @generated from rpc holos.organization.v1alpha1.OrganizationService.ListOrganizations
*/
listOrganizations: {
name: "ListOrganizations",
I: ListOrganizationsRequest,
O: ListOrganizationsResponse,
kind: MethodKind.Unary,
},
}
} as const;

View File

@@ -0,0 +1,164 @@
// @generated by protoc-gen-es v1.9.0 with parameter "target=ts"
// @generated from file holos/organization/v1alpha1/organization_service.proto (package holos.organization.v1alpha1, syntax proto3)
/* eslint-disable */
// @ts-nocheck
import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf";
import { FieldMask, Message, proto3 } from "@bufbuild/protobuf";
import { Organization } from "./organization_pb.js";
import { UserRef } from "../../object/v1alpha1/object_pb.js";
/**
* @generated from message holos.organization.v1alpha1.CreateOrganizationRequest
*/
export class CreateOrganizationRequest extends Message<CreateOrganizationRequest> {
/**
* @generated from field: holos.organization.v1alpha1.Organization organization = 1;
*/
organization?: Organization;
constructor(data?: PartialMessage<CreateOrganizationRequest>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.organization.v1alpha1.CreateOrganizationRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "organization", kind: "message", T: Organization },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): CreateOrganizationRequest {
return new CreateOrganizationRequest().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): CreateOrganizationRequest {
return new CreateOrganizationRequest().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): CreateOrganizationRequest {
return new CreateOrganizationRequest().fromJsonString(jsonString, options);
}
static equals(a: CreateOrganizationRequest | PlainMessage<CreateOrganizationRequest> | undefined, b: CreateOrganizationRequest | PlainMessage<CreateOrganizationRequest> | undefined): boolean {
return proto3.util.equals(CreateOrganizationRequest, a, b);
}
}
/**
* @generated from message holos.organization.v1alpha1.CreateOrganizationResponse
*/
export class CreateOrganizationResponse extends Message<CreateOrganizationResponse> {
/**
* @generated from field: holos.organization.v1alpha1.Organization organization = 1;
*/
organization?: Organization;
constructor(data?: PartialMessage<CreateOrganizationResponse>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.organization.v1alpha1.CreateOrganizationResponse";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "organization", kind: "message", T: Organization },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): CreateOrganizationResponse {
return new CreateOrganizationResponse().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): CreateOrganizationResponse {
return new CreateOrganizationResponse().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): CreateOrganizationResponse {
return new CreateOrganizationResponse().fromJsonString(jsonString, options);
}
static equals(a: CreateOrganizationResponse | PlainMessage<CreateOrganizationResponse> | undefined, b: CreateOrganizationResponse | PlainMessage<CreateOrganizationResponse> | undefined): boolean {
return proto3.util.equals(CreateOrganizationResponse, a, b);
}
}
/**
* @generated from message holos.organization.v1alpha1.ListOrganizationsRequest
*/
export class ListOrganizationsRequest extends Message<ListOrganizationsRequest> {
/**
* @generated from field: google.protobuf.FieldMask field_mask = 1;
*/
fieldMask?: FieldMask;
constructor(data?: PartialMessage<ListOrganizationsRequest>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.organization.v1alpha1.ListOrganizationsRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "field_mask", kind: "message", T: FieldMask },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): ListOrganizationsRequest {
return new ListOrganizationsRequest().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): ListOrganizationsRequest {
return new ListOrganizationsRequest().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): ListOrganizationsRequest {
return new ListOrganizationsRequest().fromJsonString(jsonString, options);
}
static equals(a: ListOrganizationsRequest | PlainMessage<ListOrganizationsRequest> | undefined, b: ListOrganizationsRequest | PlainMessage<ListOrganizationsRequest> | undefined): boolean {
return proto3.util.equals(ListOrganizationsRequest, a, b);
}
}
/**
* @generated from message holos.organization.v1alpha1.ListOrganizationsResponse
*/
export class ListOrganizationsResponse extends Message<ListOrganizationsResponse> {
/**
* @generated from field: optional holos.object.v1alpha1.UserRef user = 1;
*/
user?: UserRef;
/**
* @generated from field: repeated holos.organization.v1alpha1.Organization organizations = 2;
*/
organizations: Organization[] = [];
constructor(data?: PartialMessage<ListOrganizationsResponse>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.organization.v1alpha1.ListOrganizationsResponse";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "user", kind: "message", T: UserRef, opt: true },
{ no: 2, name: "organizations", kind: "message", T: Organization, repeated: true },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): ListOrganizationsResponse {
return new ListOrganizationsResponse().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): ListOrganizationsResponse {
return new ListOrganizationsResponse().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): ListOrganizationsResponse {
return new ListOrganizationsResponse().fromJsonString(jsonString, options);
}
static equals(a: ListOrganizationsResponse | PlainMessage<ListOrganizationsResponse> | undefined, b: ListOrganizationsResponse | PlainMessage<ListOrganizationsResponse> | undefined): boolean {
return proto3.util.equals(ListOrganizationsResponse, a, b);
}
}

View File

@@ -0,0 +1,182 @@
// @generated by protoc-gen-es v1.9.0 with parameter "target=ts"
// @generated from file holos/platform/v1alpha1/platform.proto (package holos.platform.v1alpha1, syntax proto3)
/* eslint-disable */
// @ts-nocheck
import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf";
import { Message, proto3, Struct } from "@bufbuild/protobuf";
import { Detail, Form } from "../../object/v1alpha1/object_pb.js";
/**
* @generated from message holos.platform.v1alpha1.Platform
*/
export class Platform extends Message<Platform> {
/**
* Unique id assigned by the server.
*
* @generated from field: string id = 1;
*/
id = "";
/**
* Owner of the platform.
*
* @generated from field: holos.platform.v1alpha1.Owner owner = 2;
*/
owner?: Owner;
/**
* name is the platform short name as a dns label.
*
* @generated from field: string name = 3;
*/
name = "";
/**
* @generated from field: optional string display_name = 4;
*/
displayName?: string;
/**
* @generated from field: optional string description = 5;
*/
description?: string;
/**
* @generated from field: optional holos.platform.v1alpha1.Spec spec = 6;
*/
spec?: Spec;
/**
* @generated from field: optional holos.object.v1alpha1.Detail detail = 8;
*/
detail?: Detail;
constructor(data?: PartialMessage<Platform>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.platform.v1alpha1.Platform";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 2, name: "owner", kind: "message", T: Owner },
{ no: 3, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 4, name: "display_name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
{ no: 5, name: "description", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
{ no: 6, name: "spec", kind: "message", T: Spec, opt: true },
{ no: 8, name: "detail", kind: "message", T: Detail, opt: true },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): Platform {
return new Platform().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): Platform {
return new Platform().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): Platform {
return new Platform().fromJsonString(jsonString, options);
}
static equals(a: Platform | PlainMessage<Platform> | undefined, b: Platform | PlainMessage<Platform> | undefined): boolean {
return proto3.util.equals(Platform, a, b);
}
}
/**
* Owner of a platform.
*
* @generated from message holos.platform.v1alpha1.Owner
*/
export class Owner extends Message<Owner> {
/**
* @generated from oneof holos.platform.v1alpha1.Owner.owner
*/
owner: {
/**
* @generated from field: string org_id = 1;
*/
value: string;
case: "orgId";
} | { case: undefined; value?: undefined } = { case: undefined };
constructor(data?: PartialMessage<Owner>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.platform.v1alpha1.Owner";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "org_id", kind: "scalar", T: 9 /* ScalarType.STRING */, oneof: "owner" },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): Owner {
return new Owner().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): Owner {
return new Owner().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): Owner {
return new Owner().fromJsonString(jsonString, options);
}
static equals(a: Owner | PlainMessage<Owner> | undefined, b: Owner | PlainMessage<Owner> | undefined): boolean {
return proto3.util.equals(Owner, a, b);
}
}
/**
* Spec represents the top level specification of a Platform.
*
* @generated from message holos.platform.v1alpha1.Spec
*/
export class Spec extends Message<Spec> {
/**
* model represents the user-defined and user-supplied form field values.
* The model is a Struct to ensure any valid JSON object defined by the user
* via the form can be represented and stored.
*
* @generated from field: google.protobuf.Struct model = 1;
*/
model?: Struct;
/**
* @generated from field: optional holos.object.v1alpha1.Form form = 2;
*/
form?: Form;
constructor(data?: PartialMessage<Spec>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.platform.v1alpha1.Spec";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "model", kind: "message", T: Struct },
{ no: 2, name: "form", kind: "message", T: Form, opt: true },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): Spec {
return new Spec().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): Spec {
return new Spec().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): Spec {
return new Spec().fromJsonString(jsonString, options);
}
static equals(a: Spec | PlainMessage<Spec> | undefined, b: Spec | PlainMessage<Spec> | undefined): boolean {
return proto3.util.equals(Spec, a, b);
}
}

View File

@@ -0,0 +1,53 @@
// @generated by protoc-gen-connect-es v1.4.0 with parameter "target=ts"
// @generated from file holos/platform/v1alpha1/platform_service.proto (package holos.platform.v1alpha1, syntax proto3)
/* eslint-disable */
// @ts-nocheck
import { CreatePlatformRequest, CreatePlatformResponse, GetPlatformRequest, GetPlatformResponse, ListPlatformsRequest, ListPlatformsResponse, UpdatePlatformRequest, UpdatePlatformResponse } from "./platform_service_pb.js";
import { MethodKind } from "@bufbuild/protobuf";
/**
* @generated from service holos.platform.v1alpha1.PlatformService
*/
export const PlatformService = {
typeName: "holos.platform.v1alpha1.PlatformService",
methods: {
/**
* @generated from rpc holos.platform.v1alpha1.PlatformService.CreatePlatform
*/
createPlatform: {
name: "CreatePlatform",
I: CreatePlatformRequest,
O: CreatePlatformResponse,
kind: MethodKind.Unary,
},
/**
* @generated from rpc holos.platform.v1alpha1.PlatformService.GetPlatform
*/
getPlatform: {
name: "GetPlatform",
I: GetPlatformRequest,
O: GetPlatformResponse,
kind: MethodKind.Unary,
},
/**
* @generated from rpc holos.platform.v1alpha1.PlatformService.UpdatePlatform
*/
updatePlatform: {
name: "UpdatePlatform",
I: UpdatePlatformRequest,
O: UpdatePlatformResponse,
kind: MethodKind.Unary,
},
/**
* @generated from rpc holos.platform.v1alpha1.PlatformService.ListPlatforms
*/
listPlatforms: {
name: "ListPlatforms",
I: ListPlatformsRequest,
O: ListPlatformsResponse,
kind: MethodKind.Unary,
},
}
} as const;

View File

@@ -0,0 +1,406 @@
// @generated by protoc-gen-es v1.9.0 with parameter "target=ts"
// @generated from file holos/platform/v1alpha1/platform_service.proto (package holos.platform.v1alpha1, syntax proto3)
/* eslint-disable */
// @ts-nocheck
import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf";
import { FieldMask, Message, proto3, Struct } from "@bufbuild/protobuf";
import { Platform } from "./platform_pb.js";
import { Form } from "../../object/v1alpha1/object_pb.js";
/**
* @generated from message holos.platform.v1alpha1.CreatePlatformRequest
*/
export class CreatePlatformRequest extends Message<CreatePlatformRequest> {
/**
* @generated from field: holos.platform.v1alpha1.Platform platform = 1;
*/
platform?: Platform;
constructor(data?: PartialMessage<CreatePlatformRequest>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.platform.v1alpha1.CreatePlatformRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "platform", kind: "message", T: Platform },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): CreatePlatformRequest {
return new CreatePlatformRequest().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): CreatePlatformRequest {
return new CreatePlatformRequest().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): CreatePlatformRequest {
return new CreatePlatformRequest().fromJsonString(jsonString, options);
}
static equals(a: CreatePlatformRequest | PlainMessage<CreatePlatformRequest> | undefined, b: CreatePlatformRequest | PlainMessage<CreatePlatformRequest> | undefined): boolean {
return proto3.util.equals(CreatePlatformRequest, a, b);
}
}
/**
* @generated from message holos.platform.v1alpha1.CreatePlatformResponse
*/
export class CreatePlatformResponse extends Message<CreatePlatformResponse> {
/**
* @generated from field: holos.platform.v1alpha1.Platform platform = 1;
*/
platform?: Platform;
constructor(data?: PartialMessage<CreatePlatformResponse>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.platform.v1alpha1.CreatePlatformResponse";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "platform", kind: "message", T: Platform },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): CreatePlatformResponse {
return new CreatePlatformResponse().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): CreatePlatformResponse {
return new CreatePlatformResponse().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): CreatePlatformResponse {
return new CreatePlatformResponse().fromJsonString(jsonString, options);
}
static equals(a: CreatePlatformResponse | PlainMessage<CreatePlatformResponse> | undefined, b: CreatePlatformResponse | PlainMessage<CreatePlatformResponse> | undefined): boolean {
return proto3.util.equals(CreatePlatformResponse, a, b);
}
}
/**
* @generated from message holos.platform.v1alpha1.GetPlatformRequest
*/
export class GetPlatformRequest extends Message<GetPlatformRequest> {
/**
* @generated from field: string platform_id = 1;
*/
platformId = "";
/**
* FieldMask represents the response Platform fields to include.
*
* @generated from field: google.protobuf.FieldMask field_mask = 2;
*/
fieldMask?: FieldMask;
constructor(data?: PartialMessage<GetPlatformRequest>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.platform.v1alpha1.GetPlatformRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "platform_id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 2, name: "field_mask", kind: "message", T: FieldMask },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): GetPlatformRequest {
return new GetPlatformRequest().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): GetPlatformRequest {
return new GetPlatformRequest().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): GetPlatformRequest {
return new GetPlatformRequest().fromJsonString(jsonString, options);
}
static equals(a: GetPlatformRequest | PlainMessage<GetPlatformRequest> | undefined, b: GetPlatformRequest | PlainMessage<GetPlatformRequest> | undefined): boolean {
return proto3.util.equals(GetPlatformRequest, a, b);
}
}
/**
* @generated from message holos.platform.v1alpha1.GetPlatformResponse
*/
export class GetPlatformResponse extends Message<GetPlatformResponse> {
/**
* @generated from field: holos.platform.v1alpha1.Platform platform = 1;
*/
platform?: Platform;
constructor(data?: PartialMessage<GetPlatformResponse>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.platform.v1alpha1.GetPlatformResponse";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "platform", kind: "message", T: Platform },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): GetPlatformResponse {
return new GetPlatformResponse().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): GetPlatformResponse {
return new GetPlatformResponse().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): GetPlatformResponse {
return new GetPlatformResponse().fromJsonString(jsonString, options);
}
static equals(a: GetPlatformResponse | PlainMessage<GetPlatformResponse> | undefined, b: GetPlatformResponse | PlainMessage<GetPlatformResponse> | undefined): boolean {
return proto3.util.equals(GetPlatformResponse, a, b);
}
}
/**
* @generated from message holos.platform.v1alpha1.UpdatePlatformRequest
*/
export class UpdatePlatformRequest extends Message<UpdatePlatformRequest> {
/**
* Update operations to perform. Fields are set to the provided value if
* selected by the mask. Absent fields are cleared if they are selected by
* the mask.
*
* @generated from field: holos.platform.v1alpha1.UpdatePlatformOperation update = 1;
*/
update?: UpdatePlatformOperation;
/**
* FieldMask represents the mutation operations to perform. Marked optional
* for the nil guard check. Required.
*
* @generated from field: optional google.protobuf.FieldMask update_mask = 2;
*/
updateMask?: FieldMask;
constructor(data?: PartialMessage<UpdatePlatformRequest>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.platform.v1alpha1.UpdatePlatformRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "update", kind: "message", T: UpdatePlatformOperation },
{ no: 2, name: "update_mask", kind: "message", T: FieldMask, opt: true },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): UpdatePlatformRequest {
return new UpdatePlatformRequest().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): UpdatePlatformRequest {
return new UpdatePlatformRequest().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): UpdatePlatformRequest {
return new UpdatePlatformRequest().fromJsonString(jsonString, options);
}
static equals(a: UpdatePlatformRequest | PlainMessage<UpdatePlatformRequest> | undefined, b: UpdatePlatformRequest | PlainMessage<UpdatePlatformRequest> | undefined): boolean {
return proto3.util.equals(UpdatePlatformRequest, a, b);
}
}
/**
* @generated from message holos.platform.v1alpha1.UpdatePlatformResponse
*/
export class UpdatePlatformResponse extends Message<UpdatePlatformResponse> {
/**
* @generated from field: holos.platform.v1alpha1.Platform platform = 1;
*/
platform?: Platform;
constructor(data?: PartialMessage<UpdatePlatformResponse>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.platform.v1alpha1.UpdatePlatformResponse";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "platform", kind: "message", T: Platform },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): UpdatePlatformResponse {
return new UpdatePlatformResponse().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): UpdatePlatformResponse {
return new UpdatePlatformResponse().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): UpdatePlatformResponse {
return new UpdatePlatformResponse().fromJsonString(jsonString, options);
}
static equals(a: UpdatePlatformResponse | PlainMessage<UpdatePlatformResponse> | undefined, b: UpdatePlatformResponse | PlainMessage<UpdatePlatformResponse> | undefined): boolean {
return proto3.util.equals(UpdatePlatformResponse, a, b);
}
}
/**
* @generated from message holos.platform.v1alpha1.ListPlatformsRequest
*/
export class ListPlatformsRequest extends Message<ListPlatformsRequest> {
/**
* @generated from field: string org_id = 1;
*/
orgId = "";
/**
* FieldMask represents the response Platform fields to include.
*
* @generated from field: google.protobuf.FieldMask field_mask = 2;
*/
fieldMask?: FieldMask;
constructor(data?: PartialMessage<ListPlatformsRequest>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.platform.v1alpha1.ListPlatformsRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "org_id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 2, name: "field_mask", kind: "message", T: FieldMask },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): ListPlatformsRequest {
return new ListPlatformsRequest().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): ListPlatformsRequest {
return new ListPlatformsRequest().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): ListPlatformsRequest {
return new ListPlatformsRequest().fromJsonString(jsonString, options);
}
static equals(a: ListPlatformsRequest | PlainMessage<ListPlatformsRequest> | undefined, b: ListPlatformsRequest | PlainMessage<ListPlatformsRequest> | undefined): boolean {
return proto3.util.equals(ListPlatformsRequest, a, b);
}
}
/**
* @generated from message holos.platform.v1alpha1.ListPlatformsResponse
*/
export class ListPlatformsResponse extends Message<ListPlatformsResponse> {
/**
* @generated from field: repeated holos.platform.v1alpha1.Platform platforms = 1;
*/
platforms: Platform[] = [];
constructor(data?: PartialMessage<ListPlatformsResponse>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.platform.v1alpha1.ListPlatformsResponse";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "platforms", kind: "message", T: Platform, repeated: true },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): ListPlatformsResponse {
return new ListPlatformsResponse().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): ListPlatformsResponse {
return new ListPlatformsResponse().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): ListPlatformsResponse {
return new ListPlatformsResponse().fromJsonString(jsonString, options);
}
static equals(a: ListPlatformsResponse | PlainMessage<ListPlatformsResponse> | undefined, b: ListPlatformsResponse | PlainMessage<ListPlatformsResponse> | undefined): boolean {
return proto3.util.equals(ListPlatformsResponse, a, b);
}
}
/**
* @generated from message holos.platform.v1alpha1.UpdatePlatformOperation
*/
export class UpdatePlatformOperation extends Message<UpdatePlatformOperation> {
/**
* Platform UUID to update.
*
* @generated from field: string platform_id = 1;
*/
platformId = "";
/**
* Update the platform name.
*
* @generated from field: optional string name = 2;
*/
name?: string;
/**
* Update the platform display name.
*
* @generated from field: optional string display_name = 3;
*/
displayName?: string;
/**
* Replace the form model.
*
* @generated from field: optional google.protobuf.Struct model = 4;
*/
model?: Struct;
/**
* Replace the form.
*
* @generated from field: optional holos.object.v1alpha1.Form form = 5;
*/
form?: Form;
constructor(data?: PartialMessage<UpdatePlatformOperation>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.platform.v1alpha1.UpdatePlatformOperation";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "platform_id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 2, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
{ no: 3, name: "display_name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
{ no: 4, name: "model", kind: "message", T: Struct, opt: true },
{ no: 5, name: "form", kind: "message", T: Form, opt: true },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): UpdatePlatformOperation {
return new UpdatePlatformOperation().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): UpdatePlatformOperation {
return new UpdatePlatformOperation().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): UpdatePlatformOperation {
return new UpdatePlatformOperation().fromJsonString(jsonString, options);
}
static equals(a: UpdatePlatformOperation | PlainMessage<UpdatePlatformOperation> | undefined, b: UpdatePlatformOperation | PlainMessage<UpdatePlatformOperation> | undefined): boolean {
return proto3.util.equals(UpdatePlatformOperation, a, b);
}
}

View File

@@ -0,0 +1,91 @@
// @generated by protoc-gen-es v1.9.0 with parameter "target=ts"
// @generated from file holos/storage/v1alpha1/storage.proto (package holos.storage.v1alpha1, syntax proto3)
/* eslint-disable */
// @ts-nocheck
import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf";
import { Message, proto3, Struct } from "@bufbuild/protobuf";
/**
* Model represents user-defined and user-supplied form field values stored as a
* marshaled JSON object. The model is a Struct to ensure any valid JSON object
* defined by the user via the form can be represented and stored.
*
* @generated from message holos.storage.v1alpha1.Model
*/
export class Model extends Message<Model> {
/**
* @generated from field: google.protobuf.Struct model = 1;
*/
model?: Struct;
constructor(data?: PartialMessage<Model>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.storage.v1alpha1.Model";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "model", kind: "message", T: Struct },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): Model {
return new Model().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): Model {
return new Model().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): Model {
return new Model().fromJsonString(jsonString, options);
}
static equals(a: Model | PlainMessage<Model> | undefined, b: Model | PlainMessage<Model> | undefined): boolean {
return proto3.util.equals(Model, a, b);
}
}
/**
* Form represents the Formly input form stored as a marshaled JSON object.
*
* @generated from message holos.storage.v1alpha1.Form
*/
export class Form extends Message<Form> {
/**
* fields represents FormlyFieldConfig[] encoded as an array of JSON objects
* organized by section.
*
* @generated from field: repeated google.protobuf.Struct field_configs = 1;
*/
fieldConfigs: Struct[] = [];
constructor(data?: PartialMessage<Form>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.storage.v1alpha1.Form";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "field_configs", kind: "message", T: Struct, repeated: true },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): Form {
return new Form().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): Form {
return new Form().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): Form {
return new Form().fromJsonString(jsonString, options);
}
static equals(a: Form | PlainMessage<Form> | undefined, b: Form | PlainMessage<Form> | undefined): boolean {
return proto3.util.equals(Form, a, b);
}
}

View File

@@ -0,0 +1,81 @@
// @generated by protoc-gen-es v1.9.0 with parameter "target=ts"
// @generated from file holos/system/v1alpha1/system.proto (package holos.system.v1alpha1, syntax proto3)
/* eslint-disable */
// @ts-nocheck
import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf";
import { Message, proto3 } from "@bufbuild/protobuf";
/**
* @generated from message holos.system.v1alpha1.Version
*/
export class Version extends Message<Version> {
/**
* @generated from field: string version = 1;
*/
version = "";
/**
* @generated from field: string git_commit = 2;
*/
gitCommit = "";
/**
* @generated from field: string git_tree_state = 3;
*/
gitTreeState = "";
/**
* @generated from field: string go_version = 4;
*/
goVersion = "";
/**
* @generated from field: string build_date = 5;
*/
buildDate = "";
/**
* @generated from field: string os = 6;
*/
os = "";
/**
* @generated from field: string arch = 7;
*/
arch = "";
constructor(data?: PartialMessage<Version>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.system.v1alpha1.Version";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "version", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 2, name: "git_commit", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 3, name: "git_tree_state", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 4, name: "go_version", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 5, name: "build_date", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 6, name: "os", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 7, name: "arch", kind: "scalar", T: 9 /* ScalarType.STRING */ },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): Version {
return new Version().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): Version {
return new Version().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): Version {
return new Version().fromJsonString(jsonString, options);
}
static equals(a: Version | PlainMessage<Version> | undefined, b: Version | PlainMessage<Version> | undefined): boolean {
return proto3.util.equals(Version, a, b);
}
}

View File

@@ -0,0 +1,44 @@
// @generated by protoc-gen-connect-es v1.4.0 with parameter "target=ts"
// @generated from file holos/system/v1alpha1/system_service.proto (package holos.system.v1alpha1, syntax proto3)
/* eslint-disable */
// @ts-nocheck
import { DropTablesRequest, DropTablesResponse, GetVersionRequest, GetVersionResponse, SeedDatabaseRequest, SeedDatabaseResponse } from "./system_service_pb.js";
import { MethodKind } from "@bufbuild/protobuf";
/**
* @generated from service holos.system.v1alpha1.SystemService
*/
export const SystemService = {
typeName: "holos.system.v1alpha1.SystemService",
methods: {
/**
* @generated from rpc holos.system.v1alpha1.SystemService.GetVersion
*/
getVersion: {
name: "GetVersion",
I: GetVersionRequest,
O: GetVersionResponse,
kind: MethodKind.Unary,
},
/**
* @generated from rpc holos.system.v1alpha1.SystemService.DropTables
*/
dropTables: {
name: "DropTables",
I: DropTablesRequest,
O: DropTablesResponse,
kind: MethodKind.Unary,
},
/**
* @generated from rpc holos.system.v1alpha1.SystemService.SeedDatabase
*/
seedDatabase: {
name: "SeedDatabase",
I: SeedDatabaseRequest,
O: SeedDatabaseResponse,
kind: MethodKind.Unary,
},
}
} as const;

View File

@@ -0,0 +1,209 @@
// @generated by protoc-gen-es v1.9.0 with parameter "target=ts"
// @generated from file holos/system/v1alpha1/system_service.proto (package holos.system.v1alpha1, syntax proto3)
/* eslint-disable */
// @ts-nocheck
import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf";
import { FieldMask, Message, proto3 } from "@bufbuild/protobuf";
import { Version } from "./system_pb.js";
/**
* @generated from message holos.system.v1alpha1.GetVersionRequest
*/
export class GetVersionRequest extends Message<GetVersionRequest> {
/**
* FieldMask represents the fields to include in the response.
*
* @generated from field: google.protobuf.FieldMask field_mask = 1;
*/
fieldMask?: FieldMask;
constructor(data?: PartialMessage<GetVersionRequest>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.system.v1alpha1.GetVersionRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "field_mask", kind: "message", T: FieldMask },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): GetVersionRequest {
return new GetVersionRequest().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): GetVersionRequest {
return new GetVersionRequest().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): GetVersionRequest {
return new GetVersionRequest().fromJsonString(jsonString, options);
}
static equals(a: GetVersionRequest | PlainMessage<GetVersionRequest> | undefined, b: GetVersionRequest | PlainMessage<GetVersionRequest> | undefined): boolean {
return proto3.util.equals(GetVersionRequest, a, b);
}
}
/**
* @generated from message holos.system.v1alpha1.GetVersionResponse
*/
export class GetVersionResponse extends Message<GetVersionResponse> {
/**
* @generated from field: holos.system.v1alpha1.Version version = 1;
*/
version?: Version;
constructor(data?: PartialMessage<GetVersionResponse>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.system.v1alpha1.GetVersionResponse";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "version", kind: "message", T: Version },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): GetVersionResponse {
return new GetVersionResponse().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): GetVersionResponse {
return new GetVersionResponse().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): GetVersionResponse {
return new GetVersionResponse().fromJsonString(jsonString, options);
}
static equals(a: GetVersionResponse | PlainMessage<GetVersionResponse> | undefined, b: GetVersionResponse | PlainMessage<GetVersionResponse> | undefined): boolean {
return proto3.util.equals(GetVersionResponse, a, b);
}
}
/**
* @generated from message holos.system.v1alpha1.SeedDatabaseRequest
*/
export class SeedDatabaseRequest extends Message<SeedDatabaseRequest> {
constructor(data?: PartialMessage<SeedDatabaseRequest>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.system.v1alpha1.SeedDatabaseRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): SeedDatabaseRequest {
return new SeedDatabaseRequest().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): SeedDatabaseRequest {
return new SeedDatabaseRequest().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): SeedDatabaseRequest {
return new SeedDatabaseRequest().fromJsonString(jsonString, options);
}
static equals(a: SeedDatabaseRequest | PlainMessage<SeedDatabaseRequest> | undefined, b: SeedDatabaseRequest | PlainMessage<SeedDatabaseRequest> | undefined): boolean {
return proto3.util.equals(SeedDatabaseRequest, a, b);
}
}
/**
* @generated from message holos.system.v1alpha1.SeedDatabaseResponse
*/
export class SeedDatabaseResponse extends Message<SeedDatabaseResponse> {
constructor(data?: PartialMessage<SeedDatabaseResponse>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.system.v1alpha1.SeedDatabaseResponse";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): SeedDatabaseResponse {
return new SeedDatabaseResponse().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): SeedDatabaseResponse {
return new SeedDatabaseResponse().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): SeedDatabaseResponse {
return new SeedDatabaseResponse().fromJsonString(jsonString, options);
}
static equals(a: SeedDatabaseResponse | PlainMessage<SeedDatabaseResponse> | undefined, b: SeedDatabaseResponse | PlainMessage<SeedDatabaseResponse> | undefined): boolean {
return proto3.util.equals(SeedDatabaseResponse, a, b);
}
}
/**
* @generated from message holos.system.v1alpha1.DropTablesRequest
*/
export class DropTablesRequest extends Message<DropTablesRequest> {
constructor(data?: PartialMessage<DropTablesRequest>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.system.v1alpha1.DropTablesRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): DropTablesRequest {
return new DropTablesRequest().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): DropTablesRequest {
return new DropTablesRequest().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): DropTablesRequest {
return new DropTablesRequest().fromJsonString(jsonString, options);
}
static equals(a: DropTablesRequest | PlainMessage<DropTablesRequest> | undefined, b: DropTablesRequest | PlainMessage<DropTablesRequest> | undefined): boolean {
return proto3.util.equals(DropTablesRequest, a, b);
}
}
/**
* @generated from message holos.system.v1alpha1.DropTablesResponse
*/
export class DropTablesResponse extends Message<DropTablesResponse> {
constructor(data?: PartialMessage<DropTablesResponse>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.system.v1alpha1.DropTablesResponse";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): DropTablesResponse {
return new DropTablesResponse().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): DropTablesResponse {
return new DropTablesResponse().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): DropTablesResponse {
return new DropTablesResponse().fromJsonString(jsonString, options);
}
static equals(a: DropTablesResponse | PlainMessage<DropTablesResponse> | undefined, b: DropTablesResponse | PlainMessage<DropTablesResponse> | undefined): boolean {
return proto3.util.equals(DropTablesResponse, a, b);
}
}

View File

@@ -0,0 +1,124 @@
// @generated by protoc-gen-es v1.9.0 with parameter "target=ts"
// @generated from file holos/user/v1alpha1/user.proto (package holos.user.v1alpha1, syntax proto3)
/* eslint-disable */
// @ts-nocheck
import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf";
import { Message, proto3 } from "@bufbuild/protobuf";
import { Detail, Subject } from "../../object/v1alpha1/object_pb.js";
/**
* User represents a human user of the system.
*
* @generated from message holos.user.v1alpha1.User
*/
export class User extends Message<User> {
/**
* Unique uuid assigned by the server.
*
* @generated from field: optional string id = 1;
*/
id?: string;
/**
* Subject represents the oidc iss and sub claims of the user.
*
* @generated from field: optional holos.object.v1alpha1.Subject subject = 2;
*/
subject?: Subject;
/**
* Email address of the user.
*
* @generated from field: string email = 3;
*/
email = "";
/**
* True if the user email has been verified.
*
* @generated from field: optional bool email_verified = 4;
*/
emailVerified?: boolean;
/**
* Full name provided by the user.
*
* @generated from field: optional string name = 5;
*/
name?: string;
/**
* Given or first name of the user.
*
* @generated from field: optional string given_name = 6;
*/
givenName?: string;
/**
* Family or last name of the user.
*
* @generated from field: optional string family_name = 7;
*/
familyName?: string;
/**
* Groups the user is a member of. This field represents the oidc groups
* claim.
*
* @generated from field: repeated string groups = 8;
*/
groups: string[] = [];
/**
* https url to an user avatar profile picture. Should be at least a 200x200 px square image.
*
* @generated from field: optional string picture = 9;
*/
picture?: string;
/**
* Detail applicable to all resource objects in the system such as created and
* updated metadata.
*
* @generated from field: optional holos.object.v1alpha1.Detail detail = 10;
*/
detail?: Detail;
constructor(data?: PartialMessage<User>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.user.v1alpha1.User";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "id", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
{ no: 2, name: "subject", kind: "message", T: Subject, opt: true },
{ no: 3, name: "email", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 4, name: "email_verified", kind: "scalar", T: 8 /* ScalarType.BOOL */, opt: true },
{ no: 5, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
{ no: 6, name: "given_name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
{ no: 7, name: "family_name", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
{ no: 8, name: "groups", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true },
{ no: 9, name: "picture", kind: "scalar", T: 9 /* ScalarType.STRING */, opt: true },
{ no: 10, name: "detail", kind: "message", T: Detail, opt: true },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): User {
return new User().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): User {
return new User().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): User {
return new User().fromJsonString(jsonString, options);
}
static equals(a: User | PlainMessage<User> | undefined, b: User | PlainMessage<User> | undefined): boolean {
return proto3.util.equals(User, a, b);
}
}

View File

@@ -0,0 +1,52 @@
// @generated by protoc-gen-connect-es v1.4.0 with parameter "target=ts"
// @generated from file holos/user/v1alpha1/user_service.proto (package holos.user.v1alpha1, syntax proto3)
/* eslint-disable */
// @ts-nocheck
import { CreateUserRequest, CreateUserResponse, GetUserRequest, GetUserResponse, RegisterUserRequest, RegisterUserResponse } from "./user_service_pb.js";
import { MethodKind } from "@bufbuild/protobuf";
/**
* UserService provides CRUD methods for User resources in the system.
*
* @generated from service holos.user.v1alpha1.UserService
*/
export const UserService = {
typeName: "holos.user.v1alpha1.UserService",
methods: {
/**
* Create a new user from authenticated claims or the provided User resource.
*
* @generated from rpc holos.user.v1alpha1.UserService.CreateUser
*/
createUser: {
name: "CreateUser",
I: CreateUserRequest,
O: CreateUserResponse,
kind: MethodKind.Unary,
},
/**
* Get an existing user by id, email, or subject.
*
* @generated from rpc holos.user.v1alpha1.UserService.GetUser
*/
getUser: {
name: "GetUser",
I: GetUserRequest,
O: GetUserResponse,
kind: MethodKind.Unary,
},
/**
* Register an user and initialize an organization, bare platform, and reference platform.
*
* @generated from rpc holos.user.v1alpha1.UserService.RegisterUser
*/
registerUser: {
name: "RegisterUser",
I: RegisterUserRequest,
O: RegisterUserResponse,
kind: MethodKind.Unary,
},
}
} as const;

View File

@@ -0,0 +1,290 @@
// @generated by protoc-gen-es v1.9.0 with parameter "target=ts"
// @generated from file holos/user/v1alpha1/user_service.proto (package holos.user.v1alpha1, syntax proto3)
/* eslint-disable */
// @ts-nocheck
import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf";
import { FieldMask, Message, proto3 } from "@bufbuild/protobuf";
import { User } from "./user_pb.js";
import { UserRef } from "../../object/v1alpha1/object_pb.js";
import { Organization } from "../../organization/v1alpha1/organization_pb.js";
/**
* Create a User from the oidc id token claims or the provided user. Each one
* of subject, email, and user id must be globally unique.
*
* @generated from message holos.user.v1alpha1.CreateUserRequest
*/
export class CreateUserRequest extends Message<CreateUserRequest> {
/**
* User resource to create. If absent, the server populates User fields with
* the oidc id token claims of the authenticated request.
*
* @generated from field: optional holos.user.v1alpha1.User user = 1;
*/
user?: User;
constructor(data?: PartialMessage<CreateUserRequest>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.user.v1alpha1.CreateUserRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "user", kind: "message", T: User, opt: true },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): CreateUserRequest {
return new CreateUserRequest().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): CreateUserRequest {
return new CreateUserRequest().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): CreateUserRequest {
return new CreateUserRequest().fromJsonString(jsonString, options);
}
static equals(a: CreateUserRequest | PlainMessage<CreateUserRequest> | undefined, b: CreateUserRequest | PlainMessage<CreateUserRequest> | undefined): boolean {
return proto3.util.equals(CreateUserRequest, a, b);
}
}
/**
* @generated from message holos.user.v1alpha1.CreateUserResponse
*/
export class CreateUserResponse extends Message<CreateUserResponse> {
/**
* @generated from field: holos.user.v1alpha1.User user = 1;
*/
user?: User;
constructor(data?: PartialMessage<CreateUserResponse>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.user.v1alpha1.CreateUserResponse";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "user", kind: "message", T: User },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): CreateUserResponse {
return new CreateUserResponse().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): CreateUserResponse {
return new CreateUserResponse().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): CreateUserResponse {
return new CreateUserResponse().fromJsonString(jsonString, options);
}
static equals(a: CreateUserResponse | PlainMessage<CreateUserResponse> | undefined, b: CreateUserResponse | PlainMessage<CreateUserResponse> | undefined): boolean {
return proto3.util.equals(CreateUserResponse, a, b);
}
}
/**
* @generated from message holos.user.v1alpha1.GetUserRequest
*/
export class GetUserRequest extends Message<GetUserRequest> {
/**
* UserRef represents the user to return in the response.
*
* @generated from field: holos.object.v1alpha1.UserRef user = 1;
*/
user?: UserRef;
/**
* FieldMask represents the response User fields to include.
*
* @generated from field: optional google.protobuf.FieldMask field_mask = 2;
*/
fieldMask?: FieldMask;
constructor(data?: PartialMessage<GetUserRequest>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.user.v1alpha1.GetUserRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "user", kind: "message", T: UserRef },
{ no: 2, name: "field_mask", kind: "message", T: FieldMask, opt: true },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): GetUserRequest {
return new GetUserRequest().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): GetUserRequest {
return new GetUserRequest().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): GetUserRequest {
return new GetUserRequest().fromJsonString(jsonString, options);
}
static equals(a: GetUserRequest | PlainMessage<GetUserRequest> | undefined, b: GetUserRequest | PlainMessage<GetUserRequest> | undefined): boolean {
return proto3.util.equals(GetUserRequest, a, b);
}
}
/**
* @generated from message holos.user.v1alpha1.GetUserResponse
*/
export class GetUserResponse extends Message<GetUserResponse> {
/**
* @generated from field: holos.user.v1alpha1.User user = 1;
*/
user?: User;
constructor(data?: PartialMessage<GetUserResponse>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.user.v1alpha1.GetUserResponse";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "user", kind: "message", T: User },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): GetUserResponse {
return new GetUserResponse().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): GetUserResponse {
return new GetUserResponse().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): GetUserResponse {
return new GetUserResponse().fromJsonString(jsonString, options);
}
static equals(a: GetUserResponse | PlainMessage<GetUserResponse> | undefined, b: GetUserResponse | PlainMessage<GetUserResponse> | undefined): boolean {
return proto3.util.equals(GetUserResponse, a, b);
}
}
/**
* Register a User from the oidc id token claims or the provided user. Each one
* of subject, email, and user id must be globally unique.
*
* @generated from message holos.user.v1alpha1.RegisterUserRequest
*/
export class RegisterUserRequest extends Message<RegisterUserRequest> {
/**
* User resource to create. If absent, the server populates User fields with
* the oidc id token claims of the authenticated request.
* NOTE: The server may ignore this request field and register the user solely
* from authenticated identity claims.
*
* @generated from field: optional holos.user.v1alpha1.User user = 1;
*/
user?: User;
/**
* Mask of the user fields to include in the response.
*
* @generated from field: optional google.protobuf.FieldMask user_mask = 2;
*/
userMask?: FieldMask;
/**
* Organization resource to create. If absent, the server generates an
* organization based on the user fields.
* NOTE: The server may ignore this request field and register the
* organization solely from authenticated identity claims.
*
* @generated from field: optional holos.organization.v1alpha1.Organization organization = 3;
*/
organization?: Organization;
/**
* Mask of the organization fields to include in the response.
*
* @generated from field: optional google.protobuf.FieldMask organization_mask = 4;
*/
organizationMask?: FieldMask;
constructor(data?: PartialMessage<RegisterUserRequest>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.user.v1alpha1.RegisterUserRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "user", kind: "message", T: User, opt: true },
{ no: 2, name: "user_mask", kind: "message", T: FieldMask, opt: true },
{ no: 3, name: "organization", kind: "message", T: Organization, opt: true },
{ no: 4, name: "organization_mask", kind: "message", T: FieldMask, opt: true },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): RegisterUserRequest {
return new RegisterUserRequest().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): RegisterUserRequest {
return new RegisterUserRequest().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): RegisterUserRequest {
return new RegisterUserRequest().fromJsonString(jsonString, options);
}
static equals(a: RegisterUserRequest | PlainMessage<RegisterUserRequest> | undefined, b: RegisterUserRequest | PlainMessage<RegisterUserRequest> | undefined): boolean {
return proto3.util.equals(RegisterUserRequest, a, b);
}
}
/**
* @generated from message holos.user.v1alpha1.RegisterUserResponse
*/
export class RegisterUserResponse extends Message<RegisterUserResponse> {
/**
* @generated from field: holos.user.v1alpha1.User user = 1;
*/
user?: User;
/**
* @generated from field: holos.organization.v1alpha1.Organization organization = 2;
*/
organization?: Organization;
constructor(data?: PartialMessage<RegisterUserResponse>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.user.v1alpha1.RegisterUserResponse";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "user", kind: "message", T: User },
{ no: 2, name: "organization", kind: "message", T: Organization },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): RegisterUserResponse {
return new RegisterUserResponse().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): RegisterUserResponse {
return new RegisterUserResponse().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): RegisterUserResponse {
return new RegisterUserResponse().fromJsonString(jsonString, options);
}
static equals(a: RegisterUserResponse | PlainMessage<RegisterUserResponse> | undefined, b: RegisterUserResponse | PlainMessage<RegisterUserResponse> | undefined): boolean {
return proto3.util.equals(RegisterUserResponse, a, b);
}
}

View File

@@ -1,35 +0,0 @@
// @generated by protoc-gen-connect-query v1.3.1 with parameter "target=ts"
// @generated from file holos/v1alpha1/organization.proto (package holos.v1alpha1, syntax proto3)
/* eslint-disable */
// @ts-nocheck
import { MethodKind } from "@bufbuild/protobuf";
import { CreateCallerOrganizationRequest, GetCallerOrganizationsRequest, GetCallerOrganizationsResponse } from "./organization_pb.js";
/**
* @generated from rpc holos.v1alpha1.OrganizationService.GetCallerOrganizations
*/
export const getCallerOrganizations = {
localName: "getCallerOrganizations",
name: "GetCallerOrganizations",
kind: MethodKind.Unary,
I: GetCallerOrganizationsRequest,
O: GetCallerOrganizationsResponse,
service: {
typeName: "holos.v1alpha1.OrganizationService"
}
} as const;
/**
* @generated from rpc holos.v1alpha1.OrganizationService.CreateCallerOrganization
*/
export const createCallerOrganization = {
localName: "createCallerOrganization",
name: "CreateCallerOrganization",
kind: MethodKind.Unary,
I: CreateCallerOrganizationRequest,
O: GetCallerOrganizationsResponse,
service: {
typeName: "holos.v1alpha1.OrganizationService"
}
} as const;

View File

@@ -1,35 +0,0 @@
// @generated by protoc-gen-connect-es v1.4.0 with parameter "target=ts"
// @generated from file holos/v1alpha1/organization.proto (package holos.v1alpha1, syntax proto3)
/* eslint-disable */
// @ts-nocheck
import { CreateCallerOrganizationRequest, GetCallerOrganizationsRequest, GetCallerOrganizationsResponse } from "./organization_pb.js";
import { MethodKind } from "@bufbuild/protobuf";
/**
* @generated from service holos.v1alpha1.OrganizationService
*/
export const OrganizationService = {
typeName: "holos.v1alpha1.OrganizationService",
methods: {
/**
* @generated from rpc holos.v1alpha1.OrganizationService.GetCallerOrganizations
*/
getCallerOrganizations: {
name: "GetCallerOrganizations",
I: GetCallerOrganizationsRequest,
O: GetCallerOrganizationsResponse,
kind: MethodKind.Unary,
},
/**
* @generated from rpc holos.v1alpha1.OrganizationService.CreateCallerOrganization
*/
createCallerOrganization: {
name: "CreateCallerOrganization",
I: CreateCallerOrganizationRequest,
O: GetCallerOrganizationsResponse,
kind: MethodKind.Unary,
},
}
} as const;

View File

@@ -1,172 +0,0 @@
// @generated by protoc-gen-es v1.9.0 with parameter "target=ts"
// @generated from file holos/v1alpha1/organization.proto (package holos.v1alpha1, syntax proto3)
/* eslint-disable */
// @ts-nocheck
import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf";
import { Message, proto3 } from "@bufbuild/protobuf";
import { Timestamps } from "./timestamps_pb.js";
import { User } from "./user_pb.js";
/**
* @generated from message holos.v1alpha1.Organization
*/
export class Organization extends Message<Organization> {
/**
* Unique id assigned by the server.
*
* @generated from field: string id = 1;
*/
id = "";
/**
* @generated from field: string name = 2;
*/
name = "";
/**
* @generated from field: string display_name = 3;
*/
displayName = "";
/**
* @generated from field: holos.v1alpha1.Timestamps timestamps = 4;
*/
timestamps?: Timestamps;
constructor(data?: PartialMessage<Organization>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.v1alpha1.Organization";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 2, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 3, name: "display_name", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 4, name: "timestamps", kind: "message", T: Timestamps },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): Organization {
return new Organization().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): Organization {
return new Organization().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): Organization {
return new Organization().fromJsonString(jsonString, options);
}
static equals(a: Organization | PlainMessage<Organization> | undefined, b: Organization | PlainMessage<Organization> | undefined): boolean {
return proto3.util.equals(Organization, a, b);
}
}
/**
* @generated from message holos.v1alpha1.GetCallerOrganizationsRequest
*/
export class GetCallerOrganizationsRequest extends Message<GetCallerOrganizationsRequest> {
constructor(data?: PartialMessage<GetCallerOrganizationsRequest>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.v1alpha1.GetCallerOrganizationsRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): GetCallerOrganizationsRequest {
return new GetCallerOrganizationsRequest().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): GetCallerOrganizationsRequest {
return new GetCallerOrganizationsRequest().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): GetCallerOrganizationsRequest {
return new GetCallerOrganizationsRequest().fromJsonString(jsonString, options);
}
static equals(a: GetCallerOrganizationsRequest | PlainMessage<GetCallerOrganizationsRequest> | undefined, b: GetCallerOrganizationsRequest | PlainMessage<GetCallerOrganizationsRequest> | undefined): boolean {
return proto3.util.equals(GetCallerOrganizationsRequest, a, b);
}
}
/**
* @generated from message holos.v1alpha1.GetCallerOrganizationsResponse
*/
export class GetCallerOrganizationsResponse extends Message<GetCallerOrganizationsResponse> {
/**
* @generated from field: holos.v1alpha1.User user = 1;
*/
user?: User;
/**
* @generated from field: repeated holos.v1alpha1.Organization organizations = 2;
*/
organizations: Organization[] = [];
constructor(data?: PartialMessage<GetCallerOrganizationsResponse>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.v1alpha1.GetCallerOrganizationsResponse";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "user", kind: "message", T: User },
{ no: 2, name: "organizations", kind: "message", T: Organization, repeated: true },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): GetCallerOrganizationsResponse {
return new GetCallerOrganizationsResponse().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): GetCallerOrganizationsResponse {
return new GetCallerOrganizationsResponse().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): GetCallerOrganizationsResponse {
return new GetCallerOrganizationsResponse().fromJsonString(jsonString, options);
}
static equals(a: GetCallerOrganizationsResponse | PlainMessage<GetCallerOrganizationsResponse> | undefined, b: GetCallerOrganizationsResponse | PlainMessage<GetCallerOrganizationsResponse> | undefined): boolean {
return proto3.util.equals(GetCallerOrganizationsResponse, a, b);
}
}
/**
* @generated from message holos.v1alpha1.CreateCallerOrganizationRequest
*/
export class CreateCallerOrganizationRequest extends Message<CreateCallerOrganizationRequest> {
constructor(data?: PartialMessage<CreateCallerOrganizationRequest>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.v1alpha1.CreateCallerOrganizationRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): CreateCallerOrganizationRequest {
return new CreateCallerOrganizationRequest().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): CreateCallerOrganizationRequest {
return new CreateCallerOrganizationRequest().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): CreateCallerOrganizationRequest {
return new CreateCallerOrganizationRequest().fromJsonString(jsonString, options);
}
static equals(a: CreateCallerOrganizationRequest | PlainMessage<CreateCallerOrganizationRequest> | undefined, b: CreateCallerOrganizationRequest | PlainMessage<CreateCallerOrganizationRequest> | undefined): boolean {
return proto3.util.equals(CreateCallerOrganizationRequest, a, b);
}
}

View File

@@ -1,55 +0,0 @@
// @generated by protoc-gen-es v1.9.0 with parameter "target=ts"
// @generated from file holos/v1alpha1/timestamps.proto (package holos.v1alpha1, syntax proto3)
/* eslint-disable */
// @ts-nocheck
import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf";
import { Message, proto3, Timestamp } from "@bufbuild/protobuf";
/**
* @generated from message holos.v1alpha1.Timestamps
*/
export class Timestamps extends Message<Timestamps> {
/**
* Created at timestamp
*
* @generated from field: google.protobuf.Timestamp created_at = 1;
*/
createdAt?: Timestamp;
/**
* Updated at timestamp
*
* @generated from field: google.protobuf.Timestamp updated_at = 2;
*/
updatedAt?: Timestamp;
constructor(data?: PartialMessage<Timestamps>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.v1alpha1.Timestamps";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "created_at", kind: "message", T: Timestamp },
{ no: 2, name: "updated_at", kind: "message", T: Timestamp },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): Timestamps {
return new Timestamps().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): Timestamps {
return new Timestamps().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): Timestamps {
return new Timestamps().fromJsonString(jsonString, options);
}
static equals(a: Timestamps | PlainMessage<Timestamps> | undefined, b: Timestamps | PlainMessage<Timestamps> | undefined): boolean {
return proto3.util.equals(Timestamps, a, b);
}
}

View File

@@ -1,49 +0,0 @@
// @generated by protoc-gen-connect-query v1.3.1 with parameter "target=ts"
// @generated from file holos/v1alpha1/user.proto (package holos.v1alpha1, syntax proto3)
/* eslint-disable */
// @ts-nocheck
import { MethodKind } from "@bufbuild/protobuf";
import { CreateCallerUserRequest, CreateCallerUserResponse, GetCallerClaimsRequest, GetCallerClaimsResponse, GetCallerUserRequest, GetCallerUserResponse } from "./user_pb.js";
/**
* @generated from rpc holos.v1alpha1.UserService.GetCallerClaims
*/
export const getCallerClaims = {
localName: "getCallerClaims",
name: "GetCallerClaims",
kind: MethodKind.Unary,
I: GetCallerClaimsRequest,
O: GetCallerClaimsResponse,
service: {
typeName: "holos.v1alpha1.UserService"
}
} as const;
/**
* @generated from rpc holos.v1alpha1.UserService.GetCallerUser
*/
export const getCallerUser = {
localName: "getCallerUser",
name: "GetCallerUser",
kind: MethodKind.Unary,
I: GetCallerUserRequest,
O: GetCallerUserResponse,
service: {
typeName: "holos.v1alpha1.UserService"
}
} as const;
/**
* @generated from rpc holos.v1alpha1.UserService.CreateCallerUser
*/
export const createCallerUser = {
localName: "createCallerUser",
name: "CreateCallerUser",
kind: MethodKind.Unary,
I: CreateCallerUserRequest,
O: CreateCallerUserResponse,
service: {
typeName: "holos.v1alpha1.UserService"
}
} as const;

View File

@@ -1,44 +0,0 @@
// @generated by protoc-gen-connect-es v1.4.0 with parameter "target=ts"
// @generated from file holos/v1alpha1/user.proto (package holos.v1alpha1, syntax proto3)
/* eslint-disable */
// @ts-nocheck
import { CreateCallerUserRequest, CreateCallerUserResponse, GetCallerClaimsRequest, GetCallerClaimsResponse, GetCallerUserRequest, GetCallerUserResponse } from "./user_pb.js";
import { MethodKind } from "@bufbuild/protobuf";
/**
* @generated from service holos.v1alpha1.UserService
*/
export const UserService = {
typeName: "holos.v1alpha1.UserService",
methods: {
/**
* @generated from rpc holos.v1alpha1.UserService.GetCallerClaims
*/
getCallerClaims: {
name: "GetCallerClaims",
I: GetCallerClaimsRequest,
O: GetCallerClaimsResponse,
kind: MethodKind.Unary,
},
/**
* @generated from rpc holos.v1alpha1.UserService.GetCallerUser
*/
getCallerUser: {
name: "GetCallerUser",
I: GetCallerUserRequest,
O: GetCallerUserResponse,
kind: MethodKind.Unary,
},
/**
* @generated from rpc holos.v1alpha1.UserService.CreateCallerUser
*/
createCallerUser: {
name: "CreateCallerUser",
I: CreateCallerUserRequest,
O: CreateCallerUserResponse,
kind: MethodKind.Unary,
},
}
} as const;

View File

@@ -1,367 +0,0 @@
// @generated by protoc-gen-es v1.9.0 with parameter "target=ts"
// @generated from file holos/v1alpha1/user.proto (package holos.v1alpha1, syntax proto3)
/* eslint-disable */
// @ts-nocheck
import type { BinaryReadOptions, FieldList, JsonReadOptions, JsonValue, PartialMessage, PlainMessage } from "@bufbuild/protobuf";
import { Message, proto3 } from "@bufbuild/protobuf";
import { Timestamps } from "./timestamps_pb.js";
/**
* User represents a human user in the system. See db schema in ent/schema/user.go
*
* @generated from message holos.v1alpha1.User
*/
export class User extends Message<User> {
/**
* Unique id assigned by the server.
*
* @generated from field: string id = 1;
*/
id = "";
/**
* @generated from field: string email = 2;
*/
email = "";
/**
* @generated from field: bool email_verified = 3;
*/
emailVerified = false;
/**
* @generated from field: string name = 4;
*/
name = "";
/**
* @generated from field: holos.v1alpha1.Timestamps timestamps = 5;
*/
timestamps?: Timestamps;
constructor(data?: PartialMessage<User>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.v1alpha1.User";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "id", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 2, name: "email", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 3, name: "email_verified", kind: "scalar", T: 8 /* ScalarType.BOOL */ },
{ no: 4, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 5, name: "timestamps", kind: "message", T: Timestamps },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): User {
return new User().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): User {
return new User().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): User {
return new User().fromJsonString(jsonString, options);
}
static equals(a: User | PlainMessage<User> | undefined, b: User | PlainMessage<User> | undefined): boolean {
return proto3.util.equals(User, a, b);
}
}
/**
* @generated from message holos.v1alpha1.CreateCallerUserRequest
*/
export class CreateCallerUserRequest extends Message<CreateCallerUserRequest> {
constructor(data?: PartialMessage<CreateCallerUserRequest>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.v1alpha1.CreateCallerUserRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): CreateCallerUserRequest {
return new CreateCallerUserRequest().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): CreateCallerUserRequest {
return new CreateCallerUserRequest().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): CreateCallerUserRequest {
return new CreateCallerUserRequest().fromJsonString(jsonString, options);
}
static equals(a: CreateCallerUserRequest | PlainMessage<CreateCallerUserRequest> | undefined, b: CreateCallerUserRequest | PlainMessage<CreateCallerUserRequest> | undefined): boolean {
return proto3.util.equals(CreateCallerUserRequest, a, b);
}
}
/**
* @generated from message holos.v1alpha1.CreateCallerUserResponse
*/
export class CreateCallerUserResponse extends Message<CreateCallerUserResponse> {
/**
* @generated from field: holos.v1alpha1.User user = 1;
*/
user?: User;
constructor(data?: PartialMessage<CreateCallerUserResponse>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.v1alpha1.CreateCallerUserResponse";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "user", kind: "message", T: User },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): CreateCallerUserResponse {
return new CreateCallerUserResponse().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): CreateCallerUserResponse {
return new CreateCallerUserResponse().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): CreateCallerUserResponse {
return new CreateCallerUserResponse().fromJsonString(jsonString, options);
}
static equals(a: CreateCallerUserResponse | PlainMessage<CreateCallerUserResponse> | undefined, b: CreateCallerUserResponse | PlainMessage<CreateCallerUserResponse> | undefined): boolean {
return proto3.util.equals(CreateCallerUserResponse, a, b);
}
}
/**
* @generated from message holos.v1alpha1.GetCallerClaimsRequest
*/
export class GetCallerClaimsRequest extends Message<GetCallerClaimsRequest> {
constructor(data?: PartialMessage<GetCallerClaimsRequest>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.v1alpha1.GetCallerClaimsRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): GetCallerClaimsRequest {
return new GetCallerClaimsRequest().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): GetCallerClaimsRequest {
return new GetCallerClaimsRequest().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): GetCallerClaimsRequest {
return new GetCallerClaimsRequest().fromJsonString(jsonString, options);
}
static equals(a: GetCallerClaimsRequest | PlainMessage<GetCallerClaimsRequest> | undefined, b: GetCallerClaimsRequest | PlainMessage<GetCallerClaimsRequest> | undefined): boolean {
return proto3.util.equals(GetCallerClaimsRequest, a, b);
}
}
/**
* @generated from message holos.v1alpha1.Claims
*/
export class Claims extends Message<Claims> {
/**
* @generated from field: string iss = 1;
*/
iss = "";
/**
* @generated from field: string sub = 2;
*/
sub = "";
/**
* @generated from field: string email = 3;
*/
email = "";
/**
* @generated from field: bool email_verified = 4;
*/
emailVerified = false;
/**
* @generated from field: string name = 5;
*/
name = "";
/**
* @generated from field: repeated string groups = 6;
*/
groups: string[] = [];
/**
* @generated from field: string given_name = 7;
*/
givenName = "";
/**
* @generated from field: string family_name = 8;
*/
familyName = "";
/**
* @generated from field: string picture = 9;
*/
picture = "";
constructor(data?: PartialMessage<Claims>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.v1alpha1.Claims";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "iss", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 2, name: "sub", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 3, name: "email", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 4, name: "email_verified", kind: "scalar", T: 8 /* ScalarType.BOOL */ },
{ no: 5, name: "name", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 6, name: "groups", kind: "scalar", T: 9 /* ScalarType.STRING */, repeated: true },
{ no: 7, name: "given_name", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 8, name: "family_name", kind: "scalar", T: 9 /* ScalarType.STRING */ },
{ no: 9, name: "picture", kind: "scalar", T: 9 /* ScalarType.STRING */ },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): Claims {
return new Claims().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): Claims {
return new Claims().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): Claims {
return new Claims().fromJsonString(jsonString, options);
}
static equals(a: Claims | PlainMessage<Claims> | undefined, b: Claims | PlainMessage<Claims> | undefined): boolean {
return proto3.util.equals(Claims, a, b);
}
}
/**
* UserClaims represents id token claims
*
* @generated from message holos.v1alpha1.GetCallerClaimsResponse
*/
export class GetCallerClaimsResponse extends Message<GetCallerClaimsResponse> {
/**
* @generated from field: holos.v1alpha1.Claims claims = 1;
*/
claims?: Claims;
constructor(data?: PartialMessage<GetCallerClaimsResponse>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.v1alpha1.GetCallerClaimsResponse";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "claims", kind: "message", T: Claims },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): GetCallerClaimsResponse {
return new GetCallerClaimsResponse().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): GetCallerClaimsResponse {
return new GetCallerClaimsResponse().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): GetCallerClaimsResponse {
return new GetCallerClaimsResponse().fromJsonString(jsonString, options);
}
static equals(a: GetCallerClaimsResponse | PlainMessage<GetCallerClaimsResponse> | undefined, b: GetCallerClaimsResponse | PlainMessage<GetCallerClaimsResponse> | undefined): boolean {
return proto3.util.equals(GetCallerClaimsResponse, a, b);
}
}
/**
* Empty request, claims are pulled from the id token
*
* @generated from message holos.v1alpha1.GetCallerUserRequest
*/
export class GetCallerUserRequest extends Message<GetCallerUserRequest> {
constructor(data?: PartialMessage<GetCallerUserRequest>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.v1alpha1.GetCallerUserRequest";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): GetCallerUserRequest {
return new GetCallerUserRequest().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): GetCallerUserRequest {
return new GetCallerUserRequest().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): GetCallerUserRequest {
return new GetCallerUserRequest().fromJsonString(jsonString, options);
}
static equals(a: GetCallerUserRequest | PlainMessage<GetCallerUserRequest> | undefined, b: GetCallerUserRequest | PlainMessage<GetCallerUserRequest> | undefined): boolean {
return proto3.util.equals(GetCallerUserRequest, a, b);
}
}
/**
* @generated from message holos.v1alpha1.GetCallerUserResponse
*/
export class GetCallerUserResponse extends Message<GetCallerUserResponse> {
/**
* @generated from field: holos.v1alpha1.User user = 1;
*/
user?: User;
constructor(data?: PartialMessage<GetCallerUserResponse>) {
super();
proto3.util.initPartial(data, this);
}
static readonly runtime: typeof proto3 = proto3;
static readonly typeName = "holos.v1alpha1.GetCallerUserResponse";
static readonly fields: FieldList = proto3.util.newFieldList(() => [
{ no: 1, name: "user", kind: "message", T: User },
]);
static fromBinary(bytes: Uint8Array, options?: Partial<BinaryReadOptions>): GetCallerUserResponse {
return new GetCallerUserResponse().fromBinary(bytes, options);
}
static fromJson(jsonValue: JsonValue, options?: Partial<JsonReadOptions>): GetCallerUserResponse {
return new GetCallerUserResponse().fromJson(jsonValue, options);
}
static fromJsonString(jsonString: string, options?: Partial<JsonReadOptions>): GetCallerUserResponse {
return new GetCallerUserResponse().fromJsonString(jsonString, options);
}
static equals(a: GetCallerUserResponse | PlainMessage<GetCallerUserResponse> | undefined, b: GetCallerUserResponse | PlainMessage<GetCallerUserResponse> | undefined): boolean {
return proto3.util.equals(GetCallerUserResponse, a, b);
}
}

View File

@@ -8,7 +8,7 @@
</mat-toolbar>
<mat-nav-list>
<a mat-list-item routerLink="/home" routerLinkActive="active-link">Home</a>
<a mat-list-item routerLink="/clusters" routerLinkActive="active-link">Clusters</a>
<a mat-list-item routerLink="/platforms" routerLinkActive="active-link">Platforms</a>
</mat-nav-list>
</mat-sidenav>
<mat-sidenav-content>
@@ -31,9 +31,11 @@
</button>
}
</span>
<app-profile-button [claims$]="claims$"></app-profile-button>
<app-version-button></app-version-button>
<app-profile-button [user$]="user$"></app-profile-button>
</mat-toolbar>
<!-- Add Content Here -->
<router-outlet></router-outlet>
<main class="main-content">
<router-outlet></router-outlet>
</main>
</mat-sidenav-content>
</mat-sidenav-container>

View File

@@ -13,7 +13,7 @@
.mat-toolbar.mat-primary {
position: sticky;
top: 0;
z-index: 1;
z-index: 1000;
}
.toolbar-spacer {

View File

@@ -1,20 +1,21 @@
import { Component, OnInit, inject } from '@angular/core';
import { BreakpointObserver, Breakpoints } from '@angular/cdk/layout';
import { AsyncPipe, NgIf } from '@angular/common';
import { MatToolbarModule } from '@angular/material/toolbar';
import { Component, OnDestroy, OnInit, inject } from '@angular/core';
import { MatButtonModule } from '@angular/material/button';
import { MatSidenavModule } from '@angular/material/sidenav';
import { MatListModule } from '@angular/material/list';
import { MatIconModule } from '@angular/material/icon';
import { Observable } from 'rxjs';
import { map, shareReplay } from 'rxjs/operators';
import { RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router';
import { MatCardModule } from '@angular/material/card';
import { Claims } from '../gen/holos/v1alpha1/user_pb';
import { MatIconModule } from '@angular/material/icon';
import { MatListModule } from '@angular/material/list';
import { MatSidenavModule } from '@angular/material/sidenav';
import { MatToolbarModule } from '@angular/material/toolbar';
import { RouterLink, RouterLinkActive, RouterOutlet } from '@angular/router';
import { Observable, Subject } from 'rxjs';
import { map, shareReplay, takeUntil } from 'rxjs/operators';
import { Organization } from '../gen/holos/organization/v1alpha1/organization_pb';
import { User } from '../gen/holos/user/v1alpha1/user_pb';
import { ProfileButtonComponent } from '../profile-button/profile-button.component';
import { UserService } from '../services/user.service';
import { Organization } from '../gen/holos/v1alpha1/organization_pb';
import { OrganizationService } from '../services/organization.service';
import { UserService } from '../services/user.service';
import { VersionButtonComponent } from '../version-button/version-button.component';
@Component({
selector: 'app-nav',
@@ -34,28 +35,35 @@ import { OrganizationService } from '../services/organization.service';
RouterOutlet,
MatCardModule,
ProfileButtonComponent,
VersionButtonComponent,
]
})
export class NavComponent implements OnInit {
export class NavComponent implements OnInit, OnDestroy {
private breakpointObserver = inject(BreakpointObserver);
private userService = inject(UserService);
private orgService = inject(OrganizationService);
private destroy$: Subject<boolean> = new Subject<boolean>();
claims$!: Observable<Claims | null>;
user$!: Observable<User | null>;
org$!: Observable<Organization | undefined>;
refreshOrg(): void {
this.orgService.refreshOrganizations()
}
isHandset$: Observable<boolean> = this.breakpointObserver.observe(Breakpoints.Handset)
.pipe(
map(result => result.matches),
shareReplay()
);
refreshOrg(): void {
this.orgService.refreshOrganizations()
}
ngOnInit(): void {
this.claims$ = this.userService.getClaims();
this.org$ = this.orgService.activeOrg();
this.user$ = this.userService.getUser().pipe(takeUntil(this.destroy$));
this.org$ = this.orgService.activeOrg().pipe(takeUntil(this.destroy$));
}
public ngOnDestroy(): void {
this.destroy$.next(true);
this.destroy$.complete();
}
}

View File

@@ -1,7 +1,7 @@
@if (claims$ | async; as claims) {
@if (user$ | async; as user) {
<button mat-icon-button [matMenuTriggerFor]="menu">
@if (claims.picture) {
<img class="profile-picture" [src]="claims.picture" alt="Profile"/>
@if (user.picture) {
<img class="profile-picture" [src]="user.picture" alt="Profile"/>
} @else {
<mat-icon>account_circle</mat-icon>
}
@@ -10,16 +10,16 @@
<mat-menu class="accounts-menu" #menu="matMenu">
<mat-card class="accounts-card">
<mat-card-header>
<div mat-card-avatar class="accounts-header-image" [ngStyle]="{'background-image': claims.picture ? 'url(' + claims.picture +')' : 'url(/ui/assets/img/account_circle.svg)'}">
<div mat-card-avatar class="accounts-header-image" [ngStyle]="{'background-image': user.picture ? 'url(' + user.picture +')' : 'url(/ui/assets/img/account_circle.svg)'}">
</div>
<mat-card-title>{{ claims.name }}</mat-card-title>
<mat-card-subtitle>{{ claims.email }}</mat-card-subtitle>
<mat-card-title>{{ user.name }}</mat-card-title>
<mat-card-subtitle>{{ user.email }}</mat-card-subtitle>
</mat-card-header>
<mat-card-actions>
<a mat-menu-item href="{{claims.iss}}/ui/console/users/me?id=general">
<a mat-menu-item href="{{user.subject?.iss}}/ui/console/users/me?id=general">
Profile
</a>
<a mat-menu-item href="{{claims.iss}}/oidc/v1/end_session">
<a mat-menu-item href="{{user.subject?.iss}}/oidc/v1/end_session">
Logout
</a>
</mat-card-actions>

View File

@@ -1,5 +1,5 @@
import { Component, Input } from '@angular/core';
import { Claims } from '../gen/holos/v1alpha1/user_pb';
import { User } from '../gen/holos/user/v1alpha1/user_pb';
import { MatButtonModule } from '@angular/material/button';
import { MatMenuModule } from '@angular/material/menu';
import { Observable } from 'rxjs';
@@ -23,5 +23,5 @@ import { MatCardModule } from '@angular/material/card';
styleUrl: './profile-button.component.scss'
})
export class ProfileButtonComponent {
@Input({ required: true }) claims$!: Observable<Claims | null>;
@Input({ required: true }) user$!: Observable<User | null>;
}

View File

@@ -1,31 +1,47 @@
import { Inject, Injectable } from '@angular/core';
import { OrganizationService as ConnectOrganizationService } from '../gen/holos/v1alpha1/organization_connect';
import { ObservableClient } from '../../connect/observable-client';
import { Observable, switchMap, of, shareReplay, catchError, BehaviorSubject } from 'rxjs';
import { GetCallerOrganizationsResponse, Organization } from '../gen/holos/v1alpha1/organization_pb';
import { UserService } from './user.service';
import { Code, ConnectError } from '@connectrpc/connect';
import { BehaviorSubject, Observable, catchError, of, shareReplay, switchMap } from 'rxjs';
import { ObservableClient } from '../../connect/observable-client';
import { OrganizationService as ConnectOrganizationService } from '../gen/holos/organization/v1alpha1/organization_service_connect';
import { Organization } from '../gen/holos/organization/v1alpha1/organization_pb';
import { UserService } from './user.service';
@Injectable({
providedIn: 'root'
})
export class OrganizationService {
private callerOrganizationsTrigger$ = new BehaviorSubject<void>(undefined);
private callerOrganizations$: Observable<GetCallerOrganizationsResponse>;
private callerOrganizations$: Observable<Organization[]>;
private fetchCallerOrganizations(): Observable<GetCallerOrganizationsResponse> {
return this.client.getCallerOrganizations({ request: {} }).pipe(
private fetchCallerOrganizations(): Observable<Organization[]> {
return this.client.listOrganizations({}).pipe(
switchMap(resp => {
if (resp && resp.organizations.length > 0) {
return of(resp)
return of(resp.organizations)
}
return this.client.createCallerOrganization({ request: {} })
return this.client.createOrganization({}).pipe(
switchMap(resp => {
if (resp.organization !== undefined) {
return of([resp.organization])
} else {
return of([])
}
})
)
}),
catchError(err => {
if (err instanceof ConnectError) {
if (err.code == Code.NotFound) {
return this.userService.createUser().pipe(
switchMap(user => this.client.createCallerOrganization({ request: {} }))
switchMap(() => this.client.createOrganization({}).pipe(
switchMap(resp => {
if (resp.organization !== undefined) {
return of([resp.organization])
} else {
return of([])
}
})
))
)
}
}
@@ -35,15 +51,9 @@ export class OrganizationService {
)
}
getOrganizations(): Observable<Organization[]> {
return this.callerOrganizations$.pipe(
switchMap(resp => of(resp.organizations))
)
}
activeOrg(): Observable<Organization | undefined> {
return this.callerOrganizations$.pipe(
switchMap(resp => of(resp.organizations.at(-1)))
switchMap(orgs => of(orgs.at(0)))
)
}

View File

@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { PlatformService } from './platform.service';
describe('PlatformService', () => {
let service: PlatformService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(PlatformService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@@ -0,0 +1,45 @@
import { Inject, Injectable } from '@angular/core';
import { FieldMask, JsonValue, Struct } from '@bufbuild/protobuf';
import { Observable, of, switchMap } from 'rxjs';
import { ObservableClient } from '../../connect/observable-client';
import { Organization } from '../gen/holos/organization/v1alpha1/organization_pb';
import { Platform } from '../gen/holos/platform/v1alpha1/platform_pb';
import { PlatformService as ConnectPlatformService } from '../gen/holos/platform/v1alpha1/platform_service_connect';
import { GetPlatformRequest, ListPlatformsRequest, UpdatePlatformOperation, UpdatePlatformRequest } from '../gen/holos/platform/v1alpha1/platform_service_pb';
@Injectable({
providedIn: 'root'
})
export class PlatformService {
listPlatforms(org: Observable<Organization>): Observable<Platform[]> {
return org.pipe(
switchMap(org => {
if (org.orgId == undefined) {
return of([])
}
const req = new ListPlatformsRequest({ orgId: org.orgId })
return this.client.listPlatforms(req).pipe(
switchMap(resp => { return of(resp.platforms) })
)
})
)
}
updateModel(platformId: string, model: JsonValue): Observable<Platform | undefined> {
const update = new UpdatePlatformOperation({ platformId: platformId, model: Struct.fromJson(model) })
const updateMask = new FieldMask({ paths: ["model"] })
const req = new UpdatePlatformRequest({ update: update, updateMask: updateMask })
return this.client.updatePlatform(req).pipe(
switchMap(resp => { return of(resp.platform) })
)
}
getPlatform(platformId: string): Observable<Platform | undefined> {
const req = new GetPlatformRequest({ platformId: platformId })
return this.client.getPlatform(req).pipe(
switchMap(resp => { return of(resp.platform) })
)
}
constructor(@Inject(ConnectPlatformService) private client: ObservableClient<typeof ConnectPlatformService>) { }
}

Some files were not shown because too many files have changed in this diff Show More