mirror of
https://github.com/holos-run/holos.git
synced 2026-03-19 16:54:58 +00:00
Compare commits
47 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a6756ecf11 | ||
|
|
ef7ec30037 | ||
|
|
1642787825 | ||
|
|
f83781480f | ||
|
|
9b70205855 | ||
|
|
0e4bf3c144 | ||
|
|
1241c74b41 | ||
|
|
44fea098de | ||
|
|
52286efa25 | ||
|
|
a1b2179442 | ||
|
|
cffc430738 | ||
|
|
d76454272b | ||
|
|
9d1e77c00f | ||
|
|
2050abdc6c | ||
|
|
3ea013c503 | ||
|
|
309db96138 | ||
|
|
283b4be71c | ||
|
|
ab9bca0750 | ||
|
|
ac2be67c3c | ||
|
|
6ffafb8cca | ||
|
|
590e6b556c | ||
|
|
5dc5c6fbdf | ||
|
|
cd8c9f2c32 | ||
|
|
3490941d4c | ||
|
|
3f201df0c2 | ||
|
|
4c22d515bd | ||
|
|
ec0ef1c4b3 | ||
|
|
1e51e2d49a | ||
|
|
5186499b90 | ||
|
|
fc275e4164 | ||
|
|
9fa466f7cf | ||
|
|
efd6f256a5 | ||
|
|
f7f9d6b5f0 | ||
|
|
0526062ab2 | ||
|
|
a1ededa722 | ||
|
|
9b09a02912 | ||
|
|
657a5e82a5 | ||
|
|
1eece02254 | ||
|
|
c866b47dcb | ||
|
|
ff52ec750b | ||
|
|
4184619afc | ||
|
|
954dbd1ec8 | ||
|
|
30b70e76aa | ||
|
|
ec6d112711 | ||
|
|
e796c6a763 | ||
|
|
be32201294 | ||
|
|
5ebc54b5b7 |
12
.github/workflows/lint.yaml
vendored
12
.github/workflows/lint.yaml
vendored
@@ -30,14 +30,15 @@ jobs:
|
||||
with:
|
||||
go-version: stable
|
||||
|
||||
- name: Install tools
|
||||
run: sudo apt update && sudo apt -qq -y install curl zip unzip tar bzip2 make
|
||||
- name: Install Packages
|
||||
run: sudo apt update && sudo apt -qq -y install git curl zip unzip tar bzip2 make
|
||||
|
||||
- name: Install Deps
|
||||
- name: Install Tools
|
||||
run: |
|
||||
make go-deps
|
||||
set -x
|
||||
make tools
|
||||
make buf
|
||||
go generate ./...
|
||||
make frontend-deps
|
||||
make frontend
|
||||
go mod tidy
|
||||
|
||||
@@ -45,3 +46,4 @@ jobs:
|
||||
uses: golangci/golangci-lint-action@v4
|
||||
with:
|
||||
version: latest
|
||||
skip-pkg-cache: true
|
||||
|
||||
7
.github/workflows/release.yaml
vendored
7
.github/workflows/release.yaml
vendored
@@ -36,11 +36,12 @@ jobs:
|
||||
|
||||
# Necessary to run these outside of goreleaser, otherwise
|
||||
# /home/runner/_work/holos/holos/internal/frontend/node_modules/.bin/protoc-gen-connect-query is not in PATH
|
||||
- name: Install Deps
|
||||
- name: Install Tools
|
||||
run: |
|
||||
make go-deps
|
||||
set -x
|
||||
make tools
|
||||
make buf
|
||||
go generate ./...
|
||||
make frontend-deps
|
||||
make frontend
|
||||
go mod tidy
|
||||
|
||||
|
||||
11
.github/workflows/test.yaml
vendored
11
.github/workflows/test.yaml
vendored
@@ -28,8 +28,8 @@ jobs:
|
||||
with:
|
||||
go-version: stable
|
||||
|
||||
- name: Install tools
|
||||
run: sudo apt update && sudo apt -qq -y install curl zip unzip tar bzip2 make
|
||||
- name: Install Packages
|
||||
run: sudo apt update && sudo apt -qq -y install git curl zip unzip tar bzip2 make
|
||||
|
||||
- name: Set up Helm
|
||||
uses: azure/setup-helm@v4
|
||||
@@ -37,11 +37,12 @@ jobs:
|
||||
- name: Set up Kubectl
|
||||
uses: azure/setup-kubectl@v3
|
||||
|
||||
- name: Install Deps
|
||||
- name: Install Tools
|
||||
run: |
|
||||
make go-deps
|
||||
set -x
|
||||
make tools
|
||||
make buf
|
||||
go generate ./...
|
||||
make frontend-deps
|
||||
make frontend
|
||||
go mod tidy
|
||||
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1,4 +1,4 @@
|
||||
bin/
|
||||
/bin/
|
||||
vendor/
|
||||
.idea/
|
||||
coverage.out
|
||||
|
||||
21
Makefile
21
Makefile
@@ -4,7 +4,7 @@ PROJ=holos
|
||||
ORG_PATH=github.com/holos-run
|
||||
REPO_PATH=$(ORG_PATH)/$(PROJ)
|
||||
|
||||
VERSION := $(shell cat pkg/version/embedded/major pkg/version/embedded/minor pkg/version/embedded/patch | xargs printf "%s.%s.%s")
|
||||
VERSION := $(shell cat version/embedded/major version/embedded/minor version/embedded/patch | xargs printf "%s.%s.%s")
|
||||
BIN_NAME := holos
|
||||
|
||||
DOCKER_REPO=quay.io/openinfrastructure/holos
|
||||
@@ -19,7 +19,7 @@ GIT_COMMIT=$(shell git rev-parse HEAD)
|
||||
GIT_TREE_STATE=$(shell test -n "`git status --porcelain`" && echo "dirty" || echo "clean")
|
||||
BUILD_DATE=$(shell date -Iseconds)
|
||||
|
||||
LD_FLAGS="-w -X ${ORG_PATH}/${PROJ}/pkg/version.GitCommit=${GIT_COMMIT} -X ${ORG_PATH}/${PROJ}/pkg/version.GitTreeState=${GIT_TREE_STATE} -X ${ORG_PATH}/${PROJ}/pkg/version.BuildDate=${BUILD_DATE}"
|
||||
LD_FLAGS="-w -X ${ORG_PATH}/${PROJ}/version.GitCommit=${GIT_COMMIT} -X ${ORG_PATH}/${PROJ}/version.GitTreeState=${GIT_TREE_STATE} -X ${ORG_PATH}/${PROJ}/version.BuildDate=${BUILD_DATE}"
|
||||
|
||||
.PHONY: default
|
||||
default: test
|
||||
@@ -68,7 +68,7 @@ generate: ## Generate code.
|
||||
go generate ./...
|
||||
|
||||
.PHONY: build
|
||||
build: generate ## Build holos executable.
|
||||
build: generate frontend ## Build holos executable.
|
||||
@echo "building ${BIN_NAME} ${VERSION}"
|
||||
@echo "GOPATH=${GOPATH}"
|
||||
go build -trimpath -o bin/$(BIN_NAME) -ldflags $(LD_FLAGS) $(REPO_PATH)/cmd/$(BIN_NAME)
|
||||
@@ -102,12 +102,15 @@ buf: ## buf generate
|
||||
cd service && buf mod update
|
||||
buf generate
|
||||
|
||||
.PHONY: tools
|
||||
tools: go-deps frontend-deps ## install tool dependencies
|
||||
|
||||
.PHONY: go-deps
|
||||
go-deps: ## install go executables
|
||||
go install github.com/bufbuild/buf/cmd/buf@v1
|
||||
go install github.com/fullstorydev/grpcurl/cmd/grpcurl@v1
|
||||
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1
|
||||
go install connectrpc.com/connect/cmd/protoc-gen-connect-go@v1
|
||||
go-deps: ## tool versions pinned in tools.go
|
||||
go install github.com/bufbuild/buf/cmd/buf
|
||||
go install github.com/fullstorydev/grpcurl/cmd/grpcurl
|
||||
go install google.golang.org/protobuf/cmd/protoc-gen-go
|
||||
go install connectrpc.com/connect/cmd/protoc-gen-connect-go
|
||||
go install honnef.co/go/tools/cmd/staticcheck@latest
|
||||
# curl https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | bash
|
||||
|
||||
@@ -123,8 +126,8 @@ frontend-deps: ## Setup npm and vite
|
||||
|
||||
.PHONY: frontend
|
||||
frontend: buf
|
||||
cd internal/frontend/holos && rm -rf dist
|
||||
mkdir -p internal/frontend/holos/dist
|
||||
cd internal/frontend/holos/dist && rm -rf app
|
||||
cd internal/frontend/holos && ng build
|
||||
touch internal/frontend/frontend.go
|
||||
|
||||
|
||||
@@ -8,9 +8,9 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/holos-run/holos"
|
||||
"github.com/holos-run/holos/pkg/errors"
|
||||
"github.com/holos-run/holos/pkg/logger"
|
||||
"github.com/holos-run/holos/pkg/util"
|
||||
"github.com/holos-run/holos/internal/errors"
|
||||
"github.com/holos-run/holos/internal/logger"
|
||||
"github.com/holos-run/holos/internal/util"
|
||||
)
|
||||
|
||||
// A HelmChart represents a helm command to provide chart values in order to render kubernetes api objects.
|
||||
|
||||
@@ -4,9 +4,9 @@ import (
|
||||
"context"
|
||||
|
||||
"github.com/holos-run/holos"
|
||||
"github.com/holos-run/holos/pkg/errors"
|
||||
"github.com/holos-run/holos/pkg/logger"
|
||||
"github.com/holos-run/holos/pkg/util"
|
||||
"github.com/holos-run/holos/internal/errors"
|
||||
"github.com/holos-run/holos/internal/logger"
|
||||
"github.com/holos-run/holos/internal/util"
|
||||
)
|
||||
|
||||
const KustomizeBuildKind = "KustomizeBuild"
|
||||
|
||||
@@ -7,9 +7,9 @@ import (
|
||||
"path/filepath"
|
||||
"slices"
|
||||
|
||||
"github.com/holos-run/holos/pkg/errors"
|
||||
"github.com/holos-run/holos/pkg/logger"
|
||||
"github.com/holos-run/holos/pkg/util"
|
||||
"github.com/holos-run/holos/internal/errors"
|
||||
"github.com/holos-run/holos/internal/logger"
|
||||
"github.com/holos-run/holos/internal/util"
|
||||
)
|
||||
|
||||
// Result is the build result for display or writing. Holos components Render the Result as a data pipeline.
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/holos-run/holos/pkg/cli"
|
||||
"os"
|
||||
|
||||
"github.com/holos-run/holos/internal/cli"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/holos-run/holos/pkg/cli"
|
||||
"github.com/rogpeppe/go-internal/testscript"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/holos-run/holos/internal/cli"
|
||||
"github.com/rogpeppe/go-internal/testscript"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
|
||||
@@ -4,3 +4,8 @@ package v1
|
||||
apiVersion: "apps/v1"
|
||||
kind: "Deployment"
|
||||
}
|
||||
|
||||
#StatefulSet: {
|
||||
apiVersion: "apps/v1"
|
||||
kind: "StatefulSet"
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import "encoding/yaml"
|
||||
ConfigMap?: [Name=_]: #ConfigMap & {metadata: name: Name}
|
||||
|
||||
Deployment?: [_]: #Deployment
|
||||
StatefulSet?: [_]: #StatefulSet
|
||||
RequestAuthentication?: [_]: #RequestAuthentication
|
||||
AuthorizationPolicy?: [_]: #AuthorizationPolicy
|
||||
}
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
package holos
|
||||
|
||||
let Namespace = "jeff-holos"
|
||||
let Broker = "broker"
|
||||
|
||||
spec: components: KubernetesObjectsList: [
|
||||
#KubernetesObjects & {
|
||||
_dependsOn: "prod-platform-issuer": _
|
||||
|
||||
metadata: name: "\(Namespace)-broker"
|
||||
apiObjectMap: OBJECTS.apiObjectMap
|
||||
},
|
||||
]
|
||||
|
||||
let SelectorLabels = {
|
||||
"app.kubernetes.io/instance": Broker
|
||||
"app.kubernetes.io/name": Broker
|
||||
}
|
||||
|
||||
let OBJECTS = #APIObjects & {
|
||||
apiObjects: {
|
||||
Certificate: "\(Broker)-tls": #Certificate & {
|
||||
metadata: {
|
||||
name: "\(Broker)-tls"
|
||||
namespace: Namespace
|
||||
labels: SelectorLabels
|
||||
}
|
||||
spec: {
|
||||
commonName: "\(Broker).\(Namespace).svc.cluster.local"
|
||||
dnsNames: [
|
||||
Broker,
|
||||
"\(Broker).\(Namespace).svc",
|
||||
"\(Broker).\(Namespace).svc.cluster.local",
|
||||
"provision-\(Broker)",
|
||||
"provision-\(Broker).\(Namespace).svc",
|
||||
"provision-\(Broker).\(Namespace).svc.cluster.local",
|
||||
"*.\(Broker)",
|
||||
"*.\(Broker).\(Namespace).svc",
|
||||
"*.\(Broker).\(Namespace).svc.cluster.local",
|
||||
]
|
||||
issuerRef: kind: "ClusterIssuer"
|
||||
issuerRef: name: "platform-issuer"
|
||||
secretName: metadata.name
|
||||
usages: ["signing", "key encipherment", "server auth", "client auth"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
package holos
|
||||
|
||||
let Namespace = "jeff-holos"
|
||||
let Broker = "broker"
|
||||
|
||||
spec: components: KubernetesObjectsList: [
|
||||
#KubernetesObjects & {
|
||||
_dependsOn: "prod-secrets-stores": _
|
||||
|
||||
metadata: name: "\(Namespace)-broker"
|
||||
apiObjectMap: OBJECTS.apiObjectMap
|
||||
},
|
||||
]
|
||||
|
||||
let SelectorLabels = {
|
||||
"app.kubernetes.io/instance": Broker
|
||||
"app.kubernetes.io/name": Broker
|
||||
}
|
||||
|
||||
let Metadata = {
|
||||
name: Broker
|
||||
namespace: Namespace
|
||||
labels: SelectorLabels
|
||||
}
|
||||
|
||||
let OBJECTS = #APIObjects & {
|
||||
apiObjects: {
|
||||
ExternalSecret: "\(Broker)-tls": #ExternalSecret & {
|
||||
metadata: name: "\(Broker)-tls"
|
||||
metadata: namespace: Namespace
|
||||
}
|
||||
ExternalSecret: "choria-\(Broker)": #ExternalSecret & {
|
||||
metadata: name: "choria-\(Broker)"
|
||||
metadata: namespace: Namespace
|
||||
}
|
||||
StatefulSet: "\(Broker)": {
|
||||
metadata: Metadata
|
||||
spec: {
|
||||
selector: matchLabels: SelectorLabels
|
||||
serviceName: Broker
|
||||
template: metadata: labels: SelectorLabels
|
||||
template: spec: {
|
||||
containers: [
|
||||
{
|
||||
name: Broker
|
||||
command: ["choria", "broker", "run", "--config", "/etc/choria/broker.conf"]
|
||||
image: "registry.choria.io/choria/choria:0.28.0"
|
||||
imagePullPolicy: "IfNotPresent"
|
||||
ports: [
|
||||
{
|
||||
containerPort: 4222
|
||||
name: "tcp-nats"
|
||||
protocol: "TCP"
|
||||
},
|
||||
{
|
||||
containerPort: 4333
|
||||
name: "https-wss"
|
||||
protocol: "TCP"
|
||||
},
|
||||
{
|
||||
containerPort: 5222
|
||||
name: "tcp-cluster"
|
||||
protocol: "TCP"
|
||||
},
|
||||
{
|
||||
containerPort: 8222
|
||||
name: "http-stats"
|
||||
protocol: "TCP"
|
||||
},
|
||||
]
|
||||
livenessProbe: httpGet: {
|
||||
path: "/healthz"
|
||||
port: "http-stats"
|
||||
}
|
||||
readinessProbe: livenessProbe
|
||||
resources: {}
|
||||
securityContext: {}
|
||||
volumeMounts: [
|
||||
{
|
||||
mountPath: "/etc/choria"
|
||||
name: Broker
|
||||
},
|
||||
{
|
||||
mountPath: "/etc/choria-tls"
|
||||
name: "\(Broker)-tls"
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
securityContext: {}
|
||||
serviceAccountName: Broker
|
||||
volumes: [
|
||||
{
|
||||
name: Broker
|
||||
secret: secretName: "choria-\(Broker)"
|
||||
},
|
||||
{
|
||||
name: "\(Broker)-tls"
|
||||
secret: secretName: "\(Broker)-tls"
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
ServiceAccount: "\(Broker)": #ServiceAccount & {
|
||||
metadata: Metadata
|
||||
}
|
||||
Service: "\(Broker)": #Service & {
|
||||
metadata: Metadata
|
||||
spec: {
|
||||
type: "ClusterIP"
|
||||
clusterIP: "None"
|
||||
selector: SelectorLabels
|
||||
ports: [
|
||||
{
|
||||
name: "tcp-nats"
|
||||
appProtocol: "tcp"
|
||||
port: 4222
|
||||
protocol: "TCP"
|
||||
targetPort: "tcp-nats"
|
||||
},
|
||||
{
|
||||
name: "tcp-cluster"
|
||||
appProtocol: "tcp"
|
||||
port: 5222
|
||||
protocol: "TCP"
|
||||
targetPort: "tcp-cluster"
|
||||
},
|
||||
{
|
||||
name: "https-wss"
|
||||
appProtocol: "https"
|
||||
port: 443
|
||||
protocol: "TCP"
|
||||
targetPort: "https-wss"
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
DestinationRule: "\(Broker)-wss": #DestinationRule & {
|
||||
metadata: Metadata
|
||||
spec: host: "\(Broker).\(Namespace).svc.cluster.local"
|
||||
spec: trafficPolicy: tls: {
|
||||
credentialName: "istio-ingress-mtls-cert"
|
||||
mode: "MUTUAL"
|
||||
}
|
||||
}
|
||||
VirtualService: "\(Broker)-wss": #VirtualService & {
|
||||
metadata: name: "\(Broker)-wss"
|
||||
metadata: namespace: Namespace
|
||||
spec: {
|
||||
gateways: ["istio-ingress/default"]
|
||||
hosts: ["jeff.provision.dev.\(#ClusterName).holos.run"]
|
||||
http: [
|
||||
{
|
||||
route: [
|
||||
{
|
||||
destination: {
|
||||
host: "\(Broker).\(Namespace).svc.cluster.local"
|
||||
port: "number": 443
|
||||
}
|
||||
},
|
||||
]
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
# build output from https://github.com/holos-run/holos-infra/blob/main/experiments/components/holos-saas/broker/build
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/instance: broker
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
app.kubernetes.io/name: broker
|
||||
app.kubernetes.io/version: 0.1.0
|
||||
helm.sh/chart: broker-0.1.0
|
||||
name: broker
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/instance: broker
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
app.kubernetes.io/name: broker
|
||||
app.kubernetes.io/version: 0.1.0
|
||||
helm.sh/chart: broker-0.1.0
|
||||
name: broker
|
||||
spec:
|
||||
clusterIP: None
|
||||
ports:
|
||||
- appProtocol: tcp
|
||||
name: tcp-nats
|
||||
port: 4222
|
||||
protocol: TCP
|
||||
targetPort: tcp-nats
|
||||
- appProtocol: tcp
|
||||
name: tcp-cluster
|
||||
port: 5222
|
||||
protocol: TCP
|
||||
targetPort: tcp-cluster
|
||||
- appProtocol: https
|
||||
name: https-wss
|
||||
port: 443
|
||||
protocol: TCP
|
||||
targetPort: https-wss
|
||||
selector:
|
||||
app.kubernetes.io/instance: broker
|
||||
app.kubernetes.io/name: broker
|
||||
type: ClusterIP
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/instance: broker
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
app.kubernetes.io/name: broker
|
||||
app.kubernetes.io/version: 0.1.0
|
||||
helm.sh/chart: broker-0.1.0
|
||||
name: broker-lb
|
||||
spec:
|
||||
externalTrafficPolicy: Local
|
||||
loadBalancerIP: 1.2.3.4
|
||||
ports:
|
||||
- appProtocol: tcp
|
||||
name: tcp-nats
|
||||
port: 4222
|
||||
protocol: TCP
|
||||
targetPort: tcp-nats
|
||||
- appProtocol: https
|
||||
name: https-wss
|
||||
port: 443
|
||||
protocol: TCP
|
||||
targetPort: https-wss
|
||||
selector:
|
||||
app.kubernetes.io/instance: broker
|
||||
app.kubernetes.io/name: broker
|
||||
type: LoadBalancer
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: StatefulSet
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/instance: broker
|
||||
app.kubernetes.io/managed-by: Helm
|
||||
app.kubernetes.io/name: broker
|
||||
app.kubernetes.io/version: 0.1.0
|
||||
helm.sh/chart: broker-0.1.0
|
||||
name: broker
|
||||
spec:
|
||||
replicas: 3
|
||||
selector:
|
||||
matchLabels:
|
||||
app.kubernetes.io/instance: broker
|
||||
app.kubernetes.io/name: broker
|
||||
serviceName: broker
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app.kubernetes.io/instance: broker
|
||||
app.kubernetes.io/name: broker
|
||||
spec:
|
||||
containers:
|
||||
- command:
|
||||
- choria
|
||||
- broker
|
||||
- run
|
||||
- --config
|
||||
- /etc/choria/broker.conf
|
||||
image: registry.choria.io/choria/choria:latest
|
||||
imagePullPolicy: Always
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: http-stats
|
||||
name: broker
|
||||
ports:
|
||||
- containerPort: 4222
|
||||
name: tcp-nats
|
||||
protocol: TCP
|
||||
- containerPort: 4333
|
||||
name: https-wss
|
||||
protocol: TCP
|
||||
- containerPort: 5222
|
||||
name: tcp-cluster
|
||||
protocol: TCP
|
||||
- containerPort: 8222
|
||||
name: http-stats
|
||||
protocol: TCP
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /healthz
|
||||
port: http-stats
|
||||
resources: {}
|
||||
securityContext: {}
|
||||
volumeMounts:
|
||||
- mountPath: /etc/choria
|
||||
name: broker
|
||||
- mountPath: /etc/choria-tls
|
||||
name: broker-tls
|
||||
securityContext: {}
|
||||
serviceAccountName: broker
|
||||
volumes:
|
||||
- name: broker
|
||||
secret:
|
||||
secretName: broker
|
||||
- name: broker-tls
|
||||
secret:
|
||||
secretName: broker-tls
|
||||
---
|
||||
apiVersion: cert-manager.io/v1
|
||||
kind: Certificate
|
||||
metadata:
|
||||
name: broker-tls
|
||||
namespace: holos-dev
|
||||
spec:
|
||||
commonName: broker.holos-dev.svc.cluster.local
|
||||
dnsNames:
|
||||
- broker
|
||||
- broker.holos-dev.svc
|
||||
- broker.holos-dev.svc.cluster.local
|
||||
- provision-broker
|
||||
- provision-broker.holos-dev.svc
|
||||
- provision-broker.holos-dev.svc.cluster.local
|
||||
- '*.broker'
|
||||
- '*.broker.holos-dev.svc'
|
||||
- '*.broker.holos-dev.svc.cluster.local'
|
||||
issuerRef:
|
||||
kind: ClusterIssuer
|
||||
name: cluster-issuer
|
||||
secretName: broker-tls
|
||||
usages:
|
||||
- signing
|
||||
- key encipherment
|
||||
- server auth
|
||||
- client auth
|
||||
---
|
||||
apiVersion: external-secrets.io/v1beta1
|
||||
kind: ExternalSecret
|
||||
metadata:
|
||||
name: broker
|
||||
spec:
|
||||
dataFrom:
|
||||
- extract:
|
||||
key: kv//kube-namespace/holos-dev/broker
|
||||
refreshInterval: 1h
|
||||
secretStoreRef:
|
||||
kind: SecretStore
|
||||
name: core-vault
|
||||
target:
|
||||
creationPolicy: Owner
|
||||
name: broker
|
||||
---
|
||||
apiVersion: networking.istio.io/v1alpha3
|
||||
kind: DestinationRule
|
||||
metadata:
|
||||
name: broker-wss
|
||||
namespace: holos-dev
|
||||
spec:
|
||||
host: broker.holos-dev.svc.cluster.local
|
||||
trafficPolicy:
|
||||
tls:
|
||||
credentialName: istio-ingress-mtls-cert
|
||||
mode: MUTUAL
|
||||
---
|
||||
apiVersion: networking.istio.io/v1alpha3
|
||||
kind: VirtualService
|
||||
metadata:
|
||||
name: broker-wss
|
||||
namespace: holos-dev
|
||||
spec:
|
||||
gateways:
|
||||
- istio-ingress/wildcard-pub-gw
|
||||
hosts:
|
||||
- provision.pub.k2.holos.run
|
||||
http:
|
||||
- route:
|
||||
- destination:
|
||||
host: broker.holos-dev.svc.cluster.local
|
||||
port:
|
||||
number: 443
|
||||
tls:
|
||||
mode: SIMPLE
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
# Machine Room Provisioner
|
||||
|
||||
This sub-tree contains Holos Components to manage a [Choria Provisioner][1]
|
||||
system for the use case of provisioning `holos controller` instances. These
|
||||
instances are implementations of Machine Room which are in turn implementations
|
||||
of Choria Server, hence why we use Choria Provisioner.
|
||||
|
||||
[1]: https://choria-io.github.io/provisioner/
|
||||
@@ -0,0 +1,62 @@
|
||||
package holos
|
||||
|
||||
// for Project in _Projects {
|
||||
// spec: components: resources: (#ProjectTemplate & {project: Project}).workload.resources
|
||||
// }
|
||||
|
||||
let Namespace = "jeff-holos"
|
||||
|
||||
#Kustomization: spec: targetNamespace: Namespace
|
||||
|
||||
spec: components: HelmChartList: [
|
||||
#HelmChart & {
|
||||
metadata: name: "jeff-holos-nats"
|
||||
namespace: Namespace
|
||||
_dependsOn: "prod-secrets-stores": _
|
||||
chart: {
|
||||
name: "nats"
|
||||
version: "1.1.10"
|
||||
repository: NatsRepository
|
||||
}
|
||||
_values: #NatsValues & {
|
||||
config: {
|
||||
// https://github.com/nats-io/k8s/tree/main/helm/charts/nats#operator-mode-with-nats-resolver
|
||||
resolver: enabled: true
|
||||
resolver: merge: {
|
||||
type: "full"
|
||||
interval: "2m"
|
||||
timeout: "1.9s"
|
||||
}
|
||||
merge: {
|
||||
operator: "eyJ0eXAiOiJKV1QiLCJhbGciOiJlZDI1NTE5LW5rZXkifQ.eyJqdGkiOiJUSElBTDM2NUtOS0lVVVJDMzNLNFJGQkJVRlFBSTRLS0NQTDJGVDZYVjdNQVhWU1dFNElRIiwiaWF0IjoxNzEzMjIxMzE1LCJpc3MiOiJPREtQM0RZTzc3T1NBRU5IU0FFR0s3WUNFTFBYT1FFWUI3RVFSTVBLWlBNQUxINE5BRUVLSjZDRyIsIm5hbWUiOiJIb2xvcyIsInN1YiI6Ik9ES1AzRFlPNzdPU0FFTkhTQUVHSzdZQ0VMUFhPUUVZQjdFUVJNUEtaUE1BTEg0TkFFRUtKNkNHIiwibmF0cyI6eyJ0eXBlIjoib3BlcmF0b3IiLCJ2ZXJzaW9uIjoyfX0.dQURTb-zIQMc-OYd9328oY887AEnvog6gOXY1-VCsDG3L89nq5x_ks4ME7dJ4Pn-Pvm2eyBi1Jx6ubgkthHgCQ"
|
||||
system_account: "ADIQCYK4K3OKTPODGCLI4PDQ6XBO52MISBPTAIDESEJMLZCMNULDKCCY"
|
||||
resolver_preload: {
|
||||
// NOTEL: Make sure you do not include the trailing , in the SYS_ACCOUNT_JWT
|
||||
"ADIQCYK4K3OKTPODGCLI4PDQ6XBO52MISBPTAIDESEJMLZCMNULDKCCY": "eyJ0eXAiOiJKV1QiLCJhbGciOiJlZDI1NTE5LW5rZXkifQ.eyJqdGkiOiI2SEVMNlhKSUdWUElMNFBURVI1MkUzTkFITjZLWkVUUUdFTlFVS0JWRzNUWlNLRzVLT09RIiwiaWF0IjoxNzEzMjIxMzE1LCJpc3MiOiJPREtQM0RZTzc3T1NBRU5IU0FFR0s3WUNFTFBYT1FFWUI3RVFSTVBLWlBNQUxINE5BRUVLSjZDRyIsIm5hbWUiOiJTWVMiLCJzdWIiOiJBRElRQ1lLNEszT0tUUE9ER0NMSTRQRFE2WEJPNTJNSVNCUFRBSURFU0VKTUxaQ01OVUxES0NDWSIsIm5hdHMiOnsibGltaXRzIjp7InN1YnMiOi0xLCJkYXRhIjotMSwicGF5bG9hZCI6LTEsImltcG9ydHMiOi0xLCJleHBvcnRzIjotMSwid2lsZGNhcmRzIjp0cnVlLCJjb25uIjotMSwibGVhZiI6LTF9LCJkZWZhdWx0X3Blcm1pc3Npb25zIjp7InB1YiI6e30sInN1YiI6e319LCJhdXRob3JpemF0aW9uIjp7fSwidHlwZSI6ImFjY291bnQiLCJ2ZXJzaW9uIjoyfX0.TiGIk8XON394D9SBEowGHY_nTeOyHiM-ihyw6HZs8AngOnYPFXH9OVjsaAf8Poa2k_V84VtH7yVNgNdjBgduDA"
|
||||
}
|
||||
}
|
||||
cluster: enabled: true
|
||||
jetstream: enabled: true
|
||||
websocket: enabled: true
|
||||
monitor: enabled: true
|
||||
}
|
||||
promExporter: enabled: true
|
||||
promExporter: podMonitor: enabled: true
|
||||
}
|
||||
},
|
||||
#HelmChart & {
|
||||
metadata: name: "jeff-holos-nack"
|
||||
namespace: Namespace
|
||||
_dependsOn: "jeff-holos-nats": _
|
||||
chart: {
|
||||
name: "nack"
|
||||
version: "0.25.2"
|
||||
repository: NatsRepository
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
let NatsRepository = {
|
||||
name: "nats"
|
||||
url: "https://nats-io.github.io/k8s/helm/charts/"
|
||||
}
|
||||
@@ -0,0 +1,722 @@
|
||||
package holos
|
||||
|
||||
#NatsValues: {
|
||||
//###############################################################################
|
||||
// Global options
|
||||
//###############################################################################
|
||||
global: {
|
||||
image: {
|
||||
// global image pull policy to use for all container images in the chart
|
||||
// can be overridden by individual image pullPolicy
|
||||
pullPolicy: null
|
||||
// global list of secret names to use as image pull secrets for all pod specs in the chart
|
||||
// secrets must exist in the same namespace
|
||||
// https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/
|
||||
pullSecretNames: []
|
||||
// global registry to use for all container images in the chart
|
||||
// can be overridden by individual image registry
|
||||
registry: null
|
||||
}
|
||||
|
||||
// global labels will be applied to all resources deployed by the chart
|
||||
labels: {}
|
||||
}
|
||||
|
||||
//###############################################################################
|
||||
// Common options
|
||||
//###############################################################################
|
||||
// override name of the chart
|
||||
nameOverride: null
|
||||
// override full name of the chart+release
|
||||
fullnameOverride: null
|
||||
// override the namespace that resources are installed into
|
||||
namespaceOverride: null
|
||||
|
||||
// reference a common CA Certificate or Bundle in all nats config `tls` blocks and nats-box contexts
|
||||
// note: `tls.verify` still must be set in the appropriate nats config `tls` blocks to require mTLS
|
||||
tlsCA: {
|
||||
enabled: false
|
||||
// set configMapName in order to mount an existing configMap to dir
|
||||
configMapName: null
|
||||
// set secretName in order to mount an existing secretName to dir
|
||||
secretName: null
|
||||
// directory to mount the configMap or secret to
|
||||
dir: "/etc/nats-ca-cert"
|
||||
// key in the configMap or secret that contains the CA Certificate or Bundle
|
||||
key: "ca.crt"
|
||||
}
|
||||
|
||||
//###############################################################################
|
||||
// NATS Stateful Set and associated resources
|
||||
//###############################################################################
|
||||
//###########################################################
|
||||
// NATS config
|
||||
//###########################################################
|
||||
config: {
|
||||
cluster: {
|
||||
enabled: true | *false
|
||||
port: 6222
|
||||
// must be 2 or higher when jetstream is enabled
|
||||
replicas: 3
|
||||
|
||||
// apply to generated route URLs that connect to other pods in the StatefulSet
|
||||
routeURLs: {
|
||||
// if both user and password are set, they will be added to route URLs
|
||||
// and the cluster authorization block
|
||||
user: null
|
||||
password: null
|
||||
// set to true to use FQDN in route URLs
|
||||
useFQDN: false
|
||||
k8sClusterDomain: "cluster.local"
|
||||
}
|
||||
|
||||
tls: {
|
||||
enabled: true | *false
|
||||
// set secretName in order to mount an existing secret to dir
|
||||
secretName: null
|
||||
dir: "/etc/nats-certs/cluster"
|
||||
cert: "tls.crt"
|
||||
key: "tls.key"
|
||||
// merge or patch the tls config
|
||||
// https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls
|
||||
merge: {}
|
||||
patch: []
|
||||
}
|
||||
|
||||
// merge or patch the cluster config
|
||||
// https://docs.nats.io/running-a-nats-service/configuration/clustering/cluster_config
|
||||
merge: {}
|
||||
patch: []
|
||||
}
|
||||
|
||||
jetstream: {
|
||||
enabled: true | *false
|
||||
|
||||
fileStore: {
|
||||
enabled: true
|
||||
dir: "/data"
|
||||
|
||||
//###########################################################
|
||||
// stateful set -> volume claim templates -> jetstream pvc
|
||||
//###########################################################
|
||||
pvc: {
|
||||
enabled: true
|
||||
size: "10Gi"
|
||||
storageClassName: null
|
||||
|
||||
// merge or patch the jetstream pvc
|
||||
// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#persistentvolumeclaim-v1-core
|
||||
merge: {}
|
||||
patch: []
|
||||
// defaults to "{{ include "nats.fullname" $ }}-js"
|
||||
name: null
|
||||
}
|
||||
|
||||
// defaults to the PVC size
|
||||
maxSize: null
|
||||
}
|
||||
|
||||
memoryStore: {
|
||||
enabled: false
|
||||
// ensure that container has a sufficient memory limit greater than maxSize
|
||||
maxSize: "1Gi"
|
||||
}
|
||||
|
||||
// merge or patch the jetstream config
|
||||
// https://docs.nats.io/running-a-nats-service/configuration#jetstream
|
||||
merge: {}
|
||||
patch: []
|
||||
}
|
||||
|
||||
nats: {
|
||||
port: 4222
|
||||
tls: {
|
||||
enabled: false
|
||||
// set secretName in order to mount an existing secret to dir
|
||||
secretName: null
|
||||
dir: "/etc/nats-certs/nats"
|
||||
cert: "tls.crt"
|
||||
key: "tls.key"
|
||||
// merge or patch the tls config
|
||||
// https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls
|
||||
merge: {}
|
||||
patch: []
|
||||
}
|
||||
}
|
||||
|
||||
leafnodes: {
|
||||
enabled: false
|
||||
port: 7422
|
||||
tls: {
|
||||
enabled: false
|
||||
// set secretName in order to mount an existing secret to dir
|
||||
secretName: null
|
||||
dir: "/etc/nats-certs/leafnodes"
|
||||
cert: "tls.crt"
|
||||
key: "tls.key"
|
||||
// merge or patch the tls config
|
||||
// https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls
|
||||
merge: {}
|
||||
patch: []
|
||||
}
|
||||
|
||||
// merge or patch the leafnodes config
|
||||
// https://docs.nats.io/running-a-nats-service/configuration/leafnodes/leafnode_conf
|
||||
merge: {}
|
||||
patch: []
|
||||
}
|
||||
|
||||
websocket: {
|
||||
enabled: true | *false
|
||||
port: 8080
|
||||
tls: {
|
||||
enabled: false
|
||||
// set secretName in order to mount an existing secret to dir
|
||||
secretName: null
|
||||
dir: "/etc/nats-certs/websocket"
|
||||
cert: "tls.crt"
|
||||
key: "tls.key"
|
||||
// merge or patch the tls config
|
||||
// https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls
|
||||
merge: {}
|
||||
patch: []
|
||||
}
|
||||
|
||||
//###########################################################
|
||||
// ingress
|
||||
//###########################################################
|
||||
// service must be enabled also
|
||||
ingress: {
|
||||
enabled: false
|
||||
// must contain at least 1 host otherwise ingress will not be created
|
||||
hosts: []
|
||||
path: "/"
|
||||
pathType: "Exact"
|
||||
// sets to the ingress class name
|
||||
className: null
|
||||
// set to an existing secret name to enable TLS on the ingress; applies to all hosts
|
||||
tlsSecretName: null
|
||||
|
||||
// merge or patch the ingress
|
||||
// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#ingress-v1-networking-k8s-io
|
||||
merge: {}
|
||||
patch: []
|
||||
// defaults to "{{ include "nats.fullname" $ }}-ws"
|
||||
name: null
|
||||
}
|
||||
|
||||
// merge or patch the websocket config
|
||||
// https://docs.nats.io/running-a-nats-service/configuration/websocket/websocket_conf
|
||||
merge: {}
|
||||
patch: []
|
||||
}
|
||||
|
||||
mqtt: {
|
||||
enabled: false
|
||||
port: 1883
|
||||
tls: {
|
||||
enabled: false
|
||||
// set secretName in order to mount an existing secret to dir
|
||||
secretName: null
|
||||
dir: "/etc/nats-certs/mqtt"
|
||||
cert: "tls.crt"
|
||||
key: "tls.key"
|
||||
// merge or patch the tls config
|
||||
// https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls
|
||||
merge: {}
|
||||
patch: []
|
||||
}
|
||||
|
||||
// merge or patch the mqtt config
|
||||
// https://docs.nats.io/running-a-nats-service/configuration/mqtt/mqtt_config
|
||||
merge: {}
|
||||
patch: []
|
||||
}
|
||||
|
||||
gateway: {
|
||||
enabled: false
|
||||
port: 7222
|
||||
tls: {
|
||||
enabled: false
|
||||
// set secretName in order to mount an existing secret to dir
|
||||
secretName: null
|
||||
dir: "/etc/nats-certs/gateway"
|
||||
cert: "tls.crt"
|
||||
key: "tls.key"
|
||||
// merge or patch the tls config
|
||||
// https://docs.nats.io/running-a-nats-service/configuration/securing_nats/tls
|
||||
merge: {}
|
||||
patch: []
|
||||
}
|
||||
|
||||
// merge or patch the gateway config
|
||||
// https://docs.nats.io/running-a-nats-service/configuration/gateways/gateway#gateway-configuration-block
|
||||
merge: {}
|
||||
patch: []
|
||||
}
|
||||
|
||||
monitor: {
|
||||
enabled: true
|
||||
port: 8222
|
||||
tls: {
|
||||
// config.nats.tls must be enabled also
|
||||
// when enabled, monitoring port will use HTTPS with the options from config.nats.tls
|
||||
enabled: false
|
||||
}
|
||||
}
|
||||
|
||||
profiling: {
|
||||
enabled: false
|
||||
port: 65432
|
||||
}
|
||||
|
||||
resolver: {
|
||||
enabled: true | *false
|
||||
dir: "/data/resolver"
|
||||
|
||||
//###########################################################
|
||||
// stateful set -> volume claim templates -> resolver pvc
|
||||
//###########################################################
|
||||
pvc: {
|
||||
enabled: true
|
||||
size: "1Gi"
|
||||
storageClassName: null
|
||||
|
||||
// merge or patch the pvc
|
||||
// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#persistentvolumeclaim-v1-core
|
||||
merge: {}
|
||||
patch: []
|
||||
// defaults to "{{ include "nats.fullname" $ }}-resolver"
|
||||
name: null
|
||||
}
|
||||
|
||||
// merge or patch the resolver
|
||||
// https://docs.nats.io/running-a-nats-service/configuration/securing_nats/auth_intro/jwt/resolver
|
||||
merge: {
|
||||
type?: string
|
||||
interval?: string
|
||||
timeout?: string
|
||||
}
|
||||
patch: []
|
||||
}
|
||||
|
||||
// adds a prefix to the server name, which defaults to the pod name
|
||||
// helpful for ensuring server name is unique in a super cluster
|
||||
serverNamePrefix: ""
|
||||
|
||||
// merge or patch the nats config
|
||||
// https://docs.nats.io/running-a-nats-service/configuration
|
||||
// following special rules apply
|
||||
// 1. strings that start with << and end with >> will be unquoted
|
||||
// use this for variables and numbers with units
|
||||
// 2. keys ending in $include will be switched to include directives
|
||||
// keys are sorted alphabetically, use prefix before $includes to control includes ordering
|
||||
// paths should be relative to /etc/nats-config/nats.conf
|
||||
// example:
|
||||
//
|
||||
// merge:
|
||||
// $include: ./my-config.conf
|
||||
// zzz$include: ./my-config-last.conf
|
||||
// server_name: nats
|
||||
// authorization:
|
||||
// token: << $TOKEN >>
|
||||
// jetstream:
|
||||
// max_memory_store: << 1GB >>
|
||||
//
|
||||
// will yield the config:
|
||||
// {
|
||||
// include ./my-config.conf;
|
||||
// "authorization": {
|
||||
// "token": $TOKEN
|
||||
// },
|
||||
// "jetstream": {
|
||||
// "max_memory_store": 1GB
|
||||
// },
|
||||
// "server_name": "nats",
|
||||
// include ./my-config-last.conf;
|
||||
// }
|
||||
merge: {
|
||||
operator?: string
|
||||
system_account?: string
|
||||
resolver_preload?: [string]: string
|
||||
}
|
||||
patch: []
|
||||
}
|
||||
|
||||
//###########################################################
|
||||
// stateful set -> pod template -> nats container
|
||||
//###########################################################
|
||||
container: {
|
||||
image: {
|
||||
repository: "nats"
|
||||
tag: "2.10.12-alpine"
|
||||
pullPolicy: null
|
||||
registry: null
|
||||
}
|
||||
|
||||
// container port options
|
||||
// must be enabled in the config section also
|
||||
// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#containerport-v1-core
|
||||
ports: {
|
||||
nats: {}
|
||||
leafnodes: {}
|
||||
websocket: {}
|
||||
mqtt: {}
|
||||
cluster: {}
|
||||
gateway: {}
|
||||
monitor: {}
|
||||
profiling: {}
|
||||
}
|
||||
|
||||
// map with key as env var name, value can be string or map
|
||||
// example:
|
||||
//
|
||||
// env:
|
||||
// GOMEMLIMIT: 7GiB
|
||||
// TOKEN:
|
||||
// valueFrom:
|
||||
// secretKeyRef:
|
||||
// name: nats-auth
|
||||
// key: token
|
||||
env: {}
|
||||
|
||||
// merge or patch the container
|
||||
// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core
|
||||
merge: {}
|
||||
patch: []
|
||||
}
|
||||
|
||||
//###########################################################
|
||||
// stateful set -> pod template -> reloader container
|
||||
//###########################################################
|
||||
reloader: {
|
||||
enabled: true
|
||||
image: {
|
||||
repository: "natsio/nats-server-config-reloader"
|
||||
tag: "0.14.1"
|
||||
pullPolicy: null
|
||||
registry: null
|
||||
}
|
||||
|
||||
// env var map, see nats.env for an example
|
||||
env: {}
|
||||
|
||||
// all nats container volume mounts with the following prefixes
|
||||
// will be mounted into the reloader container
|
||||
natsVolumeMountPrefixes: ["/etc/"]
|
||||
|
||||
// merge or patch the container
|
||||
// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core
|
||||
merge: {}
|
||||
patch: []
|
||||
}
|
||||
|
||||
//###########################################################
|
||||
// stateful set -> pod template -> prom-exporter container
|
||||
//###########################################################
|
||||
// config.monitor must be enabled
|
||||
promExporter: {
|
||||
enabled: true | *false
|
||||
image: {
|
||||
repository: "natsio/prometheus-nats-exporter"
|
||||
tag: "0.14.0"
|
||||
pullPolicy: null
|
||||
registry: null
|
||||
}
|
||||
|
||||
port: 7777
|
||||
// env var map, see nats.env for an example
|
||||
env: {}
|
||||
|
||||
// merge or patch the container
|
||||
// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core
|
||||
merge: {}
|
||||
patch: []
|
||||
|
||||
//###########################################################
|
||||
// prometheus pod monitor
|
||||
//###########################################################
|
||||
podMonitor: {
|
||||
enabled: true | *false
|
||||
|
||||
// merge or patch the pod monitor
|
||||
// https://prometheus-operator.dev/docs/operator/api/#monitoring.coreos.com/v1.PodMonitor
|
||||
merge: {}
|
||||
patch: []
|
||||
// defaults to "{{ include "nats.fullname" $ }}"
|
||||
name: null
|
||||
}
|
||||
}
|
||||
|
||||
//###########################################################
|
||||
// service
|
||||
//###########################################################
|
||||
service: {
|
||||
enabled: true
|
||||
|
||||
// service port options
|
||||
// additional boolean field enable to control whether port is exposed in the service
|
||||
// must be enabled in the config section also
|
||||
// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#serviceport-v1-core
|
||||
ports: {
|
||||
nats: enabled: true
|
||||
leafnodes: enabled: true
|
||||
websocket: enabled: true
|
||||
mqtt: enabled: true
|
||||
cluster: enabled: false
|
||||
gateway: enabled: false
|
||||
monitor: enabled: false
|
||||
profiling: enabled: false
|
||||
}
|
||||
|
||||
// merge or patch the service
|
||||
// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#service-v1-core
|
||||
merge: {}
|
||||
patch: []
|
||||
// defaults to "{{ include "nats.fullname" $ }}"
|
||||
name: null
|
||||
}
|
||||
|
||||
//###########################################################
|
||||
// other nats extension points
|
||||
//###########################################################
|
||||
// stateful set
|
||||
statefulSet: {
|
||||
// merge or patch the stateful set
|
||||
// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#statefulset-v1-apps
|
||||
merge: {}
|
||||
patch: []
|
||||
// defaults to "{{ include "nats.fullname" $ }}"
|
||||
name: null
|
||||
}
|
||||
|
||||
// stateful set -> pod template
|
||||
podTemplate: {
|
||||
// adds a hash of the ConfigMap as a pod annotation
|
||||
// this will cause the StatefulSet to roll when the ConfigMap is updated
|
||||
configChecksumAnnotation: true
|
||||
|
||||
// map of topologyKey: topologySpreadConstraint
|
||||
// labelSelector will be added to match StatefulSet pods
|
||||
//
|
||||
// topologySpreadConstraints:
|
||||
// kubernetes.io/hostname:
|
||||
// maxSkew: 1
|
||||
//
|
||||
topologySpreadConstraints: {}
|
||||
|
||||
// merge or patch the pod template
|
||||
// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#pod-v1-core
|
||||
merge: {}
|
||||
patch: []
|
||||
}
|
||||
|
||||
// headless service
|
||||
headlessService: {
|
||||
// merge or patch the headless service
|
||||
// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#service-v1-core
|
||||
merge: {}
|
||||
patch: []
|
||||
// defaults to "{{ include "nats.fullname" $ }}-headless"
|
||||
name: null
|
||||
}
|
||||
|
||||
// config map
|
||||
configMap: {
|
||||
// merge or patch the config map
|
||||
// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#configmap-v1-core
|
||||
merge: {}
|
||||
patch: []
|
||||
// defaults to "{{ include "nats.fullname" $ }}-config"
|
||||
name: null
|
||||
}
|
||||
|
||||
// pod disruption budget
|
||||
podDisruptionBudget: {
|
||||
enabled: true
|
||||
// merge or patch the pod disruption budget
|
||||
// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#poddisruptionbudget-v1-policy
|
||||
merge: {}
|
||||
patch: []
|
||||
// defaults to "{{ include "nats.fullname" $ }}"
|
||||
name: null
|
||||
}
|
||||
|
||||
// service account
|
||||
serviceAccount: {
|
||||
enabled: false
|
||||
// merge or patch the service account
|
||||
// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#serviceaccount-v1-core
|
||||
merge: {}
|
||||
patch: []
|
||||
// defaults to "{{ include "nats.fullname" $ }}"
|
||||
name: null
|
||||
}
|
||||
|
||||
//###########################################################
|
||||
// natsBox
|
||||
//
|
||||
// NATS Box Deployment and associated resources
|
||||
//###########################################################
|
||||
natsBox: {
|
||||
enabled: true
|
||||
|
||||
//###########################################################
|
||||
// NATS contexts
|
||||
//###########################################################
|
||||
contexts: {
|
||||
default: {
|
||||
creds: {
|
||||
// set contents in order to create a secret with the creds file contents
|
||||
contents: null
|
||||
// set secretName in order to mount an existing secret to dir
|
||||
secretName: null
|
||||
// defaults to /etc/nats-creds/<context-name>
|
||||
dir: null
|
||||
key: "nats.creds"
|
||||
}
|
||||
nkey: {
|
||||
// set contents in order to create a secret with the nkey file contents
|
||||
contents: null
|
||||
// set secretName in order to mount an existing secret to dir
|
||||
secretName: null
|
||||
// defaults to /etc/nats-nkeys/<context-name>
|
||||
dir: null
|
||||
key: "nats.nk"
|
||||
}
|
||||
// used to connect with client certificates
|
||||
tls: {
|
||||
// set secretName in order to mount an existing secret to dir
|
||||
secretName: null
|
||||
// defaults to /etc/nats-certs/<context-name>
|
||||
dir: null
|
||||
cert: "tls.crt"
|
||||
key: "tls.key"
|
||||
}
|
||||
|
||||
// merge or patch the context
|
||||
// https://docs.nats.io/using-nats/nats-tools/nats_cli#nats-contexts
|
||||
merge: {}
|
||||
patch: []
|
||||
}
|
||||
}
|
||||
|
||||
// name of context to select by default
|
||||
defaultContextName: "default"
|
||||
|
||||
//###########################################################
|
||||
// deployment -> pod template -> nats-box container
|
||||
//###########################################################
|
||||
container: {
|
||||
image: {
|
||||
repository: "natsio/nats-box"
|
||||
tag: "0.14.2"
|
||||
pullPolicy: null
|
||||
registry: null
|
||||
}
|
||||
|
||||
// env var map, see nats.env for an example
|
||||
env: {}
|
||||
|
||||
// merge or patch the container
|
||||
// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#container-v1-core
|
||||
merge: {}
|
||||
patch: []
|
||||
}
|
||||
|
||||
//###########################################################
|
||||
// other nats-box extension points
|
||||
//###########################################################
|
||||
// deployment
|
||||
deployment: {
|
||||
// merge or patch the deployment
|
||||
// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#deployment-v1-apps
|
||||
merge: {}
|
||||
patch: []
|
||||
// defaults to "{{ include "nats.fullname" $ }}-box"
|
||||
name: null
|
||||
}
|
||||
|
||||
// deployment -> pod template
|
||||
podTemplate: {
|
||||
// merge or patch the pod template
|
||||
// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#pod-v1-core
|
||||
merge: {}
|
||||
patch: []
|
||||
}
|
||||
|
||||
// contexts secret
|
||||
contextsSecret: {
|
||||
// merge or patch the context secret
|
||||
// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#secret-v1-core
|
||||
merge: {}
|
||||
patch: []
|
||||
// defaults to "{{ include "nats.fullname" $ }}-box-contexts"
|
||||
name: null
|
||||
}
|
||||
|
||||
// contents secret
|
||||
contentsSecret: {
|
||||
// merge or patch the contents secret
|
||||
// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#secret-v1-core
|
||||
merge: {}
|
||||
patch: []
|
||||
// defaults to "{{ include "nats.fullname" $ }}-box-contents"
|
||||
name: null
|
||||
}
|
||||
|
||||
// service account
|
||||
serviceAccount: {
|
||||
enabled: false
|
||||
// merge or patch the service account
|
||||
// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.24/#serviceaccount-v1-core
|
||||
merge: {}
|
||||
patch: []
|
||||
// defaults to "{{ include "nats.fullname" $ }}-box"
|
||||
name: null
|
||||
}
|
||||
}
|
||||
|
||||
//###############################################################################
|
||||
// Extra user-defined resources
|
||||
//###############################################################################
|
||||
//
|
||||
// add arbitrary user-generated resources
|
||||
// example:
|
||||
//
|
||||
// config:
|
||||
// websocket:
|
||||
// enabled: true
|
||||
// extraResources:
|
||||
// - apiVersion: networking.istio.io/v1beta1
|
||||
// kind: VirtualService
|
||||
// metadata:
|
||||
// name:
|
||||
// $tplYaml: >
|
||||
// {{ include "nats.fullname" $ | quote }}
|
||||
// labels:
|
||||
// $tplYaml: |
|
||||
// {{ include "nats.labels" $ }}
|
||||
// spec:
|
||||
// hosts:
|
||||
// - demo.nats.io
|
||||
// gateways:
|
||||
// - my-gateway
|
||||
// http:
|
||||
// - name: default
|
||||
// match:
|
||||
// - name: root
|
||||
// uri:
|
||||
// exact: /
|
||||
// route:
|
||||
// - destination:
|
||||
// host:
|
||||
// $tplYaml: >
|
||||
// {{ .Values.service.name | quote }}
|
||||
// port:
|
||||
// number:
|
||||
// $tplYaml: >
|
||||
// {{ .Values.config.websocket.port }}
|
||||
//
|
||||
extraResources: []
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# This script initializes authorization for a nats cluster. The process is:
|
||||
#
|
||||
# Locally:
|
||||
# 1. Generate the nats operator jwt.
|
||||
# 2. Generate a SYS account jwt issued by the operator.
|
||||
# 3. Store both into vault
|
||||
#
|
||||
# When nats is deployed an ExternalSecret populates auth.conf which is included
|
||||
# into nats.conf. This approach allows helm values to be used for most things
|
||||
# except for secrets.
|
||||
#
|
||||
# Clean up by removing the nsc directory.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
tmpdir="$(mktemp -d)"
|
||||
finish() {
|
||||
[[ -d "$tmpdir" ]] && rm -rf "$tmpdir"
|
||||
}
|
||||
trap finish EXIT
|
||||
|
||||
PARENT="$(cd "$(dirname $0)" && pwd)"
|
||||
: "${OPERATOR_NAME:="Holos"}"
|
||||
|
||||
: "${OIX_NAMESPACE:=$(kubectl config view --minify --flatten -ojsonpath='{.contexts[0].context.namespace}')}"
|
||||
nsc="${HOME}/.bin/nsc"
|
||||
|
||||
ROOT="${PARENT}/${OIX_NAMESPACE}/nsc"
|
||||
export NKEYS_PATH="${ROOT}/nkeys"
|
||||
export NSC_HOME="${ROOT}/accounts"
|
||||
|
||||
mkdir -p "$NKEYS_PATH"
|
||||
mkdir -p "$NSC_HOME"
|
||||
|
||||
# Install nsc if not already installed
|
||||
if ! [[ -x $nsc ]]; then
|
||||
platform="$(kubectl version --output=json | jq .clientVersion.platform -r)"
|
||||
platform="${platform//\//-}"
|
||||
curl -fSLo "${tmpdir}/nsc.zip" "https://github.com/nats-io/nsc/releases/download/v2.8.6/nsc-${platform}.zip"
|
||||
(cd "${tmpdir}" && unzip nsc.zip)
|
||||
sudo install -o 0 -g 0 -m 0755 "${tmpdir}/nsc" $nsc
|
||||
fi
|
||||
|
||||
echo "export NKEYS_PATH='${NKEYS_PATH}'" > "${ROOT}/nsc.env"
|
||||
echo "export NSC_HOME='${NSC_HOME}'" >> "${ROOT}/nsc.env"
|
||||
# use kubectl port-forward nats-headless 4222
|
||||
echo "export NATS_URL='nats://localhost:4222'" >> "${ROOT}/nsc.env"
|
||||
echo "export NATS_CREDS='${ROOT}/nkeys/creds/${OPERATOR_NAME}/SYS/sys.creds'" >> "${ROOT}/nsc.env"
|
||||
|
||||
echo "export NATS_CA='${ROOT}/ca.crt'" >> "${ROOT}/nsc.env"
|
||||
echo "export NATS_CERT='${ROOT}/tls.crt'" >> "${ROOT}/nsc.env"
|
||||
echo "export NATS_KEY='${ROOT}/tls.key'" >> "${ROOT}/nsc.env"
|
||||
|
||||
$nsc --data-dir="${ROOT}/stores" list operators
|
||||
|
||||
# Create operator
|
||||
$nsc add operator --name "${OPERATOR_NAME}"
|
||||
# Create system account
|
||||
$nsc add account --name SYS
|
||||
$nsc add user --name sys
|
||||
# Create account for STAN purposes.
|
||||
$nsc add account --name STAN
|
||||
$nsc add user --name stan
|
||||
|
||||
# Generate an auth config compatible with the StatefulSet mounting the
|
||||
# nats-jwt-pvc PersistentVolumeClaim at path /data/accounts
|
||||
$nsc generate config --sys-account SYS --nats-resolver \
|
||||
| sed "s,dir.*jwt',dir: '/data/accounts'" \
|
||||
> "${ROOT}/auth.conf"
|
||||
|
||||
# Store the auth config in vault.
|
||||
# vault kv put kv/${OIX_CLUSTER_NAME}/kube-namespace/holos-dev/nats-auth-config "auth.conf=@${tmpdir}/auth.conf"
|
||||
# Store the SYS creds in vault for use by the nack controller.
|
||||
# vault kv put kv/${OIX_CLUSTER_NAME}/kube-namespace/holos-dev/nats-sys-creds "sys.creds=@${OIX_CLUSTER_NAME}/nsc/nkeys/creds/${OPERATOR_NAME}/SYS/sys.creds"
|
||||
|
||||
echo "After deploying the nats component, use the get-cert command to fetch the client cert."
|
||||
|
||||
echo "Use kubectl port-forward svc/nats-headless 4222" >&2
|
||||
echo "source ${ROOT}/nsc.env to make it all work." >&2
|
||||
@@ -21,12 +21,12 @@ spec: components: KubernetesObjectsList: [
|
||||
// GatewayServers represents all hosts for all VirtualServices in the cluster attached to Gateway/default
|
||||
// NOTE: This is a critical structure because the default Gateway should be used in most cases.
|
||||
let GatewayServers = {
|
||||
// Critical Feature: Map all Project hosts to the default Gateway.
|
||||
for Project in _Projects {
|
||||
for server in (#ProjectTemplate & {project: Project}).ClusterGatewayServers {
|
||||
(server.port.name): server
|
||||
}
|
||||
(#ProjectTemplate & {project: Project}).ClusterDefaultGatewayServers
|
||||
}
|
||||
|
||||
// TODO: Refactor to use FQDN as key
|
||||
for k, svc in #OptionalServices {
|
||||
if svc.enabled && list.Contains(svc.clusterNames, #ClusterName) {
|
||||
for server in svc.servers {
|
||||
@@ -35,6 +35,7 @@ let GatewayServers = {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Remove? Why aren't these part of the platform project?
|
||||
if #PlatformServers[#ClusterName] != _|_ {
|
||||
for server in #PlatformServers[#ClusterName] {
|
||||
(server.port.name): server
|
||||
@@ -52,6 +53,11 @@ let OBJECTS = #APIObjects & {
|
||||
spec: servers: [for x in GatewayServers {x}]
|
||||
}
|
||||
|
||||
// Manage an ExternalSecret for each server defined in the default Gateway to sync the cert.
|
||||
for Server in Gateway.default.spec.servers {
|
||||
ExternalSecret: "\(Server.tls.credentialName)": metadata: namespace: "istio-ingress"
|
||||
}
|
||||
|
||||
for k, svc in #OptionalServices {
|
||||
if svc.enabled && list.Contains(svc.clusterNames, #ClusterName) {
|
||||
for k, s in svc.servers {
|
||||
|
||||
@@ -8,7 +8,7 @@ let ComponentName = "\(#InstancePrefix)-ingress"
|
||||
|
||||
spec: components: HelmChartList: [
|
||||
#HelmChart & {
|
||||
_dependsOn: "prod-secrets-namespaces": _
|
||||
_dependsOn: "prod-secrets-stores": _
|
||||
_dependsOn: "\(#InstancePrefix)-istio-base": _
|
||||
_dependsOn: "\(#InstancePrefix)-istiod": _
|
||||
|
||||
@@ -76,6 +76,10 @@ let RedirectMetaName = {
|
||||
|
||||
let OBJECTS = #APIObjects & {
|
||||
apiObjects: {
|
||||
ExternalSecret: "istio-ingress-mtls-cert": #ExternalSecret & {
|
||||
metadata: name: "istio-ingress-mtls-cert"
|
||||
metadata: namespace: #TargetNamespace
|
||||
}
|
||||
Gateway: {
|
||||
"\(RedirectMetaName.name)": #Gateway & {
|
||||
metadata: RedirectMetaName
|
||||
|
||||
@@ -4,7 +4,7 @@ package holos
|
||||
|
||||
let Namespace = "prod-platform"
|
||||
|
||||
// FYI: kube-prometheus-stack is a large umbrella chart what brings in other large charts like
|
||||
// FYI: kube-prometheus-stack is a large umbrella chart that brings in other large charts like
|
||||
// [grafana](https://github.com/grafana/helm-charts/tree/main/charts/grafana).
|
||||
// This may make affect maintainability. Consider breaking the integration down into
|
||||
// constituent charts represented as holos component instances.
|
||||
@@ -77,7 +77,7 @@ spec: components: HelmChartList: [
|
||||
token_url: OIDC.token_endpoint
|
||||
api_url: OIDC.userinfo_endpoint
|
||||
use_pkce: true
|
||||
name_attribute_path: name
|
||||
name_attribute_path: "name"
|
||||
// TODO: Lift the admin, editor, and viewer group names up to the plaform config struct.
|
||||
role_attribute_path: "contains(groups[*], 'prod-cluster-admin') && 'Admin' || contains(groups[*], 'prod-cluster-editor') && 'Editor' || 'Viewer'"
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
package holos
|
||||
|
||||
// for Project in _Projects {
|
||||
// spec: components: resources: (#ProjectTemplate & {project: Project}).workload.resources
|
||||
// }
|
||||
|
||||
let Namespace = "jeff-holos"
|
||||
|
||||
#Kustomization: spec: targetNamespace: Namespace
|
||||
|
||||
spec: components: HelmChartList: [
|
||||
#HelmChart & {
|
||||
metadata: name: "jeff-holos-nats"
|
||||
namespace: Namespace
|
||||
_dependsOn: "prod-secrets-stores": _
|
||||
chart: {
|
||||
name: "nats"
|
||||
version: "1.1.10"
|
||||
repository: NatsRepository
|
||||
}
|
||||
},
|
||||
#HelmChart & {
|
||||
metadata: name: "jeff-holos-nack"
|
||||
namespace: Namespace
|
||||
_dependsOn: "jeff-holos-nats": _
|
||||
chart: {
|
||||
name: "nack"
|
||||
version: "0.25.2"
|
||||
repository: NatsRepository
|
||||
}
|
||||
},
|
||||
]
|
||||
|
||||
let NatsRepository = {
|
||||
name: "nats"
|
||||
url: "https://nats-io.github.io/k8s/helm/charts/"
|
||||
}
|
||||
@@ -4,15 +4,23 @@ package holos
|
||||
|
||||
let ZitadelProjectID = 257713952794870157
|
||||
|
||||
let AllClusters = {
|
||||
// platform level services typically run in the core cluster pair.
|
||||
core1: _
|
||||
core2: _
|
||||
// for development, probably wouldn't run these services in the workload clusters.
|
||||
k1: _
|
||||
k2: _
|
||||
k3: _
|
||||
k4: _
|
||||
k5: _
|
||||
}
|
||||
|
||||
_Projects: #Projects & {
|
||||
// The platform project is required and where platform services reside. ArgoCD, Grafana, Prometheus, etc...
|
||||
platform: {
|
||||
resourceId: ZitadelProjectID
|
||||
// platform level services typically run in the core cluster pair.
|
||||
clusters: core1: _
|
||||
clusters: core2: _
|
||||
// for development, probably wouldn't run these services in the workload clusters.
|
||||
clusters: k2: _
|
||||
clusters: AllClusters
|
||||
// Services hosted in the platform project
|
||||
hosts: argocd: _
|
||||
hosts: grafana: _
|
||||
@@ -21,8 +29,9 @@ _Projects: #Projects & {
|
||||
|
||||
holos: {
|
||||
resourceId: ZitadelProjectID
|
||||
clusters: k1: _
|
||||
clusters: k2: _
|
||||
domain: "holos.run"
|
||||
clusters: AllClusters
|
||||
|
||||
environments: {
|
||||
prod: stage: "prod"
|
||||
dev: stage: "dev"
|
||||
@@ -30,6 +39,13 @@ _Projects: #Projects & {
|
||||
gary: stage: dev.stage
|
||||
nate: stage: dev.stage
|
||||
}
|
||||
|
||||
// app is the holos web app and grpc api.
|
||||
hosts: app: _
|
||||
// provision is the choria broker provisioning system.
|
||||
hosts: provision: _
|
||||
// nats is the nats service holos controller machine room agents connect after provisioning.
|
||||
hosts: nats: _
|
||||
}
|
||||
|
||||
iam: {
|
||||
@@ -0,0 +1,40 @@
|
||||
package holos
|
||||
|
||||
// Certificate used by the ingress to connect to services using a platform
|
||||
// issued certificate but which are not using istio sidecar injection.
|
||||
// Examples are keycloak, vault, nats, choria, etc...
|
||||
|
||||
let Namespace = "istio-ingress"
|
||||
let CertName = "istio-ingress-mtls-cert"
|
||||
|
||||
spec: components: KubernetesObjectsList: [
|
||||
#KubernetesObjects & {
|
||||
_dependsOn: "prod-platform-issuer": _
|
||||
|
||||
metadata: name: CertName
|
||||
apiObjectMap: OBJECTS.apiObjectMap
|
||||
},
|
||||
]
|
||||
|
||||
let OBJECTS = #APIObjects & {
|
||||
apiObjects: {
|
||||
Certificate: "\(CertName)": #Certificate & {
|
||||
metadata: {
|
||||
name: CertName
|
||||
namespace: Namespace
|
||||
}
|
||||
spec: {
|
||||
secretName: metadata.name
|
||||
issuerRef: kind: "ClusterIssuer"
|
||||
issuerRef: name: "platform-issuer"
|
||||
commonName: "istio-ingress"
|
||||
dnsNames: [
|
||||
"istio-ingress",
|
||||
"istio-ingress.\(Namespace)",
|
||||
"istio-ingress.\(Namespace).svc",
|
||||
"istio-ingress.\(Namespace).svc.cluster.local",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
package holos
|
||||
|
||||
// Refer to https://cert-manager.io/docs/configuration/selfsigned/#bootstrapping-ca-issuers
|
||||
|
||||
let Namespace = "cert-manager"
|
||||
|
||||
spec: components: KubernetesObjectsList: [
|
||||
#KubernetesObjects & {
|
||||
metadata: name: "prod-platform-issuer"
|
||||
|
||||
_dependsOn: "prod-mesh-certmanager": _
|
||||
apiObjectMap: OBJECTS.apiObjectMap
|
||||
},
|
||||
]
|
||||
|
||||
let SelfSigned = "platform-selfsigned"
|
||||
let PlatformIssuer = "platform-issuer"
|
||||
|
||||
let OBJECTS = #APIObjects & {
|
||||
apiObjects: {
|
||||
ClusterIssuer: {
|
||||
"\(SelfSigned)": #ClusterIssuer & {
|
||||
metadata: name: SelfSigned
|
||||
spec: selfSigned: {}
|
||||
}
|
||||
}
|
||||
Certificate: {
|
||||
"\(PlatformIssuer)": #Certificate & {
|
||||
metadata: name: PlatformIssuer
|
||||
metadata: namespace: Namespace
|
||||
spec: {
|
||||
isCA: true
|
||||
commonName: PlatformIssuer
|
||||
secretName: PlatformIssuer
|
||||
privateKey: algorithm: "ECDSA"
|
||||
privateKey: size: 256
|
||||
issuerRef: {
|
||||
name: SelfSigned
|
||||
kind: "ClusterIssuer"
|
||||
group: "cert-manager.io"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ClusterIssuer: {
|
||||
"\(PlatformIssuer)": #ClusterIssuer & {
|
||||
metadata: name: PlatformIssuer
|
||||
spec: ca: secretName: PlatformIssuer
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
# Platform Issuer
|
||||
|
||||
The platform issuer is a self signed root certificate authority which acts as a private pki for the platform. Used to issue certificates for use internally within the platform in a way that supports multi-cluster communication.
|
||||
|
||||
Refer to [Bootstrapping CA Issuers](https://cert-manager.io/docs/configuration/selfsigned/#bootstrapping-ca-issuers)
|
||||
@@ -1,5 +1,11 @@
|
||||
package holos
|
||||
|
||||
for Project in _Projects {
|
||||
spec: components: resources: (#ProjectTemplate & {project: Project}).provisioner.resources
|
||||
|
||||
// Debugging variable to enable inspecting the project host data:
|
||||
// cue eval --out json -t cluster=provisioner ./platforms/reference/clusters/provisioner/projects/... -e _ProjectHosts.holos > hosts.json
|
||||
let ProjectData = (#ProjectTemplate & {project: Project})
|
||||
_ProjectHosts: "\(Project.name)": ProjectData.ProjectHosts
|
||||
|
||||
spec: components: resources: ProjectData.provisioner.resources
|
||||
}
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
package holos
|
||||
|
||||
// Platform level definition of a project.
|
||||
#Project: {
|
||||
name: string
|
||||
|
||||
// All projects have at least a prod and dev environment and stage.
|
||||
|
||||
// Omit the prod stage segment from hostnames. foo.holos.run not foo.prod.holos.run
|
||||
stages: prod: stageSegments: []
|
||||
environments: prod: stage: "prod"
|
||||
// Omit the prod env segment from hostnames. foo.holos.run not prod.foo.holos.run
|
||||
environments: prod: envSegments: []
|
||||
|
||||
stages: dev: _
|
||||
environments: dev: stage: "dev"
|
||||
// Omit the dev env segment from hostnames. foo.dev.holos.run not dev.foo.dev.holos.run
|
||||
environments: dev: envSegments: []
|
||||
|
||||
// environments share the stage segments of their stage.
|
||||
environments: [_]: {
|
||||
stage: string
|
||||
stageSegments: stages[stage].stageSegments
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package holos
|
||||
137
docs/examples/project-hosts.cue
Normal file
137
docs/examples/project-hosts.cue
Normal file
@@ -0,0 +1,137 @@
|
||||
package holos
|
||||
|
||||
import "strings"
|
||||
|
||||
// #ProjectHosts represents all of the hosts associated with the project
|
||||
// organized for use in Certificates, Gateways, VirtualServices.
|
||||
#ProjectHosts: {
|
||||
project: #Project
|
||||
|
||||
// Hosts map key fqdn to host to reduce into structs organized by stage,
|
||||
// canonical name, etc... The flat nature and long list of properties is
|
||||
// intended to make it straight forward to derive another struct for Gateways,
|
||||
// VirtualServices, Certificates, AuthProxy cookie domains, etc...
|
||||
Hosts: {
|
||||
for Env in project.environments {
|
||||
for Host in project.hosts {
|
||||
// Global hostname, e.g. app.holos.run
|
||||
let CertInfo = (#MakeCertInfo & {
|
||||
host: Host
|
||||
env: Env
|
||||
domain: project.domain
|
||||
clusterMap: project.clusters
|
||||
}).CertInfo
|
||||
|
||||
"\(CertInfo.fqdn)": CertInfo
|
||||
|
||||
// Cluster hostname, e.g. app.east1.holos.run, app.west1.holos.run
|
||||
for Cluster in project.clusters {
|
||||
let CertInfo = (#MakeCertInfo & {
|
||||
host: Host
|
||||
env: Env
|
||||
domain: project.domain
|
||||
cluster: Cluster.name
|
||||
clusterMap: project.clusters
|
||||
}).CertInfo
|
||||
|
||||
"\(CertInfo.fqdn)": CertInfo
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// #MakeCertInfo provides dns info for a certificate
|
||||
// Refer to: https://github.com/holos-run/holos/issues/66#issuecomment-2027562626
|
||||
#MakeCertInfo: {
|
||||
host: #Host
|
||||
env: #Environment
|
||||
domain: string
|
||||
cluster: string
|
||||
clusterMap: #ClusterMap
|
||||
|
||||
let Stage = #StageInfo & {name: env.stage, project: env.project}
|
||||
let Env = env
|
||||
|
||||
// DNS segments from left to right.
|
||||
let EnvSegments = env.envSegments
|
||||
|
||||
WildcardSegments: [...string]
|
||||
if len(env.envSegments) > 0 {
|
||||
WildcardSegments: ["*"]
|
||||
}
|
||||
|
||||
let HostSegments = [host.name]
|
||||
|
||||
let StageSegments = env.stageSegments
|
||||
|
||||
ClusterSegments: [...string]
|
||||
if cluster != _|_ {
|
||||
ClusterSegments: [cluster]
|
||||
}
|
||||
|
||||
let DomainSegments = [domain]
|
||||
|
||||
// Assemble the segments
|
||||
|
||||
let FQDN = EnvSegments + HostSegments + StageSegments + ClusterSegments + DomainSegments
|
||||
let WILDCARD = WildcardSegments + HostSegments + StageSegments + ClusterSegments + DomainSegments
|
||||
let CANONICAL = HostSegments + StageSegments + DomainSegments
|
||||
|
||||
CertInfo: #CertInfo & {
|
||||
fqdn: strings.Join(FQDN, ".")
|
||||
wildcard: strings.Join(WILDCARD, ".")
|
||||
canonical: strings.Join(CANONICAL, ".")
|
||||
|
||||
project: name: Env.project
|
||||
stage: #StageOrEnvRef & {
|
||||
name: Stage.name
|
||||
slug: Stage.slug
|
||||
namespace: Stage.namespace
|
||||
}
|
||||
env: #StageOrEnvRef & {
|
||||
name: Env.name
|
||||
slug: Env.slug
|
||||
namespace: Env.namespace
|
||||
}
|
||||
|
||||
if cluster != _|_ {
|
||||
// Host is valid on a single cluster.
|
||||
clusters: "\(cluster)": _
|
||||
}
|
||||
|
||||
if cluster == _|_ {
|
||||
// Host is valid on all project clusters.
|
||||
clusters: clusterMap
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// #CertInfo defines the attributes associated with a fully qualfied domain name
|
||||
#CertInfo: {
|
||||
// fqdn is the fully qualified domain name, never a wildcard.
|
||||
fqdn: string
|
||||
// canonical is the canonical name this name may be an alternate name for.
|
||||
canonical: string
|
||||
// wildcard may replace the left most segment fqdn with a wildcard to consolidate cert dnsNames. If not a wildcad, must be fqdn
|
||||
wildcard: string
|
||||
|
||||
// Project, stage and env attributes for mapping and collecting.
|
||||
project: name: string
|
||||
|
||||
stage: #StageOrEnvRef
|
||||
env: #StageOrEnvRef
|
||||
|
||||
// clusters represents the cluster names the fqdn is valid on.
|
||||
clusters: #ClusterMap
|
||||
// hosts are always valid on the provisioner cluster
|
||||
clusters: provisioner: _
|
||||
}
|
||||
|
||||
#ClusterMap: [Name=string]: #Cluster & {name: Name}
|
||||
|
||||
#StageOrEnvRef: {
|
||||
name: string
|
||||
slug: string
|
||||
namespace: string
|
||||
}
|
||||
45
docs/examples/project-template-provisioner-certs.cue
Normal file
45
docs/examples/project-template-provisioner-certs.cue
Normal file
@@ -0,0 +1,45 @@
|
||||
package holos
|
||||
|
||||
#ProjectTemplate: {
|
||||
project: _
|
||||
GatewayServers: _
|
||||
|
||||
// Sort GatewayServers by the tls credentialName to issue wildcards
|
||||
let GatewayCerts = {
|
||||
for FQDN, Server in GatewayServers {
|
||||
let CertInfo = Server._CertInfo
|
||||
|
||||
// Sort into stage for the holos components, e.g. prod-iam-certs, dev-iam-certs
|
||||
"\(CertInfo.stage.slug)": {
|
||||
"\(Server.tls.credentialName)": #Certificate & {
|
||||
|
||||
// Store the dnsNames in a struct so they can be collected into a list
|
||||
_dnsNames: "\(CertInfo.wildcard)": CertInfo.wildcard
|
||||
|
||||
metadata: name: CertInfo.canonical & Server.tls.credentialName
|
||||
metadata: namespace: "istio-ingress"
|
||||
spec: {
|
||||
commonName: CertInfo.canonical
|
||||
secretName: CertInfo.canonical & Server.tls.credentialName
|
||||
dnsNames: [for x in _dnsNames {x}]
|
||||
issuerRef: {
|
||||
kind: "ClusterIssuer"
|
||||
name: "letsencrypt"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Resources to be managed on the provisioner cluster.
|
||||
provisioner: resources: {
|
||||
for stage in project.stages {
|
||||
"\(stage.slug)-certs": #KubernetesObjects & {
|
||||
apiObjectMap: (#APIObjects & {
|
||||
apiObjects: Certificate: GatewayCerts[stage.slug]
|
||||
}).apiObjectMap
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,87 +1,74 @@
|
||||
package holos
|
||||
|
||||
import "encoding/yaml"
|
||||
import (
|
||||
h "github.com/holos-run/holos/api/v1alpha1"
|
||||
"encoding/yaml"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Platform level definition of a project.
|
||||
#Project: {
|
||||
name: string
|
||||
// let SourceLoc = "project-template.cue"
|
||||
|
||||
// All projects have at least a prod environment and stage.
|
||||
stages: prod: stageSegments: []
|
||||
environments: prod: stage: "prod"
|
||||
environments: prod: envSegments: []
|
||||
stages: dev: _
|
||||
environments: dev: stage: "dev"
|
||||
environments: dev: envSegments: []
|
||||
// Ensure at least the project name is a short hostname. Additional may be added.
|
||||
hosts: (name): _
|
||||
#ProjectTemplate: {
|
||||
project: #Project
|
||||
|
||||
// environments share the stage segments of their stage.
|
||||
environments: [_]: {
|
||||
stage: string
|
||||
stageSegments: stages[stage].stageSegments
|
||||
// workload cluster resources
|
||||
workload: resources: [Name=_]: h.#KubernetesObjects & {
|
||||
metadata: name: Name
|
||||
}
|
||||
|
||||
// provisioner cluster resources
|
||||
provisioner: resources: [Name=_]: h.#KubernetesObjects & {
|
||||
metadata: name: Name
|
||||
}
|
||||
}
|
||||
|
||||
// Reference Platform Project Template
|
||||
#ProjectTemplate: {
|
||||
project: #Project
|
||||
let Project = project
|
||||
|
||||
// GatewayServers maps Gateway spec.servers #GatewayServer values indexed by stage then name.
|
||||
let GatewayServers = {
|
||||
// Initialize all stages, even if they have no environments.
|
||||
for stage in project.stages {
|
||||
(stage.name): {}
|
||||
}
|
||||
ProjectHosts: (#ProjectHosts & {project: Project}).Hosts
|
||||
|
||||
// For each stage, construct entries for the Gateway spec.servers.hosts field.
|
||||
for env in project.environments {
|
||||
(env.stage): {
|
||||
let Env = env
|
||||
let Stage = project.stages[env.stage]
|
||||
for host in (#EnvHosts & {project: Project, env: Env}).hosts {
|
||||
(host.name): #GatewayServer & {
|
||||
hosts: [
|
||||
"\(env.namespace)/\(host.name)",
|
||||
// Allow the authproxy VirtualService to match the project.authProxyPrefix path.
|
||||
"\(Stage.namespace)/\(host.name)",
|
||||
]
|
||||
port: host.port
|
||||
tls: credentialName: host.name
|
||||
tls: mode: "SIMPLE"
|
||||
// GatewayServers maps Gateway spec.servers #GatewayServer values indexed by stage then name.
|
||||
GatewayServers: {
|
||||
for FQDN, Host in ProjectHosts {
|
||||
// If the host is valid on the cluster being rendered
|
||||
if Host.clusters[#ClusterName] != _|_ {
|
||||
"\(FQDN)": #GatewayServer & {
|
||||
_CertInfo: Host
|
||||
hosts: [
|
||||
"\(Host.env.namespace)/\(FQDN)",
|
||||
// Allow the authproxy VirtualService to match the project.authProxyPrefix path.
|
||||
"\(Host.stage.namespace)/\(FQDN)",
|
||||
]
|
||||
port: {
|
||||
// NOTE: port names in servers must be unique: duplicate name https
|
||||
name: "https-" + strings.Replace(FQDN, ".", "-", -1)
|
||||
number: 443
|
||||
protocol: "HTTPS"
|
||||
}
|
||||
tls: credentialName: Host.canonical
|
||||
tls: mode: "SIMPLE"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ClusterGatewayServers provides a struct of Gateway servers for the current cluster.
|
||||
// ClusterDefaultGatewayServers provides a struct of Gateway servers for the current cluster.
|
||||
// This is intended for Gateway/default to add all servers to the default gateway.
|
||||
ClusterGatewayServers: {
|
||||
ClusterDefaultGatewayServers: {
|
||||
if project.clusters[#ClusterName] != _|_ {
|
||||
for Stage in project.stages {
|
||||
for server in GatewayServers[Stage.name] {
|
||||
(server.port.name): server
|
||||
}
|
||||
}
|
||||
GatewayServers
|
||||
}
|
||||
}
|
||||
|
||||
workload: resources: {
|
||||
// Provide resources only if the project is managed on --cluster-name
|
||||
// Provide resources only if the project is managed on the cluster specified
|
||||
// by --cluster-name
|
||||
if project.clusters[#ClusterName] != _|_ {
|
||||
for stage in project.stages {
|
||||
let Stage = stage
|
||||
|
||||
// Istio Gateway
|
||||
"\(stage.slug)-gateway": #KubernetesObjects & {
|
||||
apiObjectMap: (#APIObjects & {
|
||||
for host in GatewayServers[stage.name] {
|
||||
apiObjects: ExternalSecret: (host.tls.credentialName): metadata: namespace: "istio-ingress"
|
||||
}
|
||||
}).apiObjectMap
|
||||
}
|
||||
|
||||
// Manage auth-proxy in each stage
|
||||
if project.features.authproxy.enabled {
|
||||
"\(stage.slug)-authproxy": #KubernetesObjects & {
|
||||
@@ -114,90 +101,6 @@ import "encoding/yaml"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
provisioner: resources: {
|
||||
for stage in project.stages {
|
||||
"\(stage.slug)-certs": #KubernetesObjects & {
|
||||
apiObjectMap: (#APIObjects & {
|
||||
for host in GatewayServers[stage.name] {
|
||||
let CN = host.tls.credentialName
|
||||
apiObjects: Certificate: (CN): #Certificate & {
|
||||
metadata: name: CN
|
||||
metadata: namespace: "istio-ingress"
|
||||
spec: {
|
||||
commonName: CN
|
||||
dnsNames: [CN]
|
||||
secretName: CN
|
||||
issuerRef: {
|
||||
kind: "ClusterIssuer"
|
||||
name: "letsencrypt"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).apiObjectMap
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let HTTPBIN = {
|
||||
name: string | *"httpbin"
|
||||
project: #Project
|
||||
env: #Environment
|
||||
let Name = name
|
||||
let Stage = project.stages[env.stage]
|
||||
|
||||
let Metadata = {
|
||||
name: Name
|
||||
namespace: env.namespace
|
||||
labels: app: name
|
||||
}
|
||||
let Labels = {
|
||||
"app.kubernetes.io/name": Name
|
||||
"app.kubernetes.io/instance": env.slug
|
||||
"app.kubernetes.io/part-of": env.project
|
||||
"security.holos.run/authproxy": Stage.extAuthzProviderName
|
||||
}
|
||||
|
||||
apiObjects: {
|
||||
Deployment: (Name): #Deployment & {
|
||||
metadata: Metadata
|
||||
|
||||
spec: selector: matchLabels: Metadata.labels
|
||||
spec: template: {
|
||||
metadata: labels: Metadata.labels & #IstioSidecar & Labels
|
||||
spec: securityContext: seccompProfile: type: "RuntimeDefault"
|
||||
spec: containers: [{
|
||||
name: Name
|
||||
image: "quay.io/holos/mccutchen/go-httpbin"
|
||||
ports: [{containerPort: 8080}]
|
||||
securityContext: {
|
||||
seccompProfile: type: "RuntimeDefault"
|
||||
allowPrivilegeEscalation: false
|
||||
runAsNonRoot: true
|
||||
runAsUser: 8192
|
||||
runAsGroup: 8192
|
||||
capabilities: drop: ["ALL"]
|
||||
}}]
|
||||
}
|
||||
}
|
||||
Service: (Name): #Service & {
|
||||
metadata: Metadata
|
||||
spec: selector: Metadata.labels
|
||||
spec: ports: [
|
||||
{port: 80, targetPort: 8080, protocol: "TCP", name: "http"},
|
||||
]
|
||||
}
|
||||
VirtualService: (Name): #VirtualService & {
|
||||
metadata: Metadata
|
||||
let Project = project
|
||||
let Env = env
|
||||
spec: hosts: [for host in (#EnvHosts & {project: Project, env: Env}).hosts {host.name}]
|
||||
spec: gateways: ["istio-ingress/default"]
|
||||
spec: http: [{route: [{destination: host: Name}]}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AUTHPROXY configures one oauth2-proxy deployment for each host in each stage of a project. Multiple deployments per stage are used to narrow down the cookie domain.
|
||||
@@ -462,6 +365,65 @@ let AUTHPROXY = {
|
||||
}
|
||||
}
|
||||
|
||||
let HTTPBIN = {
|
||||
name: string | *"httpbin"
|
||||
project: #Project
|
||||
env: #Environment
|
||||
let Name = name
|
||||
let Stage = project.stages[env.stage]
|
||||
|
||||
let Metadata = {
|
||||
name: Name
|
||||
namespace: env.namespace
|
||||
labels: app: name
|
||||
}
|
||||
let Labels = {
|
||||
"app.kubernetes.io/name": Name
|
||||
"app.kubernetes.io/instance": env.slug
|
||||
"app.kubernetes.io/part-of": env.project
|
||||
"security.holos.run/authproxy": Stage.extAuthzProviderName
|
||||
}
|
||||
|
||||
apiObjects: {
|
||||
Deployment: (Name): #Deployment & {
|
||||
metadata: Metadata
|
||||
|
||||
spec: selector: matchLabels: Metadata.labels
|
||||
spec: template: {
|
||||
metadata: labels: Metadata.labels & #IstioSidecar & Labels
|
||||
spec: securityContext: seccompProfile: type: "RuntimeDefault"
|
||||
spec: containers: [{
|
||||
name: Name
|
||||
image: "quay.io/holos/mccutchen/go-httpbin"
|
||||
ports: [{containerPort: 8080}]
|
||||
securityContext: {
|
||||
seccompProfile: type: "RuntimeDefault"
|
||||
allowPrivilegeEscalation: false
|
||||
runAsNonRoot: true
|
||||
runAsUser: 8192
|
||||
runAsGroup: 8192
|
||||
capabilities: drop: ["ALL"]
|
||||
}}]
|
||||
}
|
||||
}
|
||||
Service: (Name): #Service & {
|
||||
metadata: Metadata
|
||||
spec: selector: Metadata.labels
|
||||
spec: ports: [
|
||||
{port: 80, targetPort: 8080, protocol: "TCP", name: "http"},
|
||||
]
|
||||
}
|
||||
VirtualService: (Name): #VirtualService & {
|
||||
metadata: Metadata
|
||||
let Project = project
|
||||
let Env = env
|
||||
spec: hosts: [for host in (#EnvHosts & {project: Project, env: Env}).hosts {host.name}]
|
||||
spec: gateways: ["istio-ingress/default"]
|
||||
spec: http: [{route: [{destination: host: Name}]}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// AUTHPOLICY configures the baseline AuthorizationPolicy and RequestAuthentication policy for each stage of each project.
|
||||
let AUTHPOLICY = {
|
||||
project: #Project
|
||||
@@ -1,12 +1,12 @@
|
||||
package holos
|
||||
|
||||
import h "github.com/holos-run/holos/api/v1alpha1"
|
||||
|
||||
import "strings"
|
||||
|
||||
// #Projects is a map of all the projects in the platform.
|
||||
#Projects: [Name=_]: #Project & {name: Name}
|
||||
|
||||
_Projects: #Projects
|
||||
|
||||
// The platform project is required and where platform services reside. ArgoCD, Grafana, Prometheus, etc...
|
||||
#Projects: platform: _
|
||||
|
||||
@@ -59,7 +59,7 @@ import "strings"
|
||||
}
|
||||
}
|
||||
|
||||
// features is YAGNI maybe?
|
||||
// Thes are useful to enable / disable.
|
||||
features: [Name=string]: #Feature & {name: Name}
|
||||
features: authproxy: _
|
||||
features: httpbin: _
|
||||
@@ -91,15 +91,25 @@ import "strings"
|
||||
name: string
|
||||
cluster?: string
|
||||
clusterSegments: [...string]
|
||||
wildcard: true | *false
|
||||
if cluster != _|_ {
|
||||
clusterSegments: [cluster]
|
||||
}
|
||||
let SEGMENTS = envSegments + [name] + stageSegments + clusterSegments + [#Platform.org.domain]
|
||||
_EnvSegments: [...string]
|
||||
if wildcard {
|
||||
if len(envSegments) > 0 {
|
||||
_EnvSegments: ["*"]
|
||||
}
|
||||
}
|
||||
if !wildcard {
|
||||
_EnvSegments: envSegments
|
||||
}
|
||||
let SEGMENTS = _EnvSegments + [name] + stageSegments + clusterSegments + [_Projects[project].domain]
|
||||
let NAMESEGMENTS = ["https"] + SEGMENTS
|
||||
host: {
|
||||
name: strings.Join(SEGMENTS, ".")
|
||||
port: {
|
||||
name: strings.Replace(strings.Join(NAMESEGMENTS, "-"), ".", "-", -1)
|
||||
name: strings.Replace(strings.Replace(strings.Join(NAMESEGMENTS, "-"), ".", "-", -1), "*", "wildcard", -1)
|
||||
number: 443
|
||||
protocol: "HTTPS"
|
||||
}
|
||||
@@ -107,17 +117,26 @@ import "strings"
|
||||
}
|
||||
}
|
||||
|
||||
#Stage: {
|
||||
#StageInfo: {
|
||||
name: string
|
||||
project: string
|
||||
slug: "\(name)-\(project)"
|
||||
// namespace is the system namespace for the project stage
|
||||
namespace: "\(name)-\(project)-system"
|
||||
}
|
||||
|
||||
#Stage: {
|
||||
#StageInfo
|
||||
name: string
|
||||
project: string
|
||||
namespace: string
|
||||
slug: string
|
||||
|
||||
// Manage a system namespace for each stage
|
||||
namespaces: [Name=_]: name: Name
|
||||
namespaces: (namespace): _
|
||||
namespaces: "\(namespace)": _
|
||||
// stageSegments are the stage portion of the dns segments
|
||||
stageSegments: [...string] | *[name]
|
||||
stageSegments: [] | *[name]
|
||||
// authProxyClientID is the ClientID registered with the oidc issuer.
|
||||
authProxyClientID: string
|
||||
// extAuthzProviderName is the provider name in the mesh config
|
||||
@@ -130,20 +149,6 @@ import "strings"
|
||||
enabled: true | *false
|
||||
}
|
||||
|
||||
#ProjectTemplate: {
|
||||
project: #Project
|
||||
|
||||
// workload cluster resources
|
||||
workload: resources: [Name=_]: h.#KubernetesObjects & {
|
||||
metadata: name: Name
|
||||
}
|
||||
|
||||
// provisioner cluster resources
|
||||
provisioner: resources: [Name=_]: h.#KubernetesObjects & {
|
||||
metadata: name: Name
|
||||
}
|
||||
}
|
||||
|
||||
// #EnvHosts provides hostnames given a project and environment.
|
||||
// Refer to https://github.com/holos-run/holos/issues/66#issuecomment-2027562626
|
||||
#EnvHosts: {
|
||||
@@ -166,7 +171,7 @@ import "strings"
|
||||
}
|
||||
|
||||
// #StageDomains provides hostnames given a project and stage. Primarily for the
|
||||
// auth proxy.
|
||||
// auth proxy cookie domains.
|
||||
// Refer to https://github.com/holos-run/holos/issues/66#issuecomment-2027562626
|
||||
#StageDomains: {
|
||||
// names are the leading prefix names to create hostnames for.
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
crt "cert-manager.io/certificate/v1"
|
||||
gw "networking.istio.io/gateway/v1beta1"
|
||||
vs "networking.istio.io/virtualservice/v1beta1"
|
||||
dr "networking.istio.io/destinationrule/v1beta1"
|
||||
ra "security.istio.io/requestauthentication/v1"
|
||||
ap "security.istio.io/authorizationpolicy/v1"
|
||||
pg "postgres-operator.crunchydata.com/postgrescluster/v1beta1"
|
||||
@@ -77,7 +78,9 @@ _apiVersion: "holos.run/v1alpha1"
|
||||
#Job: #NamespaceObject & batchv1.#Job
|
||||
#CronJob: #NamespaceObject & batchv1.#CronJob
|
||||
#Deployment: #NamespaceObject & appsv1.#Deployment
|
||||
#StatefulSet: #NamespaceObject & appsv1.#StatefulSet
|
||||
#VirtualService: #NamespaceObject & vs.#VirtualService
|
||||
#DestinationRule: #NamespaceObject & dr.#DestinationRule
|
||||
#RequestAuthentication: #NamespaceObject & ra.#RequestAuthentication
|
||||
#AuthorizationPolicy: #NamespaceObject & ap.#AuthorizationPolicy
|
||||
#Certificate: #NamespaceObject & crt.#Certificate
|
||||
|
||||
199
go.mod
199
go.mod
@@ -8,24 +8,28 @@ require (
|
||||
connectrpc.com/validate v0.1.0
|
||||
cuelang.org/go v0.8.0
|
||||
entgo.io/ent v0.13.1
|
||||
github.com/bufbuild/buf v1.30.1
|
||||
github.com/choria-io/machine-room v0.0.0-20240417064836-c604da2f005e
|
||||
github.com/coreos/go-oidc/v3 v3.10.0
|
||||
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/google/uuid v1.5.0
|
||||
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.9
|
||||
github.com/mattn/go-runewidth v0.0.15
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
github.com/prometheus/client_golang v1.19.0
|
||||
github.com/rogpeppe/go-internal v1.12.0
|
||||
github.com/sethvargo/go-retry v0.2.4
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/stretchr/testify v1.8.4
|
||||
golang.org/x/net v0.22.0
|
||||
golang.org/x/tools v0.19.0
|
||||
google.golang.org/protobuf v1.33.0
|
||||
github.com/stretchr/testify v1.9.0
|
||||
golang.org/x/net v0.24.0
|
||||
golang.org/x/tools v0.20.0
|
||||
google.golang.org/protobuf v1.33.1-0.20240408130810-98873a205002
|
||||
honnef.co/go/tools v0.4.7
|
||||
k8s.io/api v0.29.2
|
||||
k8s.io/apimachinery v0.29.2
|
||||
k8s.io/client-go v0.29.2
|
||||
@@ -36,72 +40,213 @@ require (
|
||||
|
||||
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
|
||||
github.com/BurntSushi/toml v1.3.2 // indirect
|
||||
github.com/Freman/eventloghook v0.0.0-20191003051739-e4d803b6b48b // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver v1.5.0 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.2.1 // indirect
|
||||
github.com/Masterminds/sprig/v3 v3.2.3 // indirect
|
||||
github.com/Microsoft/go-winio v0.6.1 // indirect
|
||||
github.com/OneOfOne/xxhash v1.2.8 // indirect
|
||||
github.com/achanda/go-sysctl v0.0.0-20160222034550-6be7678c45d2 // indirect
|
||||
github.com/agext/levenshtein v1.2.1 // indirect
|
||||
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230512164433-5d1fd1a340c9 // indirect
|
||||
github.com/agnivade/levenshtein v1.1.1 // indirect
|
||||
github.com/antlr4-go/antlr/v4 v4.13.0 // indirect
|
||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/bufbuild/protovalidate-go v0.3.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/blang/semver/v4 v4.0.0 // indirect
|
||||
github.com/bufbuild/protocompile v0.10.0 // indirect
|
||||
github.com/bufbuild/protovalidate-go v0.6.0 // indirect
|
||||
github.com/bufbuild/protoyaml-go v0.1.8 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/census-instrumentation/opencensus-proto v0.4.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cheekybits/genny v1.0.0 // indirect
|
||||
github.com/choria-io/fisk v0.6.2 // indirect
|
||||
github.com/choria-io/go-choria v0.28.1-0.20240416190746-b3bf9c7d5a45 // indirect
|
||||
github.com/choria-io/go-updater v0.1.0 // indirect
|
||||
github.com/choria-io/stream-replicator v0.8.3-0.20230503130504-86152f798aec // indirect
|
||||
github.com/choria-io/tokens v0.0.4-0.20240316144214-a929d9325d48 // indirect
|
||||
github.com/cloudevents/sdk-go/v2 v2.15.2 // indirect
|
||||
github.com/cncf/udpa/go v0.0.0-20220112060539-c52dc94e7fbe // indirect
|
||||
github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa // indirect
|
||||
github.com/cockroachdb/apd/v3 v3.2.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
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-credential-helpers v0.8.1 // indirect
|
||||
github.com/docker/go-connections v0.5.0 // indirect
|
||||
github.com/docker/go-units v0.5.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
|
||||
github.com/emicklei/proto v1.10.0 // indirect
|
||||
github.com/envoyproxy/go-control-plane v0.12.0 // indirect
|
||||
github.com/envoyproxy/protoc-gen-validate v1.0.4 // indirect
|
||||
github.com/evanphx/json-patch v5.7.0+incompatible // indirect
|
||||
github.com/expr-lang/expr v1.16.4 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/felixge/fgprof v0.9.4 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/ghodss/yaml v1.0.0 // indirect
|
||||
github.com/go-chi/chi/v5 v5.0.12 // indirect
|
||||
github.com/go-ini/ini v1.67.0 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.0.1 // indirect
|
||||
github.com/go-logr/logr v1.3.0 // indirect
|
||||
github.com/go-logr/logr v1.4.1 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
github.com/go-openapi/inflect v0.19.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.20.0 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.2 // indirect
|
||||
github.com/go-openapi/swag v0.22.4 // indirect
|
||||
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/protobuf v1.5.3 // indirect
|
||||
github.com/google/cel-go v0.17.4 // 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
|
||||
github.com/google/cel-go v0.20.1 // indirect
|
||||
github.com/google/gnostic-models v0.6.8 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/google/go-containerregistry v0.19.1 // indirect
|
||||
github.com/google/gofuzz v1.2.0 // indirect
|
||||
github.com/google/pprof v0.0.0-20240416155748-26353dc0451f // indirect
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/google/wire v0.5.0 // indirect
|
||||
github.com/gorilla/mux v1.8.1 // indirect
|
||||
github.com/goss-org/GOnetstat v0.0.0-20230101144325-22be0bd9e64d // indirect
|
||||
github.com/goss-org/go-ps v0.0.0-20230609005227-7b318e6a56e5 // indirect
|
||||
github.com/goss-org/goss v0.4.6 // indirect
|
||||
github.com/gosuri/uilive v0.0.4 // indirect
|
||||
github.com/gosuri/uiprogress v0.0.1 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect
|
||||
github.com/guptarohit/asciigraph v0.7.1 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/hashicorp/hcl/v2 v2.13.0 // indirect
|
||||
github.com/hashicorp/logutils v1.0.0 // indirect
|
||||
github.com/huandu/xstrings v1.4.0 // indirect
|
||||
github.com/imdario/mergo v0.3.16 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/int128/listener v1.1.0 // indirect
|
||||
github.com/int128/oauth2cli v1.14.0 // indirect
|
||||
github.com/int128/oauth2dev v1.0.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.1 // indirect
|
||||
github.com/jdx/go-netrc v1.0.0 // indirect
|
||||
github.com/jhump/protoreflect v1.16.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
github.com/klauspost/compress v1.17.8 // indirect
|
||||
github.com/klauspost/pgzip v1.2.6 // indirect
|
||||
github.com/lib/pq v1.10.9 // indirect
|
||||
github.com/looplab/fsm v1.0.1 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20240408141607-282e7b5d6b74 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||
github.com/miekg/dns v1.1.58 // indirect
|
||||
github.com/miekg/pkcs11 v1.1.1 // indirect
|
||||
github.com/minio/highwayhash v1.0.2 // indirect
|
||||
github.com/mitchellh/copystructure v1.2.0 // indirect
|
||||
github.com/mitchellh/go-homedir v1.1.0 // indirect
|
||||
github.com/mitchellh/go-wordwrap v1.0.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/mitchellh/reflectwalk v1.0.2 // indirect
|
||||
github.com/moby/docker-image-spec v1.3.1 // indirect
|
||||
github.com/moby/sys/mountinfo v0.7.1 // indirect
|
||||
github.com/moby/term v0.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/nats-io/jsm.go v0.1.1 // indirect
|
||||
github.com/nats-io/jwt/v2 v2.5.5 // indirect
|
||||
github.com/nats-io/nats-server/v2 v2.10.14 // indirect
|
||||
github.com/nats-io/nats.go v1.34.1 // indirect
|
||||
github.com/nats-io/nkeys v0.4.7 // indirect
|
||||
github.com/nats-io/nuid v1.0.1 // indirect
|
||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.15.0 // indirect
|
||||
github.com/onsi/gomega v1.31.1 // indirect
|
||||
github.com/oleiade/reflections v1.0.1 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.17.1 // indirect
|
||||
github.com/onsi/gomega v1.32.0 // indirect
|
||||
github.com/open-policy-agent/opa v0.63.0 // indirect
|
||||
github.com/opencontainers/go-digest v1.0.0 // indirect
|
||||
github.com/opencontainers/image-spec v1.1.0 // indirect
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/prometheus/client_model v0.5.0 // indirect
|
||||
github.com/prometheus/common v0.48.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/pkg/profile v1.7.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.52.3 // indirect
|
||||
github.com/prometheus/procfs v0.13.0 // indirect
|
||||
github.com/protocolbuffers/txtpbfmt v0.0.0-20230328191034-3462fbc510c0 // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/robfig/cron v1.2.0 // indirect
|
||||
github.com/rs/cors v1.10.1 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/samber/lo v1.39.0 // indirect
|
||||
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1 // indirect
|
||||
github.com/segmentio/ksuid v1.0.4 // indirect
|
||||
github.com/shirou/gopsutil/v3 v3.24.3 // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||
github.com/shopspring/decimal v1.4.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/spf13/cast v1.6.0 // indirect
|
||||
github.com/stoewer/go-strcase v1.3.0 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/tchap/go-patricia/v2 v2.3.1 // indirect
|
||||
github.com/tidwall/gjson v1.17.1 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.13 // indirect
|
||||
github.com/tklauser/numcpus v0.7.0 // indirect
|
||||
github.com/vbatts/tar-split v0.11.5 // indirect
|
||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||
github.com/xlab/tablewriter v0.0.0-20160610135559-80b567a11ad5 // indirect
|
||||
github.com/yashtewari/glob-intersection v0.2.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
github.com/zclconf/go-cty v1.8.0 // indirect
|
||||
golang.org/x/crypto v0.21.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20231108232855-2478ac86f678 // indirect
|
||||
golang.org/x/mod v0.16.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
|
||||
go.opentelemetry.io/otel v1.25.0 // indirect
|
||||
go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.25.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.25.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.25.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.25.0 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.0 // indirect
|
||||
golang.org/x/crypto v0.22.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240416160154-fe59bbe5cc7f // indirect
|
||||
golang.org/x/exp/typeparams v0.0.0-20221208152030-732eee02a75a // indirect
|
||||
golang.org/x/mod v0.17.0 // indirect
|
||||
golang.org/x/oauth2 v0.18.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/sys v0.18.0 // indirect
|
||||
golang.org/x/term v0.18.0 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
golang.org/x/sys v0.19.0 // indirect
|
||||
golang.org/x/term v0.19.0 // indirect
|
||||
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/googleapis/api v0.0.0-20230530153820-e85fd2cbaebc // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20230530153820-e85fd2cbaebc // 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
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
|
||||
22
hack/choria/gen-machine-signer
Executable file
22
hack/choria/gen-machine-signer
Executable file
@@ -0,0 +1,22 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
# build github.com/choria-io/go-choria with go build -trimpath -o choria -ldflags "-w" ./
|
||||
# Refer to https://github.com/ripienaar/choria-compose/blob/main/setup.sh#L41
|
||||
# Refer to https://github.com/holos-run/holos-infra/blob/v0.60.4/experiments/components/holos-saas/initialize/setup
|
||||
# choria jwt keys machine-signer.seed machine-signer.public
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
PARENT="$(cd "$(dirname "$0")" && pwd)"
|
||||
|
||||
tmpdir="$(mktemp -d)"
|
||||
finish() {
|
||||
[[ -d "$tmpdir" ]] && rm -rf "$tmpdir"
|
||||
}
|
||||
trap finish EXIT
|
||||
cd "$tmpdir"
|
||||
|
||||
mkdir machine-signer
|
||||
cd machine-signer
|
||||
choria jwt keys machine-signer.seed machine-signer.public
|
||||
holos create secret machine-signer --from-file .
|
||||
5
hack/choria/initialize/.gitignore
vendored
Normal file
5
hack/choria/initialize/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
/issuer/
|
||||
/provisioner/
|
||||
/broker/
|
||||
/customers/
|
||||
/agents/
|
||||
8
hack/choria/initialize/README.md
Normal file
8
hack/choria/initialize/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
Initialize machine room provisioning credentials
|
||||
|
||||
Setup Notes:
|
||||
|
||||
The holos server flag `--provisioner-seed` must match the issuer.seed value.
|
||||
To get the correct value to configure for holos server:
|
||||
|
||||
holos get secret choria-issuer --print-key=issuer.seed --namespace $NAMESPACE
|
||||
61
hack/choria/initialize/setup
Executable file
61
hack/choria/initialize/setup
Executable file
@@ -0,0 +1,61 @@
|
||||
#! /bin/bash
|
||||
#
|
||||
|
||||
export BROKER_PASSWORD="$(LC_ALL=C tr -dc "[:alpha:]" </dev/random | tr '[:upper:]' '[:lower:]' | head -c 32)"
|
||||
export PROVISIONER_TOKEN="$(LC_ALL=C tr -dc "[:alpha:]" </dev/random | tr '[:upper:]' '[:lower:]' | head -c 32)"
|
||||
|
||||
set -xeuo pipefail
|
||||
|
||||
PARENT="$(cd $(dirname "$0") && pwd)"
|
||||
TOPLEVEL="$(cd "${PARENT}" && git rev-parse --show-toplevel)"
|
||||
: "${NAMESPACE:=jeff-holos}"
|
||||
export NAMESPACE
|
||||
|
||||
tmpdir="$(mktemp -d)"
|
||||
finish() {
|
||||
[[ -d "$tmpdir" ]] && rm -rf "$tmpdir"
|
||||
}
|
||||
trap finish EXIT
|
||||
cd "$tmpdir"
|
||||
|
||||
# Generate Secrets
|
||||
|
||||
# Create organization issuer
|
||||
mkdir issuer
|
||||
choria jwt keys "./issuer/issuer.seed" "./issuer/issuer.public"
|
||||
ISSUER="$(<issuer/issuer.public)"
|
||||
export ISSUER
|
||||
|
||||
# Provisioner token used for ???
|
||||
mkdir provisioner
|
||||
echo -n "${PROVISIONER_TOKEN}" > ./provisioner/token
|
||||
|
||||
# Provisioner signer
|
||||
choria jwt keys ./provisioner/signer.seed ./provisioner/signer.public
|
||||
choria jwt client ./provisioner/signer.jwt provisioner_signer ./issuer/issuer.seed \
|
||||
--public-key "$(<provisioner/signer.public)" --server-provisioner --validity $((999*365))d --issuer
|
||||
|
||||
# Provisioner Secret
|
||||
mkdir -p provisioner/secret
|
||||
gomplate --input-dir "${PARENT}/templates/provisioner" --output-dir ./provisioner/secret/
|
||||
cp ./provisioner/signer.seed ./provisioner/secret/signer.seed
|
||||
cp ./provisioner/signer.jwt ./provisioner/secret/signer.jwt
|
||||
|
||||
# Provisioner Broker
|
||||
mkdir broker
|
||||
choria jwt keys ./broker/broker.seed ./broker/broker.public
|
||||
choria jwt server ./broker/broker.jwt broker.holos.local "$(<broker/broker.public)" ./issuer/issuer.seed \
|
||||
--org choria \
|
||||
--collectives choria \
|
||||
--subjects 'choria.node_metadata.>'
|
||||
gomplate --input-dir "${PARENT}/templates/broker/" --output-dir ./broker/
|
||||
echo -n "${BROKER_PASSWORD}" > ./broker/password
|
||||
|
||||
mkdir agents
|
||||
choria jwt keys ./agents/signer.seed ./agents/signer.public
|
||||
|
||||
# Now save the secrets
|
||||
holos create secret --append-hash=false --namespace $NAMESPACE choria-issuer --from-file=issuer
|
||||
holos create secret --append-hash=false --namespace $NAMESPACE choria-broker --from-file=broker
|
||||
holos create secret --append-hash=false --namespace $NAMESPACE choria-provisioner --from-file=provisioner
|
||||
holos create secret --append-hash=false --namespace $NAMESPACE choria-agents --from-file=agents
|
||||
21
hack/choria/initialize/templates/broker/broker.conf
Normal file
21
hack/choria/initialize/templates/broker/broker.conf
Normal file
@@ -0,0 +1,21 @@
|
||||
loglevel = info
|
||||
plugin.choria.stats_address = 0.0.0.0
|
||||
plugin.choria.stats_port = 8222
|
||||
plugin.choria.broker_network = true
|
||||
plugin.choria.network.client_port = 4222
|
||||
plugin.choria.network.peer_port = 5222
|
||||
plugin.choria.network.system.user = system
|
||||
plugin.choria.network.system.password = system
|
||||
plugin.choria.network.peers = nats://broker-0.broker:5222,nats://broker-1.broker:5222,nats://broker-2.broker:5222
|
||||
plugin.choria.use_srv = false
|
||||
plugin.choria.network.websocket_port = 4333
|
||||
|
||||
plugin.security.provider = choria
|
||||
plugin.security.choria.certificate = /etc/choria-tls/tls.crt
|
||||
plugin.security.choria.key = /etc/choria-tls/tls.key
|
||||
plugin.security.choria.token_file = /etc/choria/broker.jwt
|
||||
plugin.security.choria.seed_file = /etc/choria/broker.seed
|
||||
plugin.choria.network.provisioning.client_password = {{ .Env.BROKER_PASSWORD }}
|
||||
|
||||
plugin.security.issuer.names = choria
|
||||
plugin.security.issuer.choria.public = {{ .Env.ISSUER }}
|
||||
1
hack/choria/initialize/templates/provisioner/ISSUER
Normal file
1
hack/choria/initialize/templates/provisioner/ISSUER
Normal file
@@ -0,0 +1 @@
|
||||
{{ .Env.ISSUER -}}
|
||||
7
hack/choria/initialize/templates/provisioner/choria.cfg
Normal file
7
hack/choria/initialize/templates/provisioner/choria.cfg
Normal file
@@ -0,0 +1,7 @@
|
||||
plugin.security.provider = choria
|
||||
plugin.security.choria.token_file = /etc/provisioner/signer.jwt
|
||||
plugin.security.choria.seed_file = /etc/provisioner/signer.seed
|
||||
|
||||
identity = provisioner_signer
|
||||
|
||||
plugin.choria.middleware_hosts = broker-0.broker:4222,broker-1.broker:4222,broker-2.broker:4222
|
||||
@@ -0,0 +1,16 @@
|
||||
workers: 4
|
||||
interval: 1m
|
||||
logfile: /dev/stdout
|
||||
loglevel: info
|
||||
helper: /app/.venv/bin/helper
|
||||
token: "{{ .Env.PROVISIONER_TOKEN }}"
|
||||
choria_insecure: false
|
||||
site: holos
|
||||
broker_provisioning_password: "{{ .Env.BROKER_PASSWORD }}"
|
||||
jwt_verify_cert: "{{ .Env.ISSUER }}"
|
||||
jwt_signing_key: /etc/provisioner/signer.seed
|
||||
jwt_signing_token: /etc/provisioner/signer.jwt
|
||||
|
||||
features:
|
||||
jwt: true
|
||||
ed25519: true
|
||||
9
hack/tilt/bin/tilt
Executable file
9
hack/tilt/bin/tilt
Executable file
@@ -0,0 +1,9 @@
|
||||
#! /bin/bash
|
||||
# Override kubeconfig so we can create it with local()
|
||||
set -euo pipefail
|
||||
TOPLEVEL="$(cd $(dirname "$0")/.. && pwd)"
|
||||
export NAMESPACE="${USER}-holos"
|
||||
export KUBECONFIG="${TOPLEVEL}/kubeconfig"
|
||||
envsubst < "${KUBECONFIG}.template" > "${KUBECONFIG}"
|
||||
export TILT_WRAPPER=1
|
||||
exec tilt "$@"
|
||||
@@ -266,19 +266,9 @@ spec:
|
||||
databases:
|
||||
- holos
|
||||
options: 'SUPERUSER'
|
||||
- name: kratos
|
||||
databases:
|
||||
- kratos
|
||||
options: 'SUPERUSER'
|
||||
- name: hydra
|
||||
databases:
|
||||
- hydra
|
||||
options: 'SUPERUSER'
|
||||
- name: '{developer}'
|
||||
databases:
|
||||
- holos
|
||||
- kratos
|
||||
- hydra
|
||||
- '{developer}'
|
||||
options: 'SUPERUSER'
|
||||
# https://access.crunchydata.com/documentation/postgres-operator/latest/architecture/user-management
|
||||
|
||||
@@ -4,10 +4,10 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/holos-run/holos/pkg/cli/command"
|
||||
"github.com/holos-run/holos/pkg/errors"
|
||||
"github.com/holos-run/holos/pkg/holos"
|
||||
"github.com/holos-run/holos/pkg/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"
|
||||
)
|
||||
|
||||
@@ -3,8 +3,8 @@ package command
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/holos-run/holos/pkg/errors"
|
||||
"github.com/holos-run/holos/pkg/version"
|
||||
"github.com/holos-run/holos/internal/errors"
|
||||
"github.com/holos-run/holos/version"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -26,5 +26,6 @@ func New(name string) *cobra.Command {
|
||||
SilenceUsage: true,
|
||||
SilenceErrors: true,
|
||||
}
|
||||
cmd.Flags().SortFlags = false
|
||||
return cmd
|
||||
}
|
||||
50
internal/cli/controller/controller.go
Normal file
50
internal/cli/controller/controller.go
Normal file
@@ -0,0 +1,50 @@
|
||||
// Package controller integrates Choria Machine Room into Holos for cluster management.
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
mr "github.com/choria-io/machine-room"
|
||||
"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/version"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var (
|
||||
// SigningKey is the public key from choria jwt keys machine-signer.seed machine-signer.public, refer to gen-machine-signer.
|
||||
SigningKey = "2a136e3875f4375968ae8e8d400ba24864d3ed7c4109675f357d32cc3ca1d5a7"
|
||||
)
|
||||
|
||||
func New(cfg *holos.Config) *cobra.Command {
|
||||
cmd := command.New("controller")
|
||||
cmd.Args = cobra.ArbitraryArgs
|
||||
cmd.DisableFlagParsing = true
|
||||
cmd.RunE = func(c *cobra.Command, args []string) error {
|
||||
if SigningKey == "" {
|
||||
return errors.Wrap(fmt.Errorf("could not run: controller.SigningKey not set from build variables"))
|
||||
}
|
||||
|
||||
ctx := c.Context()
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
|
||||
app, err := mr.New(mr.Options{
|
||||
Name: "controller",
|
||||
Contact: "jeff@openinfrastructure.co",
|
||||
Version: version.Version,
|
||||
Help: "Holos Controller",
|
||||
MachineSigningKey: SigningKey,
|
||||
Args: args,
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(fmt.Errorf("could not make machine room app: %w", err))
|
||||
}
|
||||
|
||||
return app.Run(ctx)
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
@@ -1,9 +1,9 @@
|
||||
package create
|
||||
|
||||
import (
|
||||
"github.com/holos-run/holos/pkg/cli/command"
|
||||
"github.com/holos-run/holos/pkg/cli/secret"
|
||||
"github.com/holos-run/holos/pkg/holos"
|
||||
"github.com/holos-run/holos/internal/cli/command"
|
||||
"github.com/holos-run/holos/internal/cli/secret"
|
||||
"github.com/holos-run/holos/internal/holos"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package get
|
||||
|
||||
import (
|
||||
"github.com/holos-run/holos/pkg/cli/command"
|
||||
"github.com/holos-run/holos/pkg/cli/secret"
|
||||
"github.com/holos-run/holos/pkg/holos"
|
||||
"github.com/holos-run/holos/internal/cli/command"
|
||||
"github.com/holos-run/holos/internal/cli/secret"
|
||||
"github.com/holos-run/holos/internal/holos"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
@@ -5,12 +5,12 @@ import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/holos-run/holos/pkg/cli/command"
|
||||
"github.com/holos-run/holos/pkg/cli/secret"
|
||||
"github.com/holos-run/holos/pkg/errors"
|
||||
"github.com/holos-run/holos/pkg/holos"
|
||||
"github.com/holos-run/holos/pkg/logger"
|
||||
"github.com/holos-run/holos/pkg/util"
|
||||
"github.com/holos-run/holos/internal/cli/command"
|
||||
"github.com/holos-run/holos/internal/cli/secret"
|
||||
"github.com/holos-run/holos/internal/errors"
|
||||
"github.com/holos-run/holos/internal/holos"
|
||||
"github.com/holos-run/holos/internal/logger"
|
||||
"github.com/holos-run/holos/internal/util"
|
||||
"github.com/spf13/cobra"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
@@ -1,9 +1,9 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"github.com/holos-run/holos/pkg/cli/command"
|
||||
"github.com/holos-run/holos/pkg/errors"
|
||||
"github.com/holos-run/holos/pkg/holos"
|
||||
"github.com/holos-run/holos/internal/cli/command"
|
||||
"github.com/holos-run/holos/internal/errors"
|
||||
"github.com/holos-run/holos/internal/holos"
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
@@ -1,10 +1,10 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"github.com/holos-run/holos/pkg/cli/command"
|
||||
"github.com/holos-run/holos/pkg/cli/secret"
|
||||
"github.com/holos-run/holos/pkg/errors"
|
||||
"github.com/holos-run/holos/pkg/holos"
|
||||
"github.com/holos-run/holos/internal/cli/command"
|
||||
"github.com/holos-run/holos/internal/cli/secret"
|
||||
"github.com/holos-run/holos/internal/errors"
|
||||
"github.com/holos-run/holos/internal/holos"
|
||||
"github.com/spf13/cobra"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
@@ -11,11 +11,11 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/holos-run/holos/pkg/cli/command"
|
||||
"github.com/holos-run/holos/pkg/cli/secret"
|
||||
"github.com/holos-run/holos/pkg/errors"
|
||||
"github.com/holos-run/holos/pkg/holos"
|
||||
"github.com/holos-run/holos/pkg/logger"
|
||||
"github.com/holos-run/holos/internal/cli/command"
|
||||
"github.com/holos-run/holos/internal/cli/secret"
|
||||
"github.com/holos-run/holos/internal/errors"
|
||||
"github.com/holos-run/holos/internal/holos"
|
||||
"github.com/holos-run/holos/internal/logger"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/tools/txtar"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
47
internal/cli/login/login.go
Normal file
47
internal/cli/login/login.go
Normal file
@@ -0,0 +1,47 @@
|
||||
package login
|
||||
|
||||
import (
|
||||
"context"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/holos-run/holos/internal/cli/command"
|
||||
"github.com/holos-run/holos/internal/holos"
|
||||
"github.com/holos-run/holos/internal/token"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// New returns a new login command.
|
||||
func New(cfg *holos.Config) *cobra.Command {
|
||||
cmd := command.New("login")
|
||||
var printClaims bool
|
||||
|
||||
config := token.NewConfig()
|
||||
cmd.Flags().AddGoFlagSet(config.FlagSet())
|
||||
|
||||
fs := &flag.FlagSet{}
|
||||
fs.BoolVar(&printClaims, "print-claims", false, "print id token claims")
|
||||
cmd.Flags().AddGoFlagSet(fs)
|
||||
|
||||
cmd.RunE = func(c *cobra.Command, args []string) error {
|
||||
ctx := c.Context()
|
||||
if ctx == nil {
|
||||
ctx = context.Background()
|
||||
}
|
||||
token, err := token.Get(ctx, cfg.Logger(), config)
|
||||
if err != nil {
|
||||
slog.Error("could not get token", "err", err)
|
||||
return fmt.Errorf("could not get token: %w", err)
|
||||
}
|
||||
|
||||
claims := token.Claims()
|
||||
slog.Info("logged in as "+claims.Email, "name", claims.Name, "exp", token.Expiry, "email", claims.Email)
|
||||
if printClaims {
|
||||
fmt.Fprintln(cmd.OutOrStdout(), token.Pretty)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
return cmd
|
||||
}
|
||||
24
internal/cli/logout/logout.go
Normal file
24
internal/cli/logout/logout.go
Normal file
@@ -0,0 +1,24 @@
|
||||
package logout
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"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/token"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func New(cfg *holos.Config) *cobra.Command {
|
||||
cmd := command.New("logout")
|
||||
cmd.RunE = func(c *cobra.Command, args []string) error {
|
||||
if err := os.RemoveAll(token.CacheDir); err != nil {
|
||||
return errors.Wrap(fmt.Errorf("could not logout: %w", err))
|
||||
}
|
||||
cfg.Logger().Info("logged out: removed " + token.CacheDir)
|
||||
return nil
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"log/slog"
|
||||
|
||||
cue "cuelang.org/go/cue/errors"
|
||||
"github.com/holos-run/holos/pkg/errors"
|
||||
"github.com/holos-run/holos/pkg/holos"
|
||||
"github.com/holos-run/holos/internal/errors"
|
||||
"github.com/holos-run/holos/internal/holos"
|
||||
)
|
||||
|
||||
// MakeMain makes a main function for the cli or tests.
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/holos-run/holos/pkg/errors"
|
||||
"github.com/holos-run/holos/pkg/logger"
|
||||
"github.com/holos-run/holos/pkg/util"
|
||||
"github.com/holos-run/holos/internal/errors"
|
||||
"github.com/holos-run/holos/internal/logger"
|
||||
"github.com/holos-run/holos/internal/util"
|
||||
)
|
||||
|
||||
type ghAuthStatusResponse string
|
||||
@@ -5,9 +5,9 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/holos-run/holos/pkg/cli/command"
|
||||
"github.com/holos-run/holos/pkg/holos"
|
||||
"github.com/holos-run/holos/pkg/logger"
|
||||
"github.com/holos-run/holos/internal/cli/command"
|
||||
"github.com/holos-run/holos/internal/holos"
|
||||
"github.com/holos-run/holos/internal/logger"
|
||||
)
|
||||
|
||||
// Config holds configuration parameters for preflight checks.
|
||||
@@ -3,11 +3,11 @@ package render
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/holos-run/holos/pkg/cli/command"
|
||||
"github.com/holos-run/holos/pkg/errors"
|
||||
"github.com/holos-run/holos/pkg/holos"
|
||||
"github.com/holos-run/holos/pkg/internal/builder"
|
||||
"github.com/holos-run/holos/pkg/logger"
|
||||
"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"
|
||||
)
|
||||
|
||||
@@ -18,7 +18,7 @@ func makeRenderRunFunc(cfg *holos.Config) command.RunFunc {
|
||||
}
|
||||
|
||||
ctx := cmd.Context()
|
||||
log := logger.FromContext(ctx)
|
||||
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 {
|
||||
@@ -7,16 +7,19 @@ import (
|
||||
|
||||
"github.com/holos-run/holos/internal/server"
|
||||
|
||||
"github.com/holos-run/holos/pkg/cli/build"
|
||||
"github.com/holos-run/holos/pkg/cli/create"
|
||||
"github.com/holos-run/holos/pkg/cli/get"
|
||||
"github.com/holos-run/holos/pkg/cli/kv"
|
||||
"github.com/holos-run/holos/pkg/cli/preflight"
|
||||
"github.com/holos-run/holos/pkg/cli/render"
|
||||
"github.com/holos-run/holos/pkg/cli/txtar"
|
||||
"github.com/holos-run/holos/pkg/holos"
|
||||
"github.com/holos-run/holos/pkg/logger"
|
||||
"github.com/holos-run/holos/pkg/version"
|
||||
"github.com/holos-run/holos/internal/cli/build"
|
||||
"github.com/holos-run/holos/internal/cli/controller"
|
||||
"github.com/holos-run/holos/internal/cli/create"
|
||||
"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/render"
|
||||
"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.
|
||||
@@ -56,6 +59,8 @@ func New(cfg *holos.Config) *cobra.Command {
|
||||
rootCmd.AddCommand(get.New(cfg))
|
||||
rootCmd.AddCommand(create.New(cfg))
|
||||
rootCmd.AddCommand(preflight.New(cfg))
|
||||
rootCmd.AddCommand(login.New(cfg))
|
||||
rootCmd.AddCommand(logout.New(cfg))
|
||||
|
||||
// Maybe not needed?
|
||||
rootCmd.AddCommand(txtar.New(cfg))
|
||||
@@ -66,5 +71,8 @@ func New(cfg *holos.Config) *cobra.Command {
|
||||
// Server
|
||||
rootCmd.AddCommand(server.New(cfg))
|
||||
|
||||
// Controller
|
||||
rootCmd.AddCommand(controller.New(cfg))
|
||||
|
||||
return rootCmd
|
||||
}
|
||||
@@ -2,12 +2,13 @@ package cli
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"github.com/holos-run/holos/pkg/holos"
|
||||
"github.com/holos-run/holos/pkg/logger"
|
||||
"github.com/holos-run/holos/pkg/version"
|
||||
"github.com/spf13/cobra"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/holos-run/holos/internal/holos"
|
||||
"github.com/holos-run/holos/internal/logger"
|
||||
"github.com/holos-run/holos/version"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func newCommand() (*cobra.Command, *bytes.Buffer) {
|
||||
@@ -9,10 +9,10 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/holos-run/holos/pkg/cli/command"
|
||||
"github.com/holos-run/holos/pkg/errors"
|
||||
"github.com/holos-run/holos/pkg/holos"
|
||||
"github.com/holos-run/holos/pkg/logger"
|
||||
"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/logger"
|
||||
"github.com/spf13/cobra"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
"path/filepath"
|
||||
"sort"
|
||||
|
||||
"github.com/holos-run/holos/pkg/cli/command"
|
||||
"github.com/holos-run/holos/pkg/errors"
|
||||
"github.com/holos-run/holos/pkg/holos"
|
||||
"github.com/holos-run/holos/pkg/logger"
|
||||
"github.com/holos-run/holos/pkg/util"
|
||||
"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/logger"
|
||||
"github.com/holos-run/holos/internal/util"
|
||||
"github.com/spf13/cobra"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
@@ -1,7 +1,7 @@
|
||||
package secret
|
||||
|
||||
import (
|
||||
"github.com/holos-run/holos/pkg/holos"
|
||||
"github.com/holos-run/holos/internal/holos"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
package secret_test
|
||||
|
||||
import (
|
||||
"github.com/holos-run/holos/pkg/cli"
|
||||
"github.com/holos-run/holos/pkg/holos"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/holos-run/holos/internal/cli"
|
||||
"github.com/holos-run/holos/internal/holos"
|
||||
"github.com/rogpeppe/go-internal/testscript"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/kubernetes/fake"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
const clientsetKey = "clientset"
|
||||
@@ -8,10 +8,10 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/holos-run/holos/pkg/cli/command"
|
||||
"github.com/holos-run/holos/pkg/errors"
|
||||
"github.com/holos-run/holos/pkg/holos"
|
||||
"github.com/holos-run/holos/pkg/util"
|
||||
"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/util"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/tools/txtar"
|
||||
)
|
||||
@@ -15,9 +15,8 @@ import (
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect"
|
||||
"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/user"
|
||||
"github.com/holos-run/holos/internal/ent/useridentity"
|
||||
)
|
||||
|
||||
// Client is the client that holds all ent builders.
|
||||
@@ -25,10 +24,10 @@ type Client struct {
|
||||
config
|
||||
// Schema is the client for creating, migrating and dropping schema.
|
||||
Schema *migrate.Schema
|
||||
// Organization is the client for interacting with the Organization builders.
|
||||
Organization *OrganizationClient
|
||||
// User is the client for interacting with the User builders.
|
||||
User *UserClient
|
||||
// UserIdentity is the client for interacting with the UserIdentity builders.
|
||||
UserIdentity *UserIdentityClient
|
||||
}
|
||||
|
||||
// NewClient creates a new client configured with the given options.
|
||||
@@ -40,8 +39,8 @@ func NewClient(opts ...Option) *Client {
|
||||
|
||||
func (c *Client) init() {
|
||||
c.Schema = migrate.NewSchema(c.driver)
|
||||
c.Organization = NewOrganizationClient(c.config)
|
||||
c.User = NewUserClient(c.config)
|
||||
c.UserIdentity = NewUserIdentityClient(c.config)
|
||||
}
|
||||
|
||||
type (
|
||||
@@ -134,8 +133,8 @@ func (c *Client) Tx(ctx context.Context) (*Tx, error) {
|
||||
return &Tx{
|
||||
ctx: ctx,
|
||||
config: cfg,
|
||||
Organization: NewOrganizationClient(cfg),
|
||||
User: NewUserClient(cfg),
|
||||
UserIdentity: NewUserIdentityClient(cfg),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -155,15 +154,15 @@ func (c *Client) BeginTx(ctx context.Context, opts *sql.TxOptions) (*Tx, error)
|
||||
return &Tx{
|
||||
ctx: ctx,
|
||||
config: cfg,
|
||||
Organization: NewOrganizationClient(cfg),
|
||||
User: NewUserClient(cfg),
|
||||
UserIdentity: NewUserIdentityClient(cfg),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Debug returns a new debug-client. It's used to get verbose logging on specific operations.
|
||||
//
|
||||
// client.Debug().
|
||||
// User.
|
||||
// Organization.
|
||||
// Query().
|
||||
// Count(ctx)
|
||||
func (c *Client) Debug() *Client {
|
||||
@@ -185,29 +184,162 @@ func (c *Client) Close() error {
|
||||
// Use adds the mutation hooks to all the entity clients.
|
||||
// In order to add hooks to a specific client, call: `client.Node.Use(...)`.
|
||||
func (c *Client) Use(hooks ...Hook) {
|
||||
c.Organization.Use(hooks...)
|
||||
c.User.Use(hooks...)
|
||||
c.UserIdentity.Use(hooks...)
|
||||
}
|
||||
|
||||
// Intercept adds the query interceptors to all the entity clients.
|
||||
// In order to add interceptors to a specific client, call: `client.Node.Intercept(...)`.
|
||||
func (c *Client) Intercept(interceptors ...Interceptor) {
|
||||
c.Organization.Intercept(interceptors...)
|
||||
c.User.Intercept(interceptors...)
|
||||
c.UserIdentity.Intercept(interceptors...)
|
||||
}
|
||||
|
||||
// Mutate implements the ent.Mutator interface.
|
||||
func (c *Client) Mutate(ctx context.Context, m Mutation) (Value, error) {
|
||||
switch m := m.(type) {
|
||||
case *OrganizationMutation:
|
||||
return c.Organization.mutate(ctx, m)
|
||||
case *UserMutation:
|
||||
return c.User.mutate(ctx, m)
|
||||
case *UserIdentityMutation:
|
||||
return c.UserIdentity.mutate(ctx, m)
|
||||
default:
|
||||
return nil, fmt.Errorf("ent: unknown mutation type %T", m)
|
||||
}
|
||||
}
|
||||
|
||||
// OrganizationClient is a client for the Organization schema.
|
||||
type OrganizationClient struct {
|
||||
config
|
||||
}
|
||||
|
||||
// NewOrganizationClient returns a client for the Organization from the given config.
|
||||
func NewOrganizationClient(c config) *OrganizationClient {
|
||||
return &OrganizationClient{config: c}
|
||||
}
|
||||
|
||||
// Use adds a list of mutation hooks to the hooks stack.
|
||||
// A call to `Use(f, g, h)` equals to `organization.Hooks(f(g(h())))`.
|
||||
func (c *OrganizationClient) Use(hooks ...Hook) {
|
||||
c.hooks.Organization = append(c.hooks.Organization, hooks...)
|
||||
}
|
||||
|
||||
// Intercept adds a list of query interceptors to the interceptors stack.
|
||||
// A call to `Intercept(f, g, h)` equals to `organization.Intercept(f(g(h())))`.
|
||||
func (c *OrganizationClient) Intercept(interceptors ...Interceptor) {
|
||||
c.inters.Organization = append(c.inters.Organization, interceptors...)
|
||||
}
|
||||
|
||||
// Create returns a builder for creating a Organization entity.
|
||||
func (c *OrganizationClient) Create() *OrganizationCreate {
|
||||
mutation := newOrganizationMutation(c.config, OpCreate)
|
||||
return &OrganizationCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// CreateBulk returns a builder for creating a bulk of Organization entities.
|
||||
func (c *OrganizationClient) CreateBulk(builders ...*OrganizationCreate) *OrganizationCreateBulk {
|
||||
return &OrganizationCreateBulk{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 *OrganizationClient) MapCreateBulk(slice any, setFunc func(*OrganizationCreate, int)) *OrganizationCreateBulk {
|
||||
rv := reflect.ValueOf(slice)
|
||||
if rv.Kind() != reflect.Slice {
|
||||
return &OrganizationCreateBulk{err: fmt.Errorf("calling to OrganizationClient.MapCreateBulk with wrong type %T, need slice", slice)}
|
||||
}
|
||||
builders := make([]*OrganizationCreate, rv.Len())
|
||||
for i := 0; i < rv.Len(); i++ {
|
||||
builders[i] = c.Create()
|
||||
setFunc(builders[i], i)
|
||||
}
|
||||
return &OrganizationCreateBulk{config: c.config, builders: builders}
|
||||
}
|
||||
|
||||
// Update returns an update builder for Organization.
|
||||
func (c *OrganizationClient) Update() *OrganizationUpdate {
|
||||
mutation := newOrganizationMutation(c.config, OpUpdate)
|
||||
return &OrganizationUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// UpdateOne returns an update builder for the given entity.
|
||||
func (c *OrganizationClient) UpdateOne(o *Organization) *OrganizationUpdateOne {
|
||||
mutation := newOrganizationMutation(c.config, OpUpdateOne, withOrganization(o))
|
||||
return &OrganizationUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// UpdateOneID returns an update builder for the given id.
|
||||
func (c *OrganizationClient) UpdateOneID(id uuid.UUID) *OrganizationUpdateOne {
|
||||
mutation := newOrganizationMutation(c.config, OpUpdateOne, withOrganizationID(id))
|
||||
return &OrganizationUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// Delete returns a delete builder for Organization.
|
||||
func (c *OrganizationClient) Delete() *OrganizationDelete {
|
||||
mutation := newOrganizationMutation(c.config, OpDelete)
|
||||
return &OrganizationDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// DeleteOne returns a builder for deleting the given entity.
|
||||
func (c *OrganizationClient) DeleteOne(o *Organization) *OrganizationDeleteOne {
|
||||
return c.DeleteOneID(o.ID)
|
||||
}
|
||||
|
||||
// DeleteOneID returns a builder for deleting the given entity by its id.
|
||||
func (c *OrganizationClient) DeleteOneID(id uuid.UUID) *OrganizationDeleteOne {
|
||||
builder := c.Delete().Where(organization.ID(id))
|
||||
builder.mutation.id = &id
|
||||
builder.mutation.op = OpDeleteOne
|
||||
return &OrganizationDeleteOne{builder}
|
||||
}
|
||||
|
||||
// Query returns a query builder for Organization.
|
||||
func (c *OrganizationClient) Query() *OrganizationQuery {
|
||||
return &OrganizationQuery{
|
||||
config: c.config,
|
||||
ctx: &QueryContext{Type: TypeOrganization},
|
||||
inters: c.Interceptors(),
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns a Organization entity by its id.
|
||||
func (c *OrganizationClient) Get(ctx context.Context, id uuid.UUID) (*Organization, error) {
|
||||
return c.Query().Where(organization.ID(id)).Only(ctx)
|
||||
}
|
||||
|
||||
// GetX is like Get, but panics if an error occurs.
|
||||
func (c *OrganizationClient) GetX(ctx context.Context, id uuid.UUID) *Organization {
|
||||
obj, err := c.Get(ctx, id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
// Hooks returns the client hooks.
|
||||
func (c *OrganizationClient) Hooks() []Hook {
|
||||
return c.hooks.Organization
|
||||
}
|
||||
|
||||
// Interceptors returns the client interceptors.
|
||||
func (c *OrganizationClient) Interceptors() []Interceptor {
|
||||
return c.inters.Organization
|
||||
}
|
||||
|
||||
func (c *OrganizationClient) mutate(ctx context.Context, m *OrganizationMutation) (Value, error) {
|
||||
switch m.Op() {
|
||||
case OpCreate:
|
||||
return (&OrganizationCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpUpdate:
|
||||
return (&OrganizationUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpUpdateOne:
|
||||
return (&OrganizationUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpDelete, OpDeleteOne:
|
||||
return (&OrganizationDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
|
||||
default:
|
||||
return nil, fmt.Errorf("ent: unknown Organization mutation op: %q", m.Op())
|
||||
}
|
||||
}
|
||||
|
||||
// UserClient is a client for the User schema.
|
||||
type UserClient struct {
|
||||
config
|
||||
@@ -316,22 +448,6 @@ func (c *UserClient) GetX(ctx context.Context, id uuid.UUID) *User {
|
||||
return obj
|
||||
}
|
||||
|
||||
// QueryIdentities queries the identities edge of a User.
|
||||
func (c *UserClient) QueryIdentities(u *User) *UserIdentityQuery {
|
||||
query := (&UserIdentityClient{config: c.config}).Query()
|
||||
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
||||
id := u.ID
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(user.Table, user.FieldID, id),
|
||||
sqlgraph.To(useridentity.Table, useridentity.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.O2M, false, user.IdentitiesTable, user.IdentitiesColumn),
|
||||
)
|
||||
fromV = sqlgraph.Neighbors(u.driver.Dialect(), step)
|
||||
return fromV, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// Hooks returns the client hooks.
|
||||
func (c *UserClient) Hooks() []Hook {
|
||||
return c.hooks.User
|
||||
@@ -357,161 +473,12 @@ func (c *UserClient) mutate(ctx context.Context, m *UserMutation) (Value, error)
|
||||
}
|
||||
}
|
||||
|
||||
// UserIdentityClient is a client for the UserIdentity schema.
|
||||
type UserIdentityClient struct {
|
||||
config
|
||||
}
|
||||
|
||||
// NewUserIdentityClient returns a client for the UserIdentity from the given config.
|
||||
func NewUserIdentityClient(c config) *UserIdentityClient {
|
||||
return &UserIdentityClient{config: c}
|
||||
}
|
||||
|
||||
// Use adds a list of mutation hooks to the hooks stack.
|
||||
// A call to `Use(f, g, h)` equals to `useridentity.Hooks(f(g(h())))`.
|
||||
func (c *UserIdentityClient) Use(hooks ...Hook) {
|
||||
c.hooks.UserIdentity = append(c.hooks.UserIdentity, hooks...)
|
||||
}
|
||||
|
||||
// Intercept adds a list of query interceptors to the interceptors stack.
|
||||
// A call to `Intercept(f, g, h)` equals to `useridentity.Intercept(f(g(h())))`.
|
||||
func (c *UserIdentityClient) Intercept(interceptors ...Interceptor) {
|
||||
c.inters.UserIdentity = append(c.inters.UserIdentity, interceptors...)
|
||||
}
|
||||
|
||||
// Create returns a builder for creating a UserIdentity entity.
|
||||
func (c *UserIdentityClient) Create() *UserIdentityCreate {
|
||||
mutation := newUserIdentityMutation(c.config, OpCreate)
|
||||
return &UserIdentityCreate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// CreateBulk returns a builder for creating a bulk of UserIdentity entities.
|
||||
func (c *UserIdentityClient) CreateBulk(builders ...*UserIdentityCreate) *UserIdentityCreateBulk {
|
||||
return &UserIdentityCreateBulk{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 *UserIdentityClient) MapCreateBulk(slice any, setFunc func(*UserIdentityCreate, int)) *UserIdentityCreateBulk {
|
||||
rv := reflect.ValueOf(slice)
|
||||
if rv.Kind() != reflect.Slice {
|
||||
return &UserIdentityCreateBulk{err: fmt.Errorf("calling to UserIdentityClient.MapCreateBulk with wrong type %T, need slice", slice)}
|
||||
}
|
||||
builders := make([]*UserIdentityCreate, rv.Len())
|
||||
for i := 0; i < rv.Len(); i++ {
|
||||
builders[i] = c.Create()
|
||||
setFunc(builders[i], i)
|
||||
}
|
||||
return &UserIdentityCreateBulk{config: c.config, builders: builders}
|
||||
}
|
||||
|
||||
// Update returns an update builder for UserIdentity.
|
||||
func (c *UserIdentityClient) Update() *UserIdentityUpdate {
|
||||
mutation := newUserIdentityMutation(c.config, OpUpdate)
|
||||
return &UserIdentityUpdate{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// UpdateOne returns an update builder for the given entity.
|
||||
func (c *UserIdentityClient) UpdateOne(ui *UserIdentity) *UserIdentityUpdateOne {
|
||||
mutation := newUserIdentityMutation(c.config, OpUpdateOne, withUserIdentity(ui))
|
||||
return &UserIdentityUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// UpdateOneID returns an update builder for the given id.
|
||||
func (c *UserIdentityClient) UpdateOneID(id uuid.UUID) *UserIdentityUpdateOne {
|
||||
mutation := newUserIdentityMutation(c.config, OpUpdateOne, withUserIdentityID(id))
|
||||
return &UserIdentityUpdateOne{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// Delete returns a delete builder for UserIdentity.
|
||||
func (c *UserIdentityClient) Delete() *UserIdentityDelete {
|
||||
mutation := newUserIdentityMutation(c.config, OpDelete)
|
||||
return &UserIdentityDelete{config: c.config, hooks: c.Hooks(), mutation: mutation}
|
||||
}
|
||||
|
||||
// DeleteOne returns a builder for deleting the given entity.
|
||||
func (c *UserIdentityClient) DeleteOne(ui *UserIdentity) *UserIdentityDeleteOne {
|
||||
return c.DeleteOneID(ui.ID)
|
||||
}
|
||||
|
||||
// DeleteOneID returns a builder for deleting the given entity by its id.
|
||||
func (c *UserIdentityClient) DeleteOneID(id uuid.UUID) *UserIdentityDeleteOne {
|
||||
builder := c.Delete().Where(useridentity.ID(id))
|
||||
builder.mutation.id = &id
|
||||
builder.mutation.op = OpDeleteOne
|
||||
return &UserIdentityDeleteOne{builder}
|
||||
}
|
||||
|
||||
// Query returns a query builder for UserIdentity.
|
||||
func (c *UserIdentityClient) Query() *UserIdentityQuery {
|
||||
return &UserIdentityQuery{
|
||||
config: c.config,
|
||||
ctx: &QueryContext{Type: TypeUserIdentity},
|
||||
inters: c.Interceptors(),
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns a UserIdentity entity by its id.
|
||||
func (c *UserIdentityClient) Get(ctx context.Context, id uuid.UUID) (*UserIdentity, error) {
|
||||
return c.Query().Where(useridentity.ID(id)).Only(ctx)
|
||||
}
|
||||
|
||||
// GetX is like Get, but panics if an error occurs.
|
||||
func (c *UserIdentityClient) GetX(ctx context.Context, id uuid.UUID) *UserIdentity {
|
||||
obj, err := c.Get(ctx, id)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return obj
|
||||
}
|
||||
|
||||
// QueryUser queries the user edge of a UserIdentity.
|
||||
func (c *UserIdentityClient) QueryUser(ui *UserIdentity) *UserQuery {
|
||||
query := (&UserClient{config: c.config}).Query()
|
||||
query.path = func(context.Context) (fromV *sql.Selector, _ error) {
|
||||
id := ui.ID
|
||||
step := sqlgraph.NewStep(
|
||||
sqlgraph.From(useridentity.Table, useridentity.FieldID, id),
|
||||
sqlgraph.To(user.Table, user.FieldID),
|
||||
sqlgraph.Edge(sqlgraph.M2O, true, useridentity.UserTable, useridentity.UserColumn),
|
||||
)
|
||||
fromV = sqlgraph.Neighbors(ui.driver.Dialect(), step)
|
||||
return fromV, nil
|
||||
}
|
||||
return query
|
||||
}
|
||||
|
||||
// Hooks returns the client hooks.
|
||||
func (c *UserIdentityClient) Hooks() []Hook {
|
||||
return c.hooks.UserIdentity
|
||||
}
|
||||
|
||||
// Interceptors returns the client interceptors.
|
||||
func (c *UserIdentityClient) Interceptors() []Interceptor {
|
||||
return c.inters.UserIdentity
|
||||
}
|
||||
|
||||
func (c *UserIdentityClient) mutate(ctx context.Context, m *UserIdentityMutation) (Value, error) {
|
||||
switch m.Op() {
|
||||
case OpCreate:
|
||||
return (&UserIdentityCreate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpUpdate:
|
||||
return (&UserIdentityUpdate{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpUpdateOne:
|
||||
return (&UserIdentityUpdateOne{config: c.config, hooks: c.Hooks(), mutation: m}).Save(ctx)
|
||||
case OpDelete, OpDeleteOne:
|
||||
return (&UserIdentityDelete{config: c.config, hooks: c.Hooks(), mutation: m}).Exec(ctx)
|
||||
default:
|
||||
return nil, fmt.Errorf("ent: unknown UserIdentity mutation op: %q", m.Op())
|
||||
}
|
||||
}
|
||||
|
||||
// hooks and interceptors per client, for fast access.
|
||||
type (
|
||||
hooks struct {
|
||||
User, UserIdentity []ent.Hook
|
||||
Organization, User []ent.Hook
|
||||
}
|
||||
inters struct {
|
||||
User, UserIdentity []ent.Interceptor
|
||||
Organization, User []ent.Interceptor
|
||||
}
|
||||
)
|
||||
|
||||
@@ -12,8 +12,8 @@ import (
|
||||
"entgo.io/ent"
|
||||
"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/user"
|
||||
"github.com/holos-run/holos/internal/ent/useridentity"
|
||||
)
|
||||
|
||||
// ent aliases to avoid import conflicts in user's code.
|
||||
@@ -74,8 +74,8 @@ var (
|
||||
func checkColumn(table, column string) error {
|
||||
initCheck.Do(func() {
|
||||
columnCheck = sql.NewColumnCheck(map[string]func(string) bool{
|
||||
organization.Table: organization.ValidColumn,
|
||||
user.Table: user.ValidColumn,
|
||||
useridentity.Table: useridentity.ValidColumn,
|
||||
})
|
||||
})
|
||||
return columnCheck(table, column)
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
package ent
|
||||
|
||||
//go:generate go run -mod=mod entgo.io/ent/cmd/ent generate --feature sql/upsert ./schema
|
||||
//go:generate go run entgo.io/ent/cmd/ent generate --feature sql/upsert ./schema
|
||||
|
||||
@@ -9,6 +9,18 @@ import (
|
||||
"github.com/holos-run/holos/internal/ent"
|
||||
)
|
||||
|
||||
// The OrganizationFunc type is an adapter to allow the use of ordinary
|
||||
// function as Organization mutator.
|
||||
type OrganizationFunc func(context.Context, *ent.OrganizationMutation) (ent.Value, error)
|
||||
|
||||
// Mutate calls f(ctx, m).
|
||||
func (f OrganizationFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
|
||||
if mv, ok := m.(*ent.OrganizationMutation); ok {
|
||||
return f(ctx, mv)
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.OrganizationMutation", 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)
|
||||
@@ -21,18 +33,6 @@ func (f UserFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error)
|
||||
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.UserMutation", m)
|
||||
}
|
||||
|
||||
// The UserIdentityFunc type is an adapter to allow the use of ordinary
|
||||
// function as UserIdentity mutator.
|
||||
type UserIdentityFunc func(context.Context, *ent.UserIdentityMutation) (ent.Value, error)
|
||||
|
||||
// Mutate calls f(ctx, m).
|
||||
func (f UserIdentityFunc) Mutate(ctx context.Context, m ent.Mutation) (ent.Value, error) {
|
||||
if mv, ok := m.(*ent.UserIdentityMutation); ok {
|
||||
return f(ctx, mv)
|
||||
}
|
||||
return nil, fmt.Errorf("unexpected mutation type %T. expect *ent.UserIdentityMutation", m)
|
||||
}
|
||||
|
||||
// Condition is a hook condition function.
|
||||
type Condition func(context.Context, ent.Mutation) bool
|
||||
|
||||
|
||||
@@ -8,13 +8,28 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
// OrganizationsColumns holds the columns for the "organizations" table.
|
||||
OrganizationsColumns = []*schema.Column{
|
||||
{Name: "id", Type: field.TypeUUID},
|
||||
{Name: "created_at", Type: field.TypeTime},
|
||||
{Name: "updated_at", Type: field.TypeTime},
|
||||
{Name: "name", Type: field.TypeString, Unique: true},
|
||||
{Name: "display_name", Type: field.TypeString},
|
||||
}
|
||||
// OrganizationsTable holds the schema information for the "organizations" table.
|
||||
OrganizationsTable = &schema.Table{
|
||||
Name: "organizations",
|
||||
Columns: OrganizationsColumns,
|
||||
PrimaryKey: []*schema.Column{OrganizationsColumns[0]},
|
||||
}
|
||||
// UsersColumns holds the columns for the "users" table.
|
||||
UsersColumns = []*schema.Column{
|
||||
{Name: "id", Type: field.TypeUUID},
|
||||
{Name: "created_at", Type: field.TypeTime},
|
||||
{Name: "updated_at", Type: field.TypeTime},
|
||||
{Name: "email", Type: field.TypeString, Unique: true},
|
||||
{Name: "email_verified", Type: field.TypeBool, Default: false},
|
||||
{Name: "iss", Type: field.TypeString},
|
||||
{Name: "sub", Type: field.TypeString},
|
||||
{Name: "name", Type: field.TypeString},
|
||||
}
|
||||
// UsersTable holds the schema information for the "users" table.
|
||||
@@ -23,46 +38,12 @@ var (
|
||||
Columns: UsersColumns,
|
||||
PrimaryKey: []*schema.Column{UsersColumns[0]},
|
||||
}
|
||||
// UserIdentitiesColumns holds the columns for the "user_identities" table.
|
||||
UserIdentitiesColumns = []*schema.Column{
|
||||
{Name: "id", Type: field.TypeUUID},
|
||||
{Name: "created_at", Type: field.TypeTime},
|
||||
{Name: "updated_at", Type: field.TypeTime},
|
||||
{Name: "iss", Type: field.TypeString},
|
||||
{Name: "sub", Type: field.TypeString},
|
||||
{Name: "email", Type: field.TypeString},
|
||||
{Name: "email_verified", Type: field.TypeBool, Default: false},
|
||||
{Name: "name", Type: field.TypeString, Nullable: true},
|
||||
{Name: "user_id", Type: field.TypeUUID},
|
||||
}
|
||||
// UserIdentitiesTable holds the schema information for the "user_identities" table.
|
||||
UserIdentitiesTable = &schema.Table{
|
||||
Name: "user_identities",
|
||||
Columns: UserIdentitiesColumns,
|
||||
PrimaryKey: []*schema.Column{UserIdentitiesColumns[0]},
|
||||
ForeignKeys: []*schema.ForeignKey{
|
||||
{
|
||||
Symbol: "user_identities_users_identities",
|
||||
Columns: []*schema.Column{UserIdentitiesColumns[8]},
|
||||
RefColumns: []*schema.Column{UsersColumns[0]},
|
||||
OnDelete: schema.Cascade,
|
||||
},
|
||||
},
|
||||
Indexes: []*schema.Index{
|
||||
{
|
||||
Name: "useridentity_iss_sub",
|
||||
Unique: true,
|
||||
Columns: []*schema.Column{UserIdentitiesColumns[3], UserIdentitiesColumns[4]},
|
||||
},
|
||||
},
|
||||
}
|
||||
// Tables holds all the tables in the schema.
|
||||
Tables = []*schema.Table{
|
||||
OrganizationsTable,
|
||||
UsersTable,
|
||||
UserIdentitiesTable,
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
UserIdentitiesTable.ForeignKeys[0].RefTable = UsersTable
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
140
internal/ent/organization.go
Normal file
140
internal/ent/organization.go
Normal file
@@ -0,0 +1,140 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"entgo.io/ent"
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"github.com/gofrs/uuid"
|
||||
"github.com/holos-run/holos/internal/ent/organization"
|
||||
)
|
||||
|
||||
// Organization is the model entity for the Organization schema.
|
||||
type Organization 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"`
|
||||
// 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"`
|
||||
selectValues sql.SelectValues
|
||||
}
|
||||
|
||||
// scanValues returns the types for scanning values from sql.Rows.
|
||||
func (*Organization) scanValues(columns []string) ([]any, error) {
|
||||
values := make([]any, len(columns))
|
||||
for i := range columns {
|
||||
switch columns[i] {
|
||||
case organization.FieldName, organization.FieldDisplayName:
|
||||
values[i] = new(sql.NullString)
|
||||
case organization.FieldCreatedAt, organization.FieldUpdatedAt:
|
||||
values[i] = new(sql.NullTime)
|
||||
case organization.FieldID:
|
||||
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 Organization fields.
|
||||
func (o *Organization) 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 organization.FieldID:
|
||||
if value, ok := values[i].(*uuid.UUID); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field id", values[i])
|
||||
} else if value != nil {
|
||||
o.ID = *value
|
||||
}
|
||||
case organization.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 {
|
||||
o.CreatedAt = value.Time
|
||||
}
|
||||
case organization.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 {
|
||||
o.UpdatedAt = value.Time
|
||||
}
|
||||
case organization.FieldName:
|
||||
if value, ok := values[i].(*sql.NullString); !ok {
|
||||
return fmt.Errorf("unexpected type %T for field name", values[i])
|
||||
} else if value.Valid {
|
||||
o.Name = value.String
|
||||
}
|
||||
case organization.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 {
|
||||
o.DisplayName = value.String
|
||||
}
|
||||
default:
|
||||
o.selectValues.Set(columns[i], values[i])
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Value returns the ent.Value that was dynamically selected and assigned to the Organization.
|
||||
// This includes values selected through modifiers, order, etc.
|
||||
func (o *Organization) Value(name string) (ent.Value, error) {
|
||||
return o.selectValues.Get(name)
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (o *Organization) Update() *OrganizationUpdateOne {
|
||||
return NewOrganizationClient(o.config).UpdateOne(o)
|
||||
}
|
||||
|
||||
// Unwrap unwraps the Organization 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 (o *Organization) Unwrap() *Organization {
|
||||
_tx, ok := o.config.driver.(*txDriver)
|
||||
if !ok {
|
||||
panic("ent: Organization is not a transactional entity")
|
||||
}
|
||||
o.config.driver = _tx.drv
|
||||
return o
|
||||
}
|
||||
|
||||
// String implements the fmt.Stringer.
|
||||
func (o *Organization) String() string {
|
||||
var builder strings.Builder
|
||||
builder.WriteString("Organization(")
|
||||
builder.WriteString(fmt.Sprintf("id=%v, ", o.ID))
|
||||
builder.WriteString("created_at=")
|
||||
builder.WriteString(o.CreatedAt.Format(time.ANSIC))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("updated_at=")
|
||||
builder.WriteString(o.UpdatedAt.Format(time.ANSIC))
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("name=")
|
||||
builder.WriteString(o.Name)
|
||||
builder.WriteString(", ")
|
||||
builder.WriteString("display_name=")
|
||||
builder.WriteString(o.DisplayName)
|
||||
builder.WriteByte(')')
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
// Organizations is a parsable slice of Organization.
|
||||
type Organizations []*Organization
|
||||
87
internal/ent/organization/organization.go
Normal file
87
internal/ent/organization/organization.go
Normal file
@@ -0,0 +1,87 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package organization
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"github.com/gofrs/uuid"
|
||||
)
|
||||
|
||||
const (
|
||||
// Label holds the string label denoting the organization type in the database.
|
||||
Label = "organization"
|
||||
// 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"
|
||||
// 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"
|
||||
// Table holds the table name of the organization in the database.
|
||||
Table = "organizations"
|
||||
)
|
||||
|
||||
// Columns holds all SQL columns for organization fields.
|
||||
var Columns = []string{
|
||||
FieldID,
|
||||
FieldCreatedAt,
|
||||
FieldUpdatedAt,
|
||||
FieldName,
|
||||
FieldDisplayName,
|
||||
}
|
||||
|
||||
// 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 Organization 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()
|
||||
}
|
||||
|
||||
// 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()
|
||||
}
|
||||
301
internal/ent/organization/where.go
Normal file
301
internal/ent/organization/where.go
Normal file
@@ -0,0 +1,301 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package organization
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect/sql"
|
||||
"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.Organization {
|
||||
return predicate.Organization(sql.FieldEQ(FieldID, id))
|
||||
}
|
||||
|
||||
// IDEQ applies the EQ predicate on the ID field.
|
||||
func IDEQ(id uuid.UUID) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldEQ(FieldID, id))
|
||||
}
|
||||
|
||||
// IDNEQ applies the NEQ predicate on the ID field.
|
||||
func IDNEQ(id uuid.UUID) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldNEQ(FieldID, id))
|
||||
}
|
||||
|
||||
// IDIn applies the In predicate on the ID field.
|
||||
func IDIn(ids ...uuid.UUID) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldIn(FieldID, ids...))
|
||||
}
|
||||
|
||||
// IDNotIn applies the NotIn predicate on the ID field.
|
||||
func IDNotIn(ids ...uuid.UUID) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldNotIn(FieldID, ids...))
|
||||
}
|
||||
|
||||
// IDGT applies the GT predicate on the ID field.
|
||||
func IDGT(id uuid.UUID) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldGT(FieldID, id))
|
||||
}
|
||||
|
||||
// IDGTE applies the GTE predicate on the ID field.
|
||||
func IDGTE(id uuid.UUID) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldGTE(FieldID, id))
|
||||
}
|
||||
|
||||
// IDLT applies the LT predicate on the ID field.
|
||||
func IDLT(id uuid.UUID) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldLT(FieldID, id))
|
||||
}
|
||||
|
||||
// IDLTE applies the LTE predicate on the ID field.
|
||||
func IDLTE(id uuid.UUID) predicate.Organization {
|
||||
return predicate.Organization(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.Organization {
|
||||
return predicate.Organization(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.Organization {
|
||||
return predicate.Organization(sql.FieldEQ(FieldUpdatedAt, 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))
|
||||
}
|
||||
|
||||
// DisplayName applies equality check predicate on the "display_name" field. It's identical to DisplayNameEQ.
|
||||
func DisplayName(v string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldEQ(FieldDisplayName, 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))
|
||||
}
|
||||
|
||||
// CreatedAtNEQ applies the NEQ predicate on the "created_at" field.
|
||||
func CreatedAtNEQ(v time.Time) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldNEQ(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtIn applies the In predicate on the "created_at" field.
|
||||
func CreatedAtIn(vs ...time.Time) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldIn(FieldCreatedAt, vs...))
|
||||
}
|
||||
|
||||
// CreatedAtNotIn applies the NotIn predicate on the "created_at" field.
|
||||
func CreatedAtNotIn(vs ...time.Time) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldNotIn(FieldCreatedAt, vs...))
|
||||
}
|
||||
|
||||
// CreatedAtGT applies the GT predicate on the "created_at" field.
|
||||
func CreatedAtGT(v time.Time) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldGT(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtGTE applies the GTE predicate on the "created_at" field.
|
||||
func CreatedAtGTE(v time.Time) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldGTE(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtLT applies the LT predicate on the "created_at" field.
|
||||
func CreatedAtLT(v time.Time) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldLT(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// CreatedAtLTE applies the LTE predicate on the "created_at" field.
|
||||
func CreatedAtLTE(v time.Time) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldLTE(FieldCreatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtEQ applies the EQ predicate on the "updated_at" field.
|
||||
func UpdatedAtEQ(v time.Time) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldEQ(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtNEQ applies the NEQ predicate on the "updated_at" field.
|
||||
func UpdatedAtNEQ(v time.Time) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldNEQ(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtIn applies the In predicate on the "updated_at" field.
|
||||
func UpdatedAtIn(vs ...time.Time) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldIn(FieldUpdatedAt, vs...))
|
||||
}
|
||||
|
||||
// UpdatedAtNotIn applies the NotIn predicate on the "updated_at" field.
|
||||
func UpdatedAtNotIn(vs ...time.Time) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldNotIn(FieldUpdatedAt, vs...))
|
||||
}
|
||||
|
||||
// UpdatedAtGT applies the GT predicate on the "updated_at" field.
|
||||
func UpdatedAtGT(v time.Time) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldGT(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtGTE applies the GTE predicate on the "updated_at" field.
|
||||
func UpdatedAtGTE(v time.Time) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldGTE(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtLT applies the LT predicate on the "updated_at" field.
|
||||
func UpdatedAtLT(v time.Time) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldLT(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// UpdatedAtLTE applies the LTE predicate on the "updated_at" field.
|
||||
func UpdatedAtLTE(v time.Time) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldLTE(FieldUpdatedAt, v))
|
||||
}
|
||||
|
||||
// NameEQ applies the EQ predicate on the "name" field.
|
||||
func NameEQ(v string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldEQ(FieldName, v))
|
||||
}
|
||||
|
||||
// NameNEQ applies the NEQ predicate on the "name" field.
|
||||
func NameNEQ(v string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldNEQ(FieldName, v))
|
||||
}
|
||||
|
||||
// NameIn applies the In predicate on the "name" field.
|
||||
func NameIn(vs ...string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldIn(FieldName, vs...))
|
||||
}
|
||||
|
||||
// NameNotIn applies the NotIn predicate on the "name" field.
|
||||
func NameNotIn(vs ...string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldNotIn(FieldName, vs...))
|
||||
}
|
||||
|
||||
// NameGT applies the GT predicate on the "name" field.
|
||||
func NameGT(v string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldGT(FieldName, v))
|
||||
}
|
||||
|
||||
// NameGTE applies the GTE predicate on the "name" field.
|
||||
func NameGTE(v string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldGTE(FieldName, v))
|
||||
}
|
||||
|
||||
// NameLT applies the LT predicate on the "name" field.
|
||||
func NameLT(v string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldLT(FieldName, v))
|
||||
}
|
||||
|
||||
// NameLTE applies the LTE predicate on the "name" field.
|
||||
func NameLTE(v string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldLTE(FieldName, v))
|
||||
}
|
||||
|
||||
// NameContains applies the Contains predicate on the "name" field.
|
||||
func NameContains(v string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldContains(FieldName, v))
|
||||
}
|
||||
|
||||
// NameHasPrefix applies the HasPrefix predicate on the "name" field.
|
||||
func NameHasPrefix(v string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldHasPrefix(FieldName, v))
|
||||
}
|
||||
|
||||
// NameHasSuffix applies the HasSuffix predicate on the "name" field.
|
||||
func NameHasSuffix(v string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldHasSuffix(FieldName, v))
|
||||
}
|
||||
|
||||
// NameEqualFold applies the EqualFold predicate on the "name" field.
|
||||
func NameEqualFold(v string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldEqualFold(FieldName, v))
|
||||
}
|
||||
|
||||
// NameContainsFold applies the ContainsFold predicate on the "name" field.
|
||||
func NameContainsFold(v string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldContainsFold(FieldName, v))
|
||||
}
|
||||
|
||||
// DisplayNameEQ applies the EQ predicate on the "display_name" field.
|
||||
func DisplayNameEQ(v string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldEQ(FieldDisplayName, v))
|
||||
}
|
||||
|
||||
// DisplayNameNEQ applies the NEQ predicate on the "display_name" field.
|
||||
func DisplayNameNEQ(v string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldNEQ(FieldDisplayName, v))
|
||||
}
|
||||
|
||||
// DisplayNameIn applies the In predicate on the "display_name" field.
|
||||
func DisplayNameIn(vs ...string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldIn(FieldDisplayName, vs...))
|
||||
}
|
||||
|
||||
// DisplayNameNotIn applies the NotIn predicate on the "display_name" field.
|
||||
func DisplayNameNotIn(vs ...string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldNotIn(FieldDisplayName, vs...))
|
||||
}
|
||||
|
||||
// DisplayNameGT applies the GT predicate on the "display_name" field.
|
||||
func DisplayNameGT(v string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldGT(FieldDisplayName, v))
|
||||
}
|
||||
|
||||
// DisplayNameGTE applies the GTE predicate on the "display_name" field.
|
||||
func DisplayNameGTE(v string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldGTE(FieldDisplayName, v))
|
||||
}
|
||||
|
||||
// DisplayNameLT applies the LT predicate on the "display_name" field.
|
||||
func DisplayNameLT(v string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldLT(FieldDisplayName, v))
|
||||
}
|
||||
|
||||
// DisplayNameLTE applies the LTE predicate on the "display_name" field.
|
||||
func DisplayNameLTE(v string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldLTE(FieldDisplayName, v))
|
||||
}
|
||||
|
||||
// DisplayNameContains applies the Contains predicate on the "display_name" field.
|
||||
func DisplayNameContains(v string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldContains(FieldDisplayName, v))
|
||||
}
|
||||
|
||||
// DisplayNameHasPrefix applies the HasPrefix predicate on the "display_name" field.
|
||||
func DisplayNameHasPrefix(v string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldHasPrefix(FieldDisplayName, v))
|
||||
}
|
||||
|
||||
// DisplayNameHasSuffix applies the HasSuffix predicate on the "display_name" field.
|
||||
func DisplayNameHasSuffix(v string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldHasSuffix(FieldDisplayName, v))
|
||||
}
|
||||
|
||||
// DisplayNameEqualFold applies the EqualFold predicate on the "display_name" field.
|
||||
func DisplayNameEqualFold(v string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldEqualFold(FieldDisplayName, v))
|
||||
}
|
||||
|
||||
// DisplayNameContainsFold applies the ContainsFold predicate on the "display_name" field.
|
||||
func DisplayNameContainsFold(v string) predicate.Organization {
|
||||
return predicate.Organization(sql.FieldContainsFold(FieldDisplayName, v))
|
||||
}
|
||||
|
||||
// And groups predicates with the AND operator between them.
|
||||
func And(predicates ...predicate.Organization) predicate.Organization {
|
||||
return predicate.Organization(sql.AndPredicates(predicates...))
|
||||
}
|
||||
|
||||
// Or groups predicates with the OR operator between them.
|
||||
func Or(predicates ...predicate.Organization) predicate.Organization {
|
||||
return predicate.Organization(sql.OrPredicates(predicates...))
|
||||
}
|
||||
|
||||
// Not applies the not operator on the given predicate.
|
||||
func Not(p predicate.Organization) predicate.Organization {
|
||||
return predicate.Organization(sql.NotPredicates(p))
|
||||
}
|
||||
663
internal/ent/organization_create.go
Normal file
663
internal/ent/organization_create.go
Normal file
@@ -0,0 +1,663 @@
|
||||
// Code generated by ent, DO NOT EDIT.
|
||||
|
||||
package ent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"entgo.io/ent/dialect"
|
||||
"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"
|
||||
)
|
||||
|
||||
// OrganizationCreate is the builder for creating a Organization entity.
|
||||
type OrganizationCreate struct {
|
||||
config
|
||||
mutation *OrganizationMutation
|
||||
hooks []Hook
|
||||
conflict []sql.ConflictOption
|
||||
}
|
||||
|
||||
// SetCreatedAt sets the "created_at" field.
|
||||
func (oc *OrganizationCreate) SetCreatedAt(t time.Time) *OrganizationCreate {
|
||||
oc.mutation.SetCreatedAt(t)
|
||||
return oc
|
||||
}
|
||||
|
||||
// SetNillableCreatedAt sets the "created_at" field if the given value is not nil.
|
||||
func (oc *OrganizationCreate) SetNillableCreatedAt(t *time.Time) *OrganizationCreate {
|
||||
if t != nil {
|
||||
oc.SetCreatedAt(*t)
|
||||
}
|
||||
return oc
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (oc *OrganizationCreate) SetUpdatedAt(t time.Time) *OrganizationCreate {
|
||||
oc.mutation.SetUpdatedAt(t)
|
||||
return oc
|
||||
}
|
||||
|
||||
// SetNillableUpdatedAt sets the "updated_at" field if the given value is not nil.
|
||||
func (oc *OrganizationCreate) SetNillableUpdatedAt(t *time.Time) *OrganizationCreate {
|
||||
if t != nil {
|
||||
oc.SetUpdatedAt(*t)
|
||||
}
|
||||
return oc
|
||||
}
|
||||
|
||||
// SetName sets the "name" field.
|
||||
func (oc *OrganizationCreate) SetName(s string) *OrganizationCreate {
|
||||
oc.mutation.SetName(s)
|
||||
return oc
|
||||
}
|
||||
|
||||
// SetDisplayName sets the "display_name" field.
|
||||
func (oc *OrganizationCreate) SetDisplayName(s string) *OrganizationCreate {
|
||||
oc.mutation.SetDisplayName(s)
|
||||
return oc
|
||||
}
|
||||
|
||||
// SetID sets the "id" field.
|
||||
func (oc *OrganizationCreate) SetID(u uuid.UUID) *OrganizationCreate {
|
||||
oc.mutation.SetID(u)
|
||||
return oc
|
||||
}
|
||||
|
||||
// SetNillableID sets the "id" field if the given value is not nil.
|
||||
func (oc *OrganizationCreate) SetNillableID(u *uuid.UUID) *OrganizationCreate {
|
||||
if u != nil {
|
||||
oc.SetID(*u)
|
||||
}
|
||||
return oc
|
||||
}
|
||||
|
||||
// Mutation returns the OrganizationMutation object of the builder.
|
||||
func (oc *OrganizationCreate) Mutation() *OrganizationMutation {
|
||||
return oc.mutation
|
||||
}
|
||||
|
||||
// Save creates the Organization in the database.
|
||||
func (oc *OrganizationCreate) Save(ctx context.Context) (*Organization, error) {
|
||||
oc.defaults()
|
||||
return withHooks(ctx, oc.sqlSave, oc.mutation, oc.hooks)
|
||||
}
|
||||
|
||||
// SaveX calls Save and panics if Save returns an error.
|
||||
func (oc *OrganizationCreate) SaveX(ctx context.Context) *Organization {
|
||||
v, err := oc.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (oc *OrganizationCreate) Exec(ctx context.Context) error {
|
||||
_, err := oc.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (oc *OrganizationCreate) ExecX(ctx context.Context) {
|
||||
if err := oc.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// defaults sets the default values of the builder before save.
|
||||
func (oc *OrganizationCreate) defaults() {
|
||||
if _, ok := oc.mutation.CreatedAt(); !ok {
|
||||
v := organization.DefaultCreatedAt()
|
||||
oc.mutation.SetCreatedAt(v)
|
||||
}
|
||||
if _, ok := oc.mutation.UpdatedAt(); !ok {
|
||||
v := organization.DefaultUpdatedAt()
|
||||
oc.mutation.SetUpdatedAt(v)
|
||||
}
|
||||
if _, ok := oc.mutation.ID(); !ok {
|
||||
v := organization.DefaultID()
|
||||
oc.mutation.SetID(v)
|
||||
}
|
||||
}
|
||||
|
||||
// check runs all checks and user-defined validators on the builder.
|
||||
func (oc *OrganizationCreate) check() error {
|
||||
if _, ok := oc.mutation.CreatedAt(); !ok {
|
||||
return &ValidationError{Name: "created_at", err: errors.New(`ent: missing required field "Organization.created_at"`)}
|
||||
}
|
||||
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.Name(); !ok {
|
||||
return &ValidationError{Name: "name", err: errors.New(`ent: missing required field "Organization.name"`)}
|
||||
}
|
||||
if v, ok := oc.mutation.Name(); ok {
|
||||
if err := organization.NameValidator(v); err != nil {
|
||||
return &ValidationError{Name: "name", err: fmt.Errorf(`ent: validator failed for field "Organization.name": %w`, err)}
|
||||
}
|
||||
}
|
||||
if _, ok := oc.mutation.DisplayName(); !ok {
|
||||
return &ValidationError{Name: "display_name", err: errors.New(`ent: missing required field "Organization.display_name"`)}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (oc *OrganizationCreate) sqlSave(ctx context.Context) (*Organization, error) {
|
||||
if err := oc.check(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_node, _spec := oc.createSpec()
|
||||
if err := sqlgraph.CreateNode(ctx, oc.driver, _spec); err != nil {
|
||||
if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if _spec.ID.Value != nil {
|
||||
if id, ok := _spec.ID.Value.(*uuid.UUID); ok {
|
||||
_node.ID = *id
|
||||
} else if err := _node.ID.Scan(_spec.ID.Value); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
oc.mutation.id = &_node.ID
|
||||
oc.mutation.done = true
|
||||
return _node, nil
|
||||
}
|
||||
|
||||
func (oc *OrganizationCreate) createSpec() (*Organization, *sqlgraph.CreateSpec) {
|
||||
var (
|
||||
_node = &Organization{config: oc.config}
|
||||
_spec = sqlgraph.NewCreateSpec(organization.Table, sqlgraph.NewFieldSpec(organization.FieldID, field.TypeUUID))
|
||||
)
|
||||
_spec.OnConflict = oc.conflict
|
||||
if id, ok := oc.mutation.ID(); ok {
|
||||
_node.ID = id
|
||||
_spec.ID.Value = &id
|
||||
}
|
||||
if value, ok := oc.mutation.CreatedAt(); ok {
|
||||
_spec.SetField(organization.FieldCreatedAt, field.TypeTime, value)
|
||||
_node.CreatedAt = value
|
||||
}
|
||||
if value, ok := oc.mutation.UpdatedAt(); ok {
|
||||
_spec.SetField(organization.FieldUpdatedAt, field.TypeTime, value)
|
||||
_node.UpdatedAt = value
|
||||
}
|
||||
if value, ok := oc.mutation.Name(); ok {
|
||||
_spec.SetField(organization.FieldName, field.TypeString, value)
|
||||
_node.Name = value
|
||||
}
|
||||
if value, ok := oc.mutation.DisplayName(); ok {
|
||||
_spec.SetField(organization.FieldDisplayName, field.TypeString, value)
|
||||
_node.DisplayName = value
|
||||
}
|
||||
return _node, _spec
|
||||
}
|
||||
|
||||
// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
|
||||
// of the `INSERT` statement. For example:
|
||||
//
|
||||
// client.Organization.Create().
|
||||
// SetCreatedAt(v).
|
||||
// OnConflict(
|
||||
// // Update the row with the new values
|
||||
// // the was proposed for insertion.
|
||||
// sql.ResolveWithNewValues(),
|
||||
// ).
|
||||
// // Override some of the fields with custom
|
||||
// // update values.
|
||||
// Update(func(u *ent.OrganizationUpsert) {
|
||||
// SetCreatedAt(v+v).
|
||||
// }).
|
||||
// Exec(ctx)
|
||||
func (oc *OrganizationCreate) OnConflict(opts ...sql.ConflictOption) *OrganizationUpsertOne {
|
||||
oc.conflict = opts
|
||||
return &OrganizationUpsertOne{
|
||||
create: oc,
|
||||
}
|
||||
}
|
||||
|
||||
// OnConflictColumns calls `OnConflict` and configures the columns
|
||||
// as conflict target. Using this option is equivalent to using:
|
||||
//
|
||||
// client.Organization.Create().
|
||||
// OnConflict(sql.ConflictColumns(columns...)).
|
||||
// Exec(ctx)
|
||||
func (oc *OrganizationCreate) OnConflictColumns(columns ...string) *OrganizationUpsertOne {
|
||||
oc.conflict = append(oc.conflict, sql.ConflictColumns(columns...))
|
||||
return &OrganizationUpsertOne{
|
||||
create: oc,
|
||||
}
|
||||
}
|
||||
|
||||
type (
|
||||
// OrganizationUpsertOne is the builder for "upsert"-ing
|
||||
// one Organization node.
|
||||
OrganizationUpsertOne struct {
|
||||
create *OrganizationCreate
|
||||
}
|
||||
|
||||
// OrganizationUpsert is the "OnConflict" setter.
|
||||
OrganizationUpsert struct {
|
||||
*sql.UpdateSet
|
||||
}
|
||||
)
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (u *OrganizationUpsert) SetUpdatedAt(v time.Time) *OrganizationUpsert {
|
||||
u.Set(organization.FieldUpdatedAt, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
|
||||
func (u *OrganizationUpsert) UpdateUpdatedAt() *OrganizationUpsert {
|
||||
u.SetExcluded(organization.FieldUpdatedAt)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetName sets the "name" field.
|
||||
func (u *OrganizationUpsert) SetName(v string) *OrganizationUpsert {
|
||||
u.Set(organization.FieldName, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateName sets the "name" field to the value that was provided on create.
|
||||
func (u *OrganizationUpsert) UpdateName() *OrganizationUpsert {
|
||||
u.SetExcluded(organization.FieldName)
|
||||
return u
|
||||
}
|
||||
|
||||
// SetDisplayName sets the "display_name" field.
|
||||
func (u *OrganizationUpsert) SetDisplayName(v string) *OrganizationUpsert {
|
||||
u.Set(organization.FieldDisplayName, v)
|
||||
return u
|
||||
}
|
||||
|
||||
// UpdateDisplayName sets the "display_name" field to the value that was provided on create.
|
||||
func (u *OrganizationUpsert) UpdateDisplayName() *OrganizationUpsert {
|
||||
u.SetExcluded(organization.FieldDisplayName)
|
||||
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:
|
||||
//
|
||||
// client.Organization.Create().
|
||||
// OnConflict(
|
||||
// sql.ResolveWithNewValues(),
|
||||
// sql.ResolveWith(func(u *sql.UpdateSet) {
|
||||
// u.SetIgnore(organization.FieldID)
|
||||
// }),
|
||||
// ).
|
||||
// Exec(ctx)
|
||||
func (u *OrganizationUpsertOne) UpdateNewValues() *OrganizationUpsertOne {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
|
||||
if _, exists := u.create.mutation.ID(); exists {
|
||||
s.SetIgnore(organization.FieldID)
|
||||
}
|
||||
if _, exists := u.create.mutation.CreatedAt(); exists {
|
||||
s.SetIgnore(organization.FieldCreatedAt)
|
||||
}
|
||||
}))
|
||||
return u
|
||||
}
|
||||
|
||||
// Ignore sets each column to itself in case of conflict.
|
||||
// Using this option is equivalent to using:
|
||||
//
|
||||
// client.Organization.Create().
|
||||
// OnConflict(sql.ResolveWithIgnore()).
|
||||
// Exec(ctx)
|
||||
func (u *OrganizationUpsertOne) Ignore() *OrganizationUpsertOne {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
|
||||
return u
|
||||
}
|
||||
|
||||
// DoNothing configures the conflict_action to `DO NOTHING`.
|
||||
// Supported only by SQLite and PostgreSQL.
|
||||
func (u *OrganizationUpsertOne) DoNothing() *OrganizationUpsertOne {
|
||||
u.create.conflict = append(u.create.conflict, sql.DoNothing())
|
||||
return u
|
||||
}
|
||||
|
||||
// Update allows overriding fields `UPDATE` values. See the OrganizationCreate.OnConflict
|
||||
// documentation for more info.
|
||||
func (u *OrganizationUpsertOne) Update(set func(*OrganizationUpsert)) *OrganizationUpsertOne {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
|
||||
set(&OrganizationUpsert{UpdateSet: update})
|
||||
}))
|
||||
return u
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (u *OrganizationUpsertOne) SetUpdatedAt(v time.Time) *OrganizationUpsertOne {
|
||||
return u.Update(func(s *OrganizationUpsert) {
|
||||
s.SetUpdatedAt(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
|
||||
func (u *OrganizationUpsertOne) UpdateUpdatedAt() *OrganizationUpsertOne {
|
||||
return u.Update(func(s *OrganizationUpsert) {
|
||||
s.UpdateUpdatedAt()
|
||||
})
|
||||
}
|
||||
|
||||
// SetName sets the "name" field.
|
||||
func (u *OrganizationUpsertOne) SetName(v string) *OrganizationUpsertOne {
|
||||
return u.Update(func(s *OrganizationUpsert) {
|
||||
s.SetName(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateName sets the "name" field to the value that was provided on create.
|
||||
func (u *OrganizationUpsertOne) UpdateName() *OrganizationUpsertOne {
|
||||
return u.Update(func(s *OrganizationUpsert) {
|
||||
s.UpdateName()
|
||||
})
|
||||
}
|
||||
|
||||
// SetDisplayName sets the "display_name" field.
|
||||
func (u *OrganizationUpsertOne) SetDisplayName(v string) *OrganizationUpsertOne {
|
||||
return u.Update(func(s *OrganizationUpsert) {
|
||||
s.SetDisplayName(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateDisplayName sets the "display_name" field to the value that was provided on create.
|
||||
func (u *OrganizationUpsertOne) UpdateDisplayName() *OrganizationUpsertOne {
|
||||
return u.Update(func(s *OrganizationUpsert) {
|
||||
s.UpdateDisplayName()
|
||||
})
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (u *OrganizationUpsertOne) Exec(ctx context.Context) error {
|
||||
if len(u.create.conflict) == 0 {
|
||||
return errors.New("ent: missing options for OrganizationCreate.OnConflict")
|
||||
}
|
||||
return u.create.Exec(ctx)
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (u *OrganizationUpsertOne) ExecX(ctx context.Context) {
|
||||
if err := u.create.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// Exec executes the UPSERT query and returns the inserted/updated ID.
|
||||
func (u *OrganizationUpsertOne) ID(ctx context.Context) (id uuid.UUID, err error) {
|
||||
if u.create.driver.Dialect() == dialect.MySQL {
|
||||
// In case of "ON CONFLICT", there is no way to get back non-numeric ID
|
||||
// fields from the database since MySQL does not support the RETURNING clause.
|
||||
return id, errors.New("ent: OrganizationUpsertOne.ID is not supported by MySQL driver. Use OrganizationUpsertOne.Exec instead")
|
||||
}
|
||||
node, err := u.create.Save(ctx)
|
||||
if err != nil {
|
||||
return id, err
|
||||
}
|
||||
return node.ID, nil
|
||||
}
|
||||
|
||||
// IDX is like ID, but panics if an error occurs.
|
||||
func (u *OrganizationUpsertOne) IDX(ctx context.Context) uuid.UUID {
|
||||
id, err := u.ID(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// OrganizationCreateBulk is the builder for creating many Organization entities in bulk.
|
||||
type OrganizationCreateBulk struct {
|
||||
config
|
||||
err error
|
||||
builders []*OrganizationCreate
|
||||
conflict []sql.ConflictOption
|
||||
}
|
||||
|
||||
// Save creates the Organization entities in the database.
|
||||
func (ocb *OrganizationCreateBulk) Save(ctx context.Context) ([]*Organization, error) {
|
||||
if ocb.err != nil {
|
||||
return nil, ocb.err
|
||||
}
|
||||
specs := make([]*sqlgraph.CreateSpec, len(ocb.builders))
|
||||
nodes := make([]*Organization, len(ocb.builders))
|
||||
mutators := make([]Mutator, len(ocb.builders))
|
||||
for i := range ocb.builders {
|
||||
func(i int, root context.Context) {
|
||||
builder := ocb.builders[i]
|
||||
builder.defaults()
|
||||
var mut Mutator = MutateFunc(func(ctx context.Context, m Mutation) (Value, error) {
|
||||
mutation, ok := m.(*OrganizationMutation)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unexpected mutation type %T", m)
|
||||
}
|
||||
if err := builder.check(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
builder.mutation = mutation
|
||||
var err error
|
||||
nodes[i], specs[i] = builder.createSpec()
|
||||
if i < len(mutators)-1 {
|
||||
_, err = mutators[i+1].Mutate(root, ocb.builders[i+1].mutation)
|
||||
} else {
|
||||
spec := &sqlgraph.BatchCreateSpec{Nodes: specs}
|
||||
spec.OnConflict = ocb.conflict
|
||||
// Invoke the actual operation on the latest mutation in the chain.
|
||||
if err = sqlgraph.BatchCreate(ctx, ocb.driver, spec); err != nil {
|
||||
if sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mutation.id = &nodes[i].ID
|
||||
mutation.done = true
|
||||
return nodes[i], nil
|
||||
})
|
||||
for i := len(builder.hooks) - 1; i >= 0; i-- {
|
||||
mut = builder.hooks[i](mut)
|
||||
}
|
||||
mutators[i] = mut
|
||||
}(i, ctx)
|
||||
}
|
||||
if len(mutators) > 0 {
|
||||
if _, err := mutators[0].Mutate(ctx, ocb.builders[0].mutation); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return nodes, nil
|
||||
}
|
||||
|
||||
// SaveX is like Save, but panics if an error occurs.
|
||||
func (ocb *OrganizationCreateBulk) SaveX(ctx context.Context) []*Organization {
|
||||
v, err := ocb.Save(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (ocb *OrganizationCreateBulk) Exec(ctx context.Context) error {
|
||||
_, err := ocb.Save(ctx)
|
||||
return err
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (ocb *OrganizationCreateBulk) ExecX(ctx context.Context) {
|
||||
if err := ocb.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
// OnConflict allows configuring the `ON CONFLICT` / `ON DUPLICATE KEY` clause
|
||||
// of the `INSERT` statement. For example:
|
||||
//
|
||||
// client.Organization.CreateBulk(builders...).
|
||||
// OnConflict(
|
||||
// // Update the row with the new values
|
||||
// // the was proposed for insertion.
|
||||
// sql.ResolveWithNewValues(),
|
||||
// ).
|
||||
// // Override some of the fields with custom
|
||||
// // update values.
|
||||
// Update(func(u *ent.OrganizationUpsert) {
|
||||
// SetCreatedAt(v+v).
|
||||
// }).
|
||||
// Exec(ctx)
|
||||
func (ocb *OrganizationCreateBulk) OnConflict(opts ...sql.ConflictOption) *OrganizationUpsertBulk {
|
||||
ocb.conflict = opts
|
||||
return &OrganizationUpsertBulk{
|
||||
create: ocb,
|
||||
}
|
||||
}
|
||||
|
||||
// OnConflictColumns calls `OnConflict` and configures the columns
|
||||
// as conflict target. Using this option is equivalent to using:
|
||||
//
|
||||
// client.Organization.Create().
|
||||
// OnConflict(sql.ConflictColumns(columns...)).
|
||||
// Exec(ctx)
|
||||
func (ocb *OrganizationCreateBulk) OnConflictColumns(columns ...string) *OrganizationUpsertBulk {
|
||||
ocb.conflict = append(ocb.conflict, sql.ConflictColumns(columns...))
|
||||
return &OrganizationUpsertBulk{
|
||||
create: ocb,
|
||||
}
|
||||
}
|
||||
|
||||
// OrganizationUpsertBulk is the builder for "upsert"-ing
|
||||
// a bulk of Organization nodes.
|
||||
type OrganizationUpsertBulk struct {
|
||||
create *OrganizationCreateBulk
|
||||
}
|
||||
|
||||
// UpdateNewValues updates the mutable fields using the new values that
|
||||
// were set on create. Using this option is equivalent to using:
|
||||
//
|
||||
// client.Organization.Create().
|
||||
// OnConflict(
|
||||
// sql.ResolveWithNewValues(),
|
||||
// sql.ResolveWith(func(u *sql.UpdateSet) {
|
||||
// u.SetIgnore(organization.FieldID)
|
||||
// }),
|
||||
// ).
|
||||
// Exec(ctx)
|
||||
func (u *OrganizationUpsertBulk) UpdateNewValues() *OrganizationUpsertBulk {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWithNewValues())
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(s *sql.UpdateSet) {
|
||||
for _, b := range u.create.builders {
|
||||
if _, exists := b.mutation.ID(); exists {
|
||||
s.SetIgnore(organization.FieldID)
|
||||
}
|
||||
if _, exists := b.mutation.CreatedAt(); exists {
|
||||
s.SetIgnore(organization.FieldCreatedAt)
|
||||
}
|
||||
}
|
||||
}))
|
||||
return u
|
||||
}
|
||||
|
||||
// Ignore sets each column to itself in case of conflict.
|
||||
// Using this option is equivalent to using:
|
||||
//
|
||||
// client.Organization.Create().
|
||||
// OnConflict(sql.ResolveWithIgnore()).
|
||||
// Exec(ctx)
|
||||
func (u *OrganizationUpsertBulk) Ignore() *OrganizationUpsertBulk {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWithIgnore())
|
||||
return u
|
||||
}
|
||||
|
||||
// DoNothing configures the conflict_action to `DO NOTHING`.
|
||||
// Supported only by SQLite and PostgreSQL.
|
||||
func (u *OrganizationUpsertBulk) DoNothing() *OrganizationUpsertBulk {
|
||||
u.create.conflict = append(u.create.conflict, sql.DoNothing())
|
||||
return u
|
||||
}
|
||||
|
||||
// Update allows overriding fields `UPDATE` values. See the OrganizationCreateBulk.OnConflict
|
||||
// documentation for more info.
|
||||
func (u *OrganizationUpsertBulk) Update(set func(*OrganizationUpsert)) *OrganizationUpsertBulk {
|
||||
u.create.conflict = append(u.create.conflict, sql.ResolveWith(func(update *sql.UpdateSet) {
|
||||
set(&OrganizationUpsert{UpdateSet: update})
|
||||
}))
|
||||
return u
|
||||
}
|
||||
|
||||
// SetUpdatedAt sets the "updated_at" field.
|
||||
func (u *OrganizationUpsertBulk) SetUpdatedAt(v time.Time) *OrganizationUpsertBulk {
|
||||
return u.Update(func(s *OrganizationUpsert) {
|
||||
s.SetUpdatedAt(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateUpdatedAt sets the "updated_at" field to the value that was provided on create.
|
||||
func (u *OrganizationUpsertBulk) UpdateUpdatedAt() *OrganizationUpsertBulk {
|
||||
return u.Update(func(s *OrganizationUpsert) {
|
||||
s.UpdateUpdatedAt()
|
||||
})
|
||||
}
|
||||
|
||||
// SetName sets the "name" field.
|
||||
func (u *OrganizationUpsertBulk) SetName(v string) *OrganizationUpsertBulk {
|
||||
return u.Update(func(s *OrganizationUpsert) {
|
||||
s.SetName(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateName sets the "name" field to the value that was provided on create.
|
||||
func (u *OrganizationUpsertBulk) UpdateName() *OrganizationUpsertBulk {
|
||||
return u.Update(func(s *OrganizationUpsert) {
|
||||
s.UpdateName()
|
||||
})
|
||||
}
|
||||
|
||||
// SetDisplayName sets the "display_name" field.
|
||||
func (u *OrganizationUpsertBulk) SetDisplayName(v string) *OrganizationUpsertBulk {
|
||||
return u.Update(func(s *OrganizationUpsert) {
|
||||
s.SetDisplayName(v)
|
||||
})
|
||||
}
|
||||
|
||||
// UpdateDisplayName sets the "display_name" field to the value that was provided on create.
|
||||
func (u *OrganizationUpsertBulk) UpdateDisplayName() *OrganizationUpsertBulk {
|
||||
return u.Update(func(s *OrganizationUpsert) {
|
||||
s.UpdateDisplayName()
|
||||
})
|
||||
}
|
||||
|
||||
// Exec executes the query.
|
||||
func (u *OrganizationUpsertBulk) Exec(ctx context.Context) error {
|
||||
if u.create.err != nil {
|
||||
return u.create.err
|
||||
}
|
||||
for i, b := range u.create.builders {
|
||||
if len(b.conflict) != 0 {
|
||||
return fmt.Errorf("ent: OnConflict was set for builder %d. Set it on the OrganizationCreateBulk instead", i)
|
||||
}
|
||||
}
|
||||
if len(u.create.conflict) == 0 {
|
||||
return errors.New("ent: missing options for OrganizationCreateBulk.OnConflict")
|
||||
}
|
||||
return u.create.Exec(ctx)
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (u *OrganizationUpsertBulk) ExecX(ctx context.Context) {
|
||||
if err := u.create.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
88
internal/ent/organization_delete.go
Normal file
88
internal/ent/organization_delete.go
Normal 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/organization"
|
||||
"github.com/holos-run/holos/internal/ent/predicate"
|
||||
)
|
||||
|
||||
// OrganizationDelete is the builder for deleting a Organization entity.
|
||||
type OrganizationDelete struct {
|
||||
config
|
||||
hooks []Hook
|
||||
mutation *OrganizationMutation
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the OrganizationDelete builder.
|
||||
func (od *OrganizationDelete) Where(ps ...predicate.Organization) *OrganizationDelete {
|
||||
od.mutation.Where(ps...)
|
||||
return od
|
||||
}
|
||||
|
||||
// Exec executes the deletion query and returns how many vertices were deleted.
|
||||
func (od *OrganizationDelete) Exec(ctx context.Context) (int, error) {
|
||||
return withHooks(ctx, od.sqlExec, od.mutation, od.hooks)
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (od *OrganizationDelete) ExecX(ctx context.Context) int {
|
||||
n, err := od.Exec(ctx)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func (od *OrganizationDelete) sqlExec(ctx context.Context) (int, error) {
|
||||
_spec := sqlgraph.NewDeleteSpec(organization.Table, sqlgraph.NewFieldSpec(organization.FieldID, field.TypeUUID))
|
||||
if ps := od.mutation.predicates; len(ps) > 0 {
|
||||
_spec.Predicate = func(selector *sql.Selector) {
|
||||
for i := range ps {
|
||||
ps[i](selector)
|
||||
}
|
||||
}
|
||||
}
|
||||
affected, err := sqlgraph.DeleteNodes(ctx, od.driver, _spec)
|
||||
if err != nil && sqlgraph.IsConstraintError(err) {
|
||||
err = &ConstraintError{msg: err.Error(), wrap: err}
|
||||
}
|
||||
od.mutation.done = true
|
||||
return affected, err
|
||||
}
|
||||
|
||||
// OrganizationDeleteOne is the builder for deleting a single Organization entity.
|
||||
type OrganizationDeleteOne struct {
|
||||
od *OrganizationDelete
|
||||
}
|
||||
|
||||
// Where appends a list predicates to the OrganizationDelete builder.
|
||||
func (odo *OrganizationDeleteOne) Where(ps ...predicate.Organization) *OrganizationDeleteOne {
|
||||
odo.od.mutation.Where(ps...)
|
||||
return odo
|
||||
}
|
||||
|
||||
// Exec executes the deletion query.
|
||||
func (odo *OrganizationDeleteOne) Exec(ctx context.Context) error {
|
||||
n, err := odo.od.Exec(ctx)
|
||||
switch {
|
||||
case err != nil:
|
||||
return err
|
||||
case n == 0:
|
||||
return &NotFoundError{organization.Label}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// ExecX is like Exec, but panics if an error occurs.
|
||||
func (odo *OrganizationDeleteOne) ExecX(ctx context.Context) {
|
||||
if err := odo.Exec(ctx); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user