mirror of
https://github.com/holos-run/holos.git
synced 2026-03-19 16:54:58 +00:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4127804092 | ||
|
|
8f424cfabe | ||
|
|
699148abdd | ||
|
|
73f777759e | ||
|
|
8b9070f185 | ||
|
|
1e8861c8b7 | ||
|
|
bdc182f4eb | ||
|
|
4db3fb4ead | ||
|
|
1911c7fe01 | ||
|
|
5e582ec5c6 |
@@ -30,6 +30,7 @@
|
||||
"errgroup",
|
||||
"fieldmaskpb",
|
||||
"flushcache",
|
||||
"gendoc",
|
||||
"ghaction",
|
||||
"gitops",
|
||||
"godoc",
|
||||
@@ -68,6 +69,7 @@
|
||||
"pflag",
|
||||
"PKCE",
|
||||
"platformconnect",
|
||||
"podinfo",
|
||||
"promhttp",
|
||||
"protobuf",
|
||||
"protojson",
|
||||
|
||||
@@ -2,11 +2,6 @@ package v1alpha3
|
||||
|
||||
import "google.golang.org/protobuf/types/known/structpb"
|
||||
|
||||
type PlatformMetadata struct {
|
||||
// Name represents the Platform name.
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// Platform represents a platform to manage. A Platform resource informs holos
|
||||
// which components to build. The platform resource also acts as a container
|
||||
// for the platform model form values provided by the PlatformService. The
|
||||
@@ -24,13 +19,18 @@ type Platform struct {
|
||||
Spec PlatformSpec `json:"spec"`
|
||||
}
|
||||
|
||||
type PlatformMetadata struct {
|
||||
// Name represents the Platform name.
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// PlatformSpec represents the specification of a Platform. Think of a platform
|
||||
// specification as a list of platform components to apply to a list of
|
||||
// kubernetes clusters combined with the user-specified Platform Model.
|
||||
type PlatformSpec struct {
|
||||
// Model represents the platform model holos gets from from the
|
||||
// PlatformService.GetPlatform rpc method and provides to CUE using a tag.
|
||||
Model structpb.Struct `json:"model"`
|
||||
Model structpb.Struct `json:"model" cue:"{...}"`
|
||||
// Components represents a list of holos components to manage.
|
||||
Components []PlatformSpecComponent `json:"components"`
|
||||
}
|
||||
|
||||
150
api/schema/v1alpha3/definitions.go
Normal file
150
api/schema/v1alpha3/definitions.go
Normal file
@@ -0,0 +1,150 @@
|
||||
// Package v1alpha3 contains CUE definitions intended as convenience wrappers
|
||||
// around the core data types defined in package core. The purpose of these
|
||||
// wrappers is to make life easier for platform engineers by reducing boiler
|
||||
// plate code and generating component build plans in a consistent manner.
|
||||
package v1alpha3
|
||||
|
||||
import (
|
||||
core "github.com/holos-run/holos/api/core/v1alpha3"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
)
|
||||
|
||||
//go:generate ../../../hack/gendoc
|
||||
|
||||
// Helm provides a BuildPlan via the Output field which contains one HelmChart
|
||||
// from package core. Useful as a convenience wrapper to render a HelmChart
|
||||
// with optional mix-in resources and Kustomization post-processing.
|
||||
type Helm struct {
|
||||
// Name represents the chart name.
|
||||
Name string
|
||||
// Version represents the chart version.
|
||||
Version string
|
||||
// Namespace represents the helm namespace option when rendering the chart.
|
||||
Namespace string
|
||||
// Resources are kubernetes api objects to mix into the output.
|
||||
Resources map[string]any `cue:"{...}"`
|
||||
|
||||
// Repo represents the chart repository
|
||||
Repo struct {
|
||||
Name string `json:"name"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
// Values represents data to marshal into a values.yaml for helm.
|
||||
Values interface{} `cue:"{...}"`
|
||||
|
||||
// Chart represents the derived HelmChart for inclusion in the BuildPlan
|
||||
// Output field value. The default HelmChart field values are derived from
|
||||
// other Helm field values and should be sufficient for most use cases.
|
||||
Chart core.HelmChart
|
||||
|
||||
// EnableKustomizePostProcessor processes helm output with kustomize if true.
|
||||
EnableKustomizePostProcessor bool `cue:"true | *false"`
|
||||
|
||||
// KustomizeFiles represents additional files to include in a Kustomization
|
||||
// resources list. Useful to patch helm output. The implementation is a
|
||||
// struct with filename keys and structs as values. Holos encodes the struct
|
||||
// value to yaml then writes the result to the filename key. Component
|
||||
// authors may then reference the filename in the kustomization.yaml resources
|
||||
// or patches lists.
|
||||
// Requires EnableKustomizePostProcessor: true.
|
||||
KustomizeFiles map[string]any `cue:"{[string]: {...}}"`
|
||||
|
||||
// KustomizePatches represents patches to apply to the helm output. Requires
|
||||
// EnableKustomizePostProcessor: true.
|
||||
KustomizePatches map[core.InternalLabel]any `cue:"{[string]: {...}}"`
|
||||
|
||||
// KustomizeResources represents additional resources files to include in the
|
||||
// kustomize resources list.
|
||||
KustomizeResources map[string]any `cue:"{[string]: {...}}"`
|
||||
|
||||
// ArgoConfig represents the ArgoCD GitOps configuration for this Component.
|
||||
ArgoConfig ArgoConfig
|
||||
|
||||
// Output represents the derived BuildPlan for the Holos cli to render.
|
||||
Output core.BuildPlan
|
||||
}
|
||||
|
||||
// Resources represents the default schema for a Kubernetes API object resource.
|
||||
// For example, a Service, Namespace or Deployment. The top level key is the
|
||||
// kind of resource so default behavior and strict schema enforcement may be
|
||||
// enforced for the kind. The second level keys are an arbitrary internal
|
||||
// label, which serves as the default value for the resource metadata name
|
||||
// field, but may differ for situations where the same resource kind and name
|
||||
// are managed in different namespaces.
|
||||
//
|
||||
// Refer to [definitions.cue] for the CUE schema definition as an example to
|
||||
// build on when defining your own Components.
|
||||
//
|
||||
// [definitions.cue]: https://github.com/holos-run/holos/blob/main/internal/generate/platforms/cue.mod/pkg/github.com/holos-run/holos/api/schema/v1alpha3/definitions.cue#L9
|
||||
// type Resources map[string]map[string]any
|
||||
|
||||
// ArgoConfig represents the ArgoCD GitOps configuration for a Component.
|
||||
// Useful to define once at the root of the Platform configuration and reuse
|
||||
// across all Components.
|
||||
type ArgoConfig struct {
|
||||
// Enabled causes holos to render an ArgoCD Application resource for GitOps if true.
|
||||
Enabled bool `cue:"true | *false"`
|
||||
// ClusterName represents the cluster within the platform the Application
|
||||
// resource is intended for.
|
||||
ClusterName string
|
||||
// DeployRoot represents the path from the git repository root to the `deploy`
|
||||
// rendering output directory. Used as a prefix for the
|
||||
// Application.spec.source.path field.
|
||||
DeployRoot string `cue:"string | *\".\""`
|
||||
// RepoURL represents the value passed to the Application.spec.source.repoURL
|
||||
// field.
|
||||
RepoURL string
|
||||
// TargetRevision represents the value passed to the
|
||||
// Application.spec.source.targetRevision field. Defaults to the branch named
|
||||
// main.
|
||||
TargetRevision string `cue:"string | *\"main\""`
|
||||
}
|
||||
|
||||
// Cluster represents a cluster managed by the Platform.
|
||||
type Cluster struct {
|
||||
// Name represents the cluster name, for example "east1", "west1", or
|
||||
// "management".
|
||||
Name string `json:"name"`
|
||||
// Primary represents if the cluster is marked as the primary among a set of
|
||||
// candidate clusters. Useful for promotion of database leaders.
|
||||
Primary bool `json:"primary" cue:"true | *false"`
|
||||
}
|
||||
|
||||
// Fleet represents a named collection of similarly configured Clusters. Useful
|
||||
// to segregate workload clusters from their management cluster.
|
||||
type Fleet struct {
|
||||
Name string `json:"name"`
|
||||
// Clusters represents a mapping of Clusters by their name.
|
||||
Clusters map[string]Cluster `json:"clusters" cue:"{[Name=_]: name: Name}"`
|
||||
}
|
||||
|
||||
// StandardFleets represents the standard set of Clusters in a Platform
|
||||
// segmented into Fleets by their purpose. The management Fleet contains a
|
||||
// single Cluster, for example a GKE autopilot cluster with no workloads
|
||||
// deployed for reliability and cost efficiency. The workload Fleet contains
|
||||
// all other Clusters which contain workloads and sync Secrets from the
|
||||
// management cluster.
|
||||
type StandardFleets struct {
|
||||
// Workload represents a Fleet of zero or more workload Clusters.
|
||||
Workload Fleet `json:"workload" cue:"{name: \"workload\"}"`
|
||||
// Management represents a Fleet with one Cluster named management.
|
||||
Management Fleet `json:"management" cue:"{name: \"management\", clusters: management: _}"`
|
||||
}
|
||||
|
||||
// Platform is a convenience structure to produce a core Platform specification
|
||||
// value in the Output field. Useful to collect components at the root of the
|
||||
// Platform configuration tree as a struct, which are automatically converted
|
||||
// into a list for the core Platform spec output.
|
||||
type Platform struct {
|
||||
// Name represents the Platform name.
|
||||
Name string `cue:"string | *\"holos\""`
|
||||
// Components is a structured map of components to manage by their name.
|
||||
Components map[string]core.PlatformSpecComponent
|
||||
// Model represents the Platform model holos gets from from the
|
||||
// PlatformService.GetPlatform rpc method and provides to CUE using a tag.
|
||||
Model structpb.Struct `cue:"{...}"`
|
||||
// Output represents the core Platform spec for the holos cli to iterate over
|
||||
// and render each listed Component, injecting the Model.
|
||||
Output core.Platform
|
||||
}
|
||||
@@ -368,7 +368,7 @@ PlatformSpec represents the specification of a Platform. Think of a platform spe
|
||||
type PlatformSpec struct {
|
||||
// Model represents the platform model holos gets from from the
|
||||
// PlatformService.GetPlatform rpc method and provides to CUE using a tag.
|
||||
Model structpb.Struct `json:"model"`
|
||||
Model structpb.Struct `json:"model" cue:"{...}"`
|
||||
// Components represents a list of holos components to manage.
|
||||
Components []PlatformSpecComponent `json:"components"`
|
||||
}
|
||||
|
||||
168
doc/md/api/schema/v1alpha3.md
Normal file
168
doc/md/api/schema/v1alpha3.md
Normal file
@@ -0,0 +1,168 @@
|
||||
<!-- Code generated by gomarkdoc. DO NOT EDIT -->
|
||||
|
||||
# v1alpha3
|
||||
|
||||
```go
|
||||
import "github.com/holos-run/holos/api/schema/v1alpha3"
|
||||
```
|
||||
|
||||
Package v1alpha3 contains CUE definitions intended as convenience wrappers around the core data types defined in package core. The purpose of these wrappers is to make life easier for platform engineers by reducing boiler plate code and generating component build plans in a consistent manner.
|
||||
|
||||
## Index
|
||||
|
||||
- [type ArgoConfig](<#ArgoConfig>)
|
||||
- [type Cluster](<#Cluster>)
|
||||
- [type Fleet](<#Fleet>)
|
||||
- [type Helm](<#Helm>)
|
||||
- [type Platform](<#Platform>)
|
||||
- [type StandardFleets](<#StandardFleets>)
|
||||
|
||||
|
||||
<a name="ArgoConfig"></a>
|
||||
## type ArgoConfig {#ArgoConfig}
|
||||
|
||||
ArgoConfig represents the ArgoCD GitOps configuration for a Component. Useful to define once at the root of the Platform configuration and reuse across all Components.
|
||||
|
||||
```go
|
||||
type ArgoConfig struct {
|
||||
// Enabled causes holos to render an ArgoCD Application resource for GitOps if true.
|
||||
Enabled bool `cue:"true | *false"`
|
||||
// ClusterName represents the cluster within the platform the Application
|
||||
// resource is intended for.
|
||||
ClusterName string
|
||||
// DeployRoot represents the path from the git repository root to the `deploy`
|
||||
// rendering output directory. Used as a prefix for the
|
||||
// Application.spec.source.path field.
|
||||
DeployRoot string `cue:"string | *\".\""`
|
||||
// RepoURL represents the value passed to the Application.spec.source.repoURL
|
||||
// field.
|
||||
RepoURL string
|
||||
// TargetRevision represents the value passed to the
|
||||
// Application.spec.source.targetRevision field. Defaults to the branch named
|
||||
// main.
|
||||
TargetRevision string `cue:"string | *\"main\""`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Cluster"></a>
|
||||
## type Cluster {#Cluster}
|
||||
|
||||
Cluster represents a cluster managed by the Platform.
|
||||
|
||||
```go
|
||||
type Cluster struct {
|
||||
// Name represents the cluster name, for example "east1", "west1", or
|
||||
// "management".
|
||||
Name string `json:"name"`
|
||||
// Primary represents if the cluster is marked as the primary among a set of
|
||||
// candidate clusters. Useful for promotion of database leaders.
|
||||
Primary bool `json:"primary" cue:"true | *false"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Fleet"></a>
|
||||
## type Fleet {#Fleet}
|
||||
|
||||
Fleet represents a named collection of similarly configured Clusters. Useful to segregate workload clusters from their management cluster.
|
||||
|
||||
```go
|
||||
type Fleet struct {
|
||||
Name string `json:"name"`
|
||||
// Clusters represents a mapping of Clusters by their name.
|
||||
Clusters map[string]Cluster `json:"clusters" cue:"{[Name=_]: name: Name}"`
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Helm"></a>
|
||||
## type Helm {#Helm}
|
||||
|
||||
Helm provides a BuildPlan via the Output field which contains one HelmChart from package core. Useful as a convenience wrapper to render a HelmChart with optional mix\-in resources and Kustomization post\-processing.
|
||||
|
||||
```go
|
||||
type Helm struct {
|
||||
// Name represents the chart name.
|
||||
Name string
|
||||
// Version represents the chart version.
|
||||
Version string
|
||||
// Namespace represents the helm namespace option when rendering the chart.
|
||||
Namespace string
|
||||
// Resources are kubernetes api objects to mix into the output.
|
||||
Resources map[string]any `cue:"{...}"`
|
||||
|
||||
// Repo represents the chart repository
|
||||
Repo struct {
|
||||
Name string `json:"name"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
// Values represents data to marshal into a values.yaml for helm.
|
||||
Values interface{} `cue:"{...}"`
|
||||
|
||||
// Chart represents the derived HelmChart for inclusion in the BuildPlan
|
||||
// Output field value. The default HelmChart field values are derived from
|
||||
// other Helm field values and should be sufficient for most use cases.
|
||||
Chart core.HelmChart
|
||||
|
||||
// EnableKustomizePostProcessor processes helm output with kustomize if true.
|
||||
EnableKustomizePostProcessor bool `cue:"true | *false"`
|
||||
|
||||
// KustomizeFiles represents additional files to include in a Kustomization
|
||||
// resources list. Useful to patch helm output. The implementation is a
|
||||
// struct with filename keys and structs as values. Holos encodes the struct
|
||||
// value to yaml then writes the result to the filename key. Component
|
||||
// authors may then reference the filename in the kustomization.yaml resources
|
||||
// or patches lists.
|
||||
// Requires EnableKustomizePostProcessor: true.
|
||||
KustomizeFiles map[string]any `cue:"{[string]: {...}}"`
|
||||
|
||||
// KustomizePatches represents patches to apply to the helm output. Requires
|
||||
// EnableKustomizePostProcessor: true.
|
||||
KustomizePatches map[core.InternalLabel]any `cue:"{[string]: {...}}"`
|
||||
|
||||
// KustomizeResources represents additional resources files to include in the
|
||||
// kustomize resources list.
|
||||
KustomizeResources map[string]any `cue:"{[string]: {...}}"`
|
||||
|
||||
// ArgoConfig represents the ArgoCD GitOps configuration for this Component.
|
||||
ArgoConfig ArgoConfig
|
||||
|
||||
// Output represents the derived BuildPlan for the Holos cli to render.
|
||||
Output core.BuildPlan
|
||||
}
|
||||
```
|
||||
|
||||
<a name="Platform"></a>
|
||||
## type Platform {#Platform}
|
||||
|
||||
Platform is a convenience structure to produce a core Platform specification value in the Output field. Useful to collect components at the root of the Platform configuration tree as a struct, which are automatically converted into a list for the core Platform spec output.
|
||||
|
||||
```go
|
||||
type Platform struct {
|
||||
// Name represents the Platform name.
|
||||
Name string `cue:"string | *\"holos\""`
|
||||
// Components is a structured map of components to manage by their name.
|
||||
Components map[string]core.PlatformSpecComponent
|
||||
// Model represents the Platform model holos gets from from the
|
||||
// PlatformService.GetPlatform rpc method and provides to CUE using a tag.
|
||||
Model structpb.Struct `cue:"{...}"`
|
||||
// Output represents the core Platform spec for the holos cli to iterate over
|
||||
// and render each listed Component, injecting the Model.
|
||||
Output core.Platform
|
||||
}
|
||||
```
|
||||
|
||||
<a name="StandardFleets"></a>
|
||||
## type StandardFleets {#StandardFleets}
|
||||
|
||||
StandardFleets represents the standard set of Clusters in a Platform segmented into Fleets by their purpose. The management Fleet contains a single Cluster, for example a GKE autopilot cluster with no workloads deployed for reliability and cost efficiency. The workload Fleet contains all other Clusters which contain workloads and sync Secrets from the management cluster.
|
||||
|
||||
```go
|
||||
type StandardFleets struct {
|
||||
// Workload represents a Fleet of zero or more workload Clusters.
|
||||
Workload Fleet `json:"workload" cue:"{name: \"workload\"}"`
|
||||
// Management represents a Fleet with one Cluster named management.
|
||||
Management Fleet `json:"management" cue:"{name: \"management\", clusters: management: _}"`
|
||||
}
|
||||
```
|
||||
|
||||
Generated by [gomarkdoc](<https://github.com/princjef/gomarkdoc>)
|
||||
@@ -13,10 +13,17 @@ and more consistent.
|
||||
You'll need the following tools installed to complete this guide.
|
||||
|
||||
1. [holos](/docs/install) - to build the platform.
|
||||
2. [helm](https://helm.sh/docs/intro/install/) - to render Holos components that wrap upstream Helm charts.
|
||||
3. [k3d](https://k3d.io/#installation) - to provide a Kubernetes API server.
|
||||
4. [OrbStack](https://docs.orbstack.dev/install) or [Docker](https://docs.docker.com/get-docker/) - to use k3d.
|
||||
5. [kubectl](https://kubernetes.io/docs/tasks/tools/) - to interact with the k8s api server.
|
||||
2. [helm](https://helm.sh/docs/intro/install/) - to render Holos components that
|
||||
wrap upstream Helm charts.
|
||||
|
||||
Optionally, if you'd like to apply the rendered manifests to a real cluster
|
||||
you'll need:
|
||||
|
||||
1. [k3d](https://k3d.io/#installation) - to provide a Kubernetes API server.
|
||||
2. [OrbStack](https://docs.orbstack.dev/install) or
|
||||
[Docker](https://docs.docker.com/get-docker/) - to use k3d.
|
||||
3. [kubectl](https://kubernetes.io/docs/tasks/tools/) - to interact with
|
||||
kubernetes.
|
||||
|
||||
## Install Holos
|
||||
|
||||
@@ -53,8 +60,8 @@ repository unless otherwise stated.
|
||||
## Generate the Platform {#Generate-Platform}
|
||||
|
||||
Generate the Platform code in the repository root. A Platform refers to all of
|
||||
the software and services integrated together to provide your organization's
|
||||
software development platform. In this guide the platform will contain a single
|
||||
the software holistically integrated to provide a software development platform
|
||||
for your organization. In this guide the platform will contain a single
|
||||
Component to demonstrate how the concepts fit together.
|
||||
|
||||
```bash
|
||||
@@ -63,7 +70,324 @@ holos generate platform quickstart
|
||||
|
||||
Commit the generated platform config to the repository.
|
||||
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "holos generate platform quickstart - $(holos --version)"
|
||||
```
|
||||
<Tabs groupId="commit-platform">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "holos generate platform quickstart - $(holos --version)"
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
[main (root-commit) 0b17b7f] holos generate platform quickstart
|
||||
213 files changed, 72349 insertions(+)
|
||||
...
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Generate a Component {#generate-component}
|
||||
|
||||
The platform you generated is empty. Generate the CUE code definition for a
|
||||
Component that wraps the podinfo Helm chart.
|
||||
|
||||
<Tabs groupId="gen-podinfo">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
holos generate component helm podinfo
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
generated component
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
This command produces two files. A leaf `components/podinfo/podinfo.gen.cue`
|
||||
file, and a root `podinfo.gen.cue` file. Holos takes advantage of the fact that
|
||||
[order is irrelevant](https://cuelang.org/docs/tour/basics/order-irrelevance/)
|
||||
in CUE to register the component with the Platform specification by adding a
|
||||
file to the root of the Git repository in addition to defining the component
|
||||
itself in the leaf component directory.
|
||||
|
||||
The Helm chart Component is defined in the `components/podinfo/podinfo.cue`
|
||||
file, for example:
|
||||
|
||||
<Tabs groupId="podinfo-files">
|
||||
<TabItem value="components/podinfo/podinfo.gen.cue" label="Leaf">
|
||||
`components/podinfo/podinfo.gen.cue`
|
||||
```cue
|
||||
package holos
|
||||
|
||||
// Produce a helm chart build plan.
|
||||
(#Helm & Chart).Output
|
||||
|
||||
let Chart = {
|
||||
Name: "podinfo"
|
||||
Version: "6.6.2"
|
||||
Namespace: "default"
|
||||
|
||||
Repo: name: "podinfo"
|
||||
Repo: url: "https://stefanprodan.github.io/podinfo"
|
||||
|
||||
Values: {}
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="podinfo.gen.cue" label="Root">
|
||||
`podinfo.gen.cue`
|
||||
```cue
|
||||
package holos
|
||||
|
||||
// Manage podinfo on workload clusters only
|
||||
for Cluster in #Fleets.workload.clusters {
|
||||
#Platform: Components: "\(Cluster.name)/podinfo": {
|
||||
path: "components/podinfo"
|
||||
cluster: Cluster.name
|
||||
}
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
In this example we're providing the minimal information about the Helm chart we
|
||||
want to manage. The name, version, Kubernetes namespace to deploy into, and the
|
||||
chart repository location.
|
||||
|
||||
This chart deploys cleanly with no values provided, but we include an empty
|
||||
Values struct to illustrate how Holos improves the consistency and safety of
|
||||
Helm by taking advantage the strong type checking in CUE. Shared values,
|
||||
such as the organization domain name, can safely be passed to all Components
|
||||
across all clusters in the Platform by defining them at the root of the
|
||||
configuration.
|
||||
|
||||
Commit the generated component config to the repository.
|
||||
|
||||
<Tabs groupId="commit-component">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "holos generate component helm podinfo - $(holos --version)"
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
[main cc0e90c] holos generate component helm podinfo
|
||||
2 files changed, 24 insertions(+)
|
||||
create mode 100644 components/podinfo/podinfo.gen.cue
|
||||
create mode 100644 podinfo.gen.cue
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
## Render the Component
|
||||
|
||||
Individual components can be rendered without needing to be included in a
|
||||
Platform spec, useful when developing a new component.
|
||||
|
||||
<Tabs groupId="render-podinfo">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
holos render component ./components/podinfo --cluster-name=default
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
cached
|
||||
rendered podinfo
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
First, the command caches the helm chart locally to speed up subsequent
|
||||
renderings. Then the command executes helm to produce the output which is
|
||||
written into the deploy directory.
|
||||
|
||||
<Tabs groupId="tree-podinfo">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
tree deploy
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
deploy
|
||||
└── clusters
|
||||
└── default
|
||||
└── components
|
||||
└── podinfo
|
||||
└── podinfo.gen.yaml
|
||||
|
||||
5 directories, 1 file
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
The component is deployed to one cluster named default. The same component is
|
||||
often deployed to multiple clusters, for example east and west for reliability.
|
||||
|
||||
:::tip
|
||||
|
||||
This example is equivalent to executing `helm template` on the chart and saving
|
||||
the output to a file. Holos simplifies this task by making it safer and more
|
||||
consistent across multiple charts.
|
||||
|
||||
:::
|
||||
|
||||
## Mix in an ArgoCD Application
|
||||
|
||||
So far we've seen how Holos is a convenient wrapper around Helm, but we haven't
|
||||
yet seen how it makes it easier to consistently and safely manage all of the
|
||||
software that goes into a platform. We'll mix in an ArgoCD
|
||||
[Application][application] resource to manage the podinfo Component with GitOps.
|
||||
We'll define this configuration in a way that is automatically and consistently
|
||||
re-used across all Components added to the Platform in the future, including
|
||||
Components which are not Helm charts.
|
||||
|
||||
Create a new file named `argocd.cue` in the root of your git repository with the
|
||||
following contents:
|
||||
|
||||
<Tabs groupId="argocd-config">
|
||||
<TabItem value="command" label="File: argocd.cue">
|
||||
```cue
|
||||
package holos
|
||||
|
||||
#ArgoConfig: {
|
||||
Enabled: true
|
||||
RepoURL: "https://example.com/holos-quickstart.git"
|
||||
}
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="note" label="Note">
|
||||
If you plan to apply the rendered output to a real cluster, change the RepoURL
|
||||
to the url of the git repository you created in this guide. It is sufficient to
|
||||
keep the example URL if you're getting a feel for Holos and inspecting the
|
||||
rendered output without applying it to a live cluster.
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
With this file in place, render the component again.
|
||||
|
||||
<Tabs groupId="render-podinfo-argocd">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
holos render component ./components/podinfo --cluster-name=default
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
wrote deploy file
|
||||
rendered gitops/podinfo
|
||||
rendered podinfo
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Holos uses the locally cached copy of the chart to render the output to improve
|
||||
performance and reliability. Then, the Helm template output is rendered along
|
||||
with an additional ArgoCD Application resource for GitOps in the
|
||||
`podinfo.application.gen.yaml` file.
|
||||
|
||||
:::tip
|
||||
|
||||
By defining the ArgoCD configuration at the root, we again take advantage of the
|
||||
fact that [order is
|
||||
irrelevant](https://cuelang.org/docs/tour/basics/order-irrelevance/) in CUE.
|
||||
|
||||
:::
|
||||
|
||||
Defining the configuration at the root causes all of the leaf Components to take
|
||||
on the ArgoCD configuration and render an Application resource for the
|
||||
Component.
|
||||
|
||||
<Tabs groupId="tree-podinfo-argocd">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
tree deploy
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
deploy
|
||||
└── clusters
|
||||
└── default
|
||||
├── components
|
||||
│ └── podinfo
|
||||
│ └── podinfo.gen.yaml
|
||||
└── gitops
|
||||
└── podinfo.application.gen.yaml
|
||||
|
||||
6 directories, 2 files
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
Note the new `podinfo.application.gen.yaml` created by enabling the ArgoCD in
|
||||
the Helm component. The Application resource in the file looks like the
|
||||
following.
|
||||
|
||||
<Tabs groupId="podinfo-application">
|
||||
<TabItem value="file" label="podinfo.application.gen.yaml">
|
||||
```yaml
|
||||
apiVersion: argoproj.io/v1alpha1
|
||||
kind: Application
|
||||
metadata:
|
||||
name: podinfo
|
||||
namespace: argocd
|
||||
spec:
|
||||
destination:
|
||||
server: https://kubernetes.default.svc
|
||||
project: default
|
||||
source:
|
||||
path: ./deploy/clusters/default/components/podinfo
|
||||
repoURL: https://example.com/holos-quickstart.git
|
||||
targetRevision: main
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
:::tip
|
||||
|
||||
Holos will generate a similar Application resource for all additional Components
|
||||
added to your Platform.
|
||||
|
||||
:::
|
||||
|
||||
Finally, add and commit the results to your platform Git repository.
|
||||
|
||||
<Tabs groupId="commit-argo">
|
||||
<TabItem value="command" label="Command">
|
||||
```bash
|
||||
git add .
|
||||
git commit -m "holos render component ./components/podinfo --cluster-name=default"
|
||||
```
|
||||
</TabItem>
|
||||
<TabItem value="output" label="Output">
|
||||
```txt
|
||||
[main f95cef1] holos render component ./components/podinfo --cluster-name=default
|
||||
3 files changed, 134 insertions(+)
|
||||
create mode 100644 argocd.cue
|
||||
create mode 100644 deploy/clusters/default/components/podinfo/podinfo.gen.yaml
|
||||
create mode 100644 deploy/clusters/default/gitops/podinfo.application.gen.yaml
|
||||
```
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
|
||||
In this section we learned how Holos provides a simple way to add an ArgoCD
|
||||
Application resource for the podinfo Component which wraps a Helm chart. Holos
|
||||
provides consistency by managing an Application resource for every Component
|
||||
added to the platform, all by defining the configuration of ArgoCD in the
|
||||
`argocd.cue` file in the root of the Git repository.
|
||||
|
||||
## Quickstart Recap {#quickstart-recap}
|
||||
|
||||
In this guide we learned how to:
|
||||
|
||||
1. Install Holos.
|
||||
2. Generate a Git repository for the Platform config.
|
||||
3. Create a Component that wraps the upstream podinfo Helm Chart without modifications.
|
||||
4. Render individual components.
|
||||
5. Mix in an ArgoCD Application resource to every Component in the Platform.
|
||||
|
||||
[application]: https://argo-cd.readthedocs.io/en/stable/user-guide/application-specification/
|
||||
|
||||
@@ -18,6 +18,14 @@ const sidebars: SidebarsConfig = {
|
||||
'comparison',
|
||||
],
|
||||
api: [
|
||||
{
|
||||
label: 'Schema',
|
||||
type: 'category',
|
||||
collapsed: false,
|
||||
items: [
|
||||
'api/schema/v1alpha3',
|
||||
],
|
||||
},
|
||||
{
|
||||
label: 'Core API',
|
||||
type: 'category',
|
||||
|
||||
@@ -75,9 +75,6 @@ func (b *buildPlanWrapper) validate() error {
|
||||
if bp.Kind != v1.BuildPlanKind {
|
||||
errs = append(errs, fmt.Sprintf("kind invalid: want: %s have: %s", v1alpha1.BuildPlanKind, bp.Kind))
|
||||
}
|
||||
if bp.APIVersion != v1.APIVersion {
|
||||
errs = append(errs, fmt.Sprintf("apiVersion invalid: want: %s have: %s", v1.APIVersion, bp.APIVersion))
|
||||
}
|
||||
if len(errs) > 0 {
|
||||
return errors.New("invalid BuildPlan: " + strings.Join(errs, ", "))
|
||||
}
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/holos-run/holos/internal/cli/command"
|
||||
"github.com/holos-run/holos/internal/client"
|
||||
"github.com/holos-run/holos/internal/errors"
|
||||
"github.com/holos-run/holos/internal/generate"
|
||||
"github.com/holos-run/holos/internal/holos"
|
||||
@@ -35,11 +34,9 @@ func NewPlatform(cfg *holos.Config) *cobra.Command {
|
||||
cmd.Args = cobra.ExactArgs(1)
|
||||
cmd.RunE = func(cmd *cobra.Command, args []string) error {
|
||||
ctx := cmd.Root().Context()
|
||||
clientContext := holos.NewClientContext(ctx)
|
||||
client := client.New(client.NewConfig(cfg))
|
||||
|
||||
for _, name := range args {
|
||||
if err := generate.GeneratePlatform(ctx, client, clientContext.OrgID, name); err != nil {
|
||||
if err := generate.GeneratePlatform(ctx, name); err != nil {
|
||||
return errors.Wrap(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,8 +131,8 @@ func makeRenderFunc[T any](log *slog.Logger, path string, cfg T) func([]byte) *b
|
||||
func GenerateComponent(ctx context.Context, kind string, name string, cfg *Schematic) error {
|
||||
// use name from args to build the source path
|
||||
path := filepath.Join(componentsRoot, kind, name)
|
||||
// use cfg.Name from flags to build the destination path
|
||||
dstPath := filepath.Join(getCwd(ctx), cfg.Name)
|
||||
// write to the current directory.
|
||||
dstPath := filepath.Join(getCwd(ctx))
|
||||
log := logger.FromContext(ctx).With("name", cfg.Name, "path", dstPath)
|
||||
log.DebugContext(ctx, "mkdir")
|
||||
if err := os.MkdirAll(dstPath, os.ModePerm); err != nil {
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package holos
|
||||
|
||||
// Produce a helm chart build plan.
|
||||
(#Helm & Chart).Output
|
||||
|
||||
let Chart = {
|
||||
Name: "{{ .Name }}"
|
||||
Version: "{{ .Version }}"
|
||||
@@ -10,6 +13,3 @@ let Chart = {
|
||||
|
||||
Values: {}
|
||||
}
|
||||
|
||||
// Produce a helm chart build plan.
|
||||
(#Helm & Chart).Output
|
||||
@@ -0,0 +1,9 @@
|
||||
package holos
|
||||
|
||||
// Manage podinfo on workload clusters only
|
||||
for Cluster in #Fleets.workload.clusters {
|
||||
#Platform: Components: "\(Cluster.name)/podinfo": {
|
||||
path: "components/podinfo"
|
||||
cluster: Cluster.name
|
||||
}
|
||||
}
|
||||
@@ -37,27 +37,9 @@ func Platforms() []string {
|
||||
return dirs
|
||||
}
|
||||
|
||||
func writePlatformMetadata(ctx context.Context, rpc *client.Client, orgID string, name string) error {
|
||||
func initPlatformMetadata(ctx context.Context, name string) error {
|
||||
log := logger.FromContext(ctx)
|
||||
|
||||
// Link the local platform the SaaS platform ID.
|
||||
rpcPlatforms, err := rpc.Platforms(ctx, orgID)
|
||||
if err != nil {
|
||||
return errors.Wrap(err)
|
||||
}
|
||||
|
||||
var rpcPlatform *platform.Platform
|
||||
for _, p := range rpcPlatforms {
|
||||
if p.GetName() == name {
|
||||
rpcPlatform = p
|
||||
break
|
||||
}
|
||||
log.DebugContext(ctx, "checking platform", "want", name, "have", p.GetName())
|
||||
}
|
||||
if rpcPlatform == nil {
|
||||
return errors.Wrap(errors.New("cannot generate: platform not found in the holos server"))
|
||||
}
|
||||
|
||||
rpcPlatform := &platform.Platform{Name: name}
|
||||
// Write the platform data.
|
||||
encoder := protojson.MarshalOptions{Indent: " "}
|
||||
data, err := encoder.Marshal(rpcPlatform)
|
||||
@@ -67,7 +49,7 @@ func writePlatformMetadata(ctx context.Context, rpc *client.Client, orgID string
|
||||
if len(data) > 0 {
|
||||
data = append(data, '\n')
|
||||
}
|
||||
log = log.With("platform_id", rpcPlatform.GetId())
|
||||
|
||||
if err := os.WriteFile(client.PlatformMetadataFile, data, 0644); err != nil {
|
||||
return errors.Wrap(fmt.Errorf("could not write platform metadata: %w", err))
|
||||
}
|
||||
@@ -78,7 +60,7 @@ func writePlatformMetadata(ctx context.Context, rpc *client.Client, orgID string
|
||||
|
||||
// GeneratePlatform writes the cue code for a platform to the local working
|
||||
// directory.
|
||||
func GeneratePlatform(ctx context.Context, rpc *client.Client, orgID string, name string) error {
|
||||
func GeneratePlatform(ctx context.Context, name string) error {
|
||||
log := logger.FromContext(ctx)
|
||||
// Check for a valid platform
|
||||
platformPath := filepath.Join(platformsRoot, name)
|
||||
@@ -90,7 +72,7 @@ func GeneratePlatform(ctx context.Context, rpc *client.Client, orgID string, nam
|
||||
log.DebugContext(ctx, fmt.Sprintf("skipped write %s: already exists", client.PlatformConfigFile))
|
||||
} else {
|
||||
if os.IsNotExist(err) {
|
||||
if err := writePlatformMetadata(ctx, rpc, orgID, name); err != nil {
|
||||
if err := initPlatformMetadata(ctx, name); err != nil {
|
||||
return errors.Wrap(err)
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -6,11 +6,6 @@ package v1alpha3
|
||||
|
||||
import "google.golang.org/protobuf/types/known/structpb"
|
||||
|
||||
#PlatformMetadata: {
|
||||
// Name represents the Platform name.
|
||||
name: string @go(Name)
|
||||
}
|
||||
|
||||
// Platform represents a platform to manage. A Platform resource informs holos
|
||||
// which components to build. The platform resource also acts as a container
|
||||
// for the platform model form values provided by the PlatformService. The
|
||||
@@ -30,13 +25,18 @@ import "google.golang.org/protobuf/types/known/structpb"
|
||||
spec: #PlatformSpec @go(Spec)
|
||||
}
|
||||
|
||||
#PlatformMetadata: {
|
||||
// Name represents the Platform name.
|
||||
name: string @go(Name)
|
||||
}
|
||||
|
||||
// PlatformSpec represents the specification of a Platform. Think of a platform
|
||||
// specification as a list of platform components to apply to a list of
|
||||
// kubernetes clusters combined with the user-specified Platform Model.
|
||||
#PlatformSpec: {
|
||||
// Model represents the platform model holos gets from from the
|
||||
// PlatformService.GetPlatform rpc method and provides to CUE using a tag.
|
||||
model: structpb.#Struct @go(Model)
|
||||
model: structpb.#Struct & {...} @go(Model)
|
||||
|
||||
// Components represents a list of holos components to manage.
|
||||
components: [...#PlatformSpecComponent] @go(Components,[]PlatformSpecComponent)
|
||||
|
||||
@@ -0,0 +1,151 @@
|
||||
// Code generated by cue get go. DO NOT EDIT.
|
||||
|
||||
//cue:generate cue get go github.com/holos-run/holos/api/schema/v1alpha3
|
||||
|
||||
// Package v1alpha3 contains CUE definitions intended as convenience wrappers
|
||||
// around the core data types defined in package core. The purpose of these
|
||||
// wrappers is to make life easier for platform engineers by reducing boiler
|
||||
// plate code and generating component build plans in a consistent manner.
|
||||
package v1alpha3
|
||||
|
||||
import (
|
||||
core "github.com/holos-run/holos/api/core/v1alpha3"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
)
|
||||
|
||||
// Helm provides a BuildPlan via the Output field which contains one HelmChart
|
||||
// from package core. Useful as a convenience wrapper to render a HelmChart
|
||||
// with optional mix-in resources and Kustomization post-processing.
|
||||
#Helm: {
|
||||
// Name represents the chart name.
|
||||
Name: string
|
||||
|
||||
// Version represents the chart version.
|
||||
Version: string
|
||||
|
||||
// Namespace represents the helm namespace option when rendering the chart.
|
||||
Namespace: string
|
||||
|
||||
// Resources are kubernetes api objects to mix into the output.
|
||||
Resources: {...} & {...} @go(,map[string]any)
|
||||
|
||||
// Repo represents the chart repository
|
||||
Repo: {
|
||||
name: string @go(Name)
|
||||
url: string @go(URL)
|
||||
} @go(,"struct{Name string \"json:\\\"name\\\"\"; URL string \"json:\\\"url\\\"\"}")
|
||||
|
||||
// Values represents data to marshal into a values.yaml for helm.
|
||||
Values: _ & {...} @go(,interface{})
|
||||
|
||||
// Chart represents the derived HelmChart for inclusion in the BuildPlan
|
||||
// Output field value. The default HelmChart field values are derived from
|
||||
// other Helm field values and should be sufficient for most use cases.
|
||||
Chart: core.#HelmChart
|
||||
|
||||
// EnableKustomizePostProcessor processes helm output with kustomize if true.
|
||||
EnableKustomizePostProcessor: bool & (true | *false)
|
||||
|
||||
// KustomizeFiles represents additional files to include in a Kustomization
|
||||
// resources list. Useful to patch helm output. The implementation is a
|
||||
// struct with filename keys and structs as values. Holos encodes the struct
|
||||
// value to yaml then writes the result to the filename key. Component
|
||||
// authors may then reference the filename in the kustomization.yaml resources
|
||||
// or patches lists.
|
||||
// Requires EnableKustomizePostProcessor: true.
|
||||
KustomizeFiles: {...} & {[string]: {...}} @go(,map[string]any)
|
||||
|
||||
// KustomizePatches represents patches to apply to the helm output. Requires
|
||||
// EnableKustomizePostProcessor: true.
|
||||
KustomizePatches: {...} & {[string]: {...}} @go(,map[core.InternalLabel]any)
|
||||
|
||||
// KustomizeResources represents additional resources files to include in the
|
||||
// kustomize resources list.
|
||||
KustomizeResources: {...} & {[string]: {...}} @go(,map[string]any)
|
||||
|
||||
// ArgoConfig represents the ArgoCD GitOps configuration for this Component.
|
||||
ArgoConfig: #ArgoConfig
|
||||
|
||||
// Output represents the derived BuildPlan for the Holos cli to render.
|
||||
Output: core.#BuildPlan
|
||||
}
|
||||
|
||||
// ArgoConfig represents the ArgoCD GitOps configuration for a Component.
|
||||
// Useful to define once at the root of the Platform configuration and reuse
|
||||
// across all Components.
|
||||
#ArgoConfig: {
|
||||
// Enabled causes holos to render an ArgoCD Application resource for GitOps if true.
|
||||
Enabled: bool & (true | *false)
|
||||
|
||||
// ClusterName represents the cluster within the platform the Application
|
||||
// resource is intended for.
|
||||
ClusterName: string
|
||||
|
||||
// DeployRoot represents the path from the git repository root to the `deploy`
|
||||
// rendering output directory. Used as a prefix for the
|
||||
// Application.spec.source.path field.
|
||||
DeployRoot: string & (string | *".")
|
||||
|
||||
// RepoURL represents the value passed to the Application.spec.source.repoURL
|
||||
// field.
|
||||
RepoURL: string
|
||||
|
||||
// TargetRevision represents the value passed to the
|
||||
// Application.spec.source.targetRevision field. Defaults to the branch named
|
||||
// main.
|
||||
TargetRevision: string & (string | *"main")
|
||||
}
|
||||
|
||||
// Cluster represents a cluster managed by the Platform.
|
||||
#Cluster: {
|
||||
// Name represents the cluster name, for example "east1", "west1", or
|
||||
// "management".
|
||||
name: string @go(Name)
|
||||
|
||||
// Primary represents if the cluster is marked as the primary among a set of
|
||||
// candidate clusters. Useful for promotion of database leaders.
|
||||
primary: bool & (true | *false) @go(Primary)
|
||||
}
|
||||
|
||||
// Fleet represents a named collection of similarly configured Clusters. Useful
|
||||
// to segregate workload clusters from their management cluster.
|
||||
#Fleet: {
|
||||
name: string @go(Name)
|
||||
|
||||
// Clusters represents a mapping of Clusters by their name.
|
||||
clusters: {[string]: #Cluster} & {[Name=_]: name: Name} @go(Clusters,map[string]Cluster)
|
||||
}
|
||||
|
||||
// StandardFleets represents the standard set of Clusters in a Platform
|
||||
// segmented into Fleets by their purpose. The management Fleet contains a
|
||||
// single Cluster, for example a GKE autopilot cluster with no workloads
|
||||
// deployed for reliability and cost efficiency. The workload Fleet contains
|
||||
// all other Clusters which contain workloads and sync Secrets from the
|
||||
// management cluster.
|
||||
#StandardFleets: {
|
||||
// Workload represents a Fleet of zero or more workload Clusters.
|
||||
workload: #Fleet & {name: "workload"} @go(Workload)
|
||||
|
||||
// Management represents a Fleet with one Cluster named management.
|
||||
management: #Fleet & {name: "management", clusters: management: _} @go(Management)
|
||||
}
|
||||
|
||||
// Platform is a convenience structure to produce a core Platform specification
|
||||
// value in the Output field. Useful to collect components at the root of the
|
||||
// Platform configuration tree as a struct, which are automatically converted
|
||||
// into a list for the core Platform spec output.
|
||||
#Platform: {
|
||||
// Name represents the Platform name.
|
||||
Name: string & (string | *"holos")
|
||||
|
||||
// Components is a structured map of components to manage by their name.
|
||||
Components: {[string]: core.#PlatformSpecComponent} @go(,map[string]core.PlatformSpecComponent)
|
||||
|
||||
// Model represents the Platform model holos gets from from the
|
||||
// PlatformService.GetPlatform rpc method and provides to CUE using a tag.
|
||||
Model: structpb.#Struct & {...}
|
||||
|
||||
// Output represents the core Platform spec for the holos cli to iterate over
|
||||
// and render each listed Component, injecting the Model.
|
||||
Output: core.#Platform
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
package v1alpha3
|
||||
|
||||
import (
|
||||
"encoding/yaml"
|
||||
core "github.com/holos-run/holos/api/core/v1alpha3"
|
||||
kc "sigs.k8s.io/kustomize/api/types"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
batchv1 "k8s.io/api/batch/v1"
|
||||
|
||||
app "argoproj.io/application/v1alpha1"
|
||||
)
|
||||
|
||||
#Resources: {
|
||||
[Kind=string]: [InternalLabel=string]: {
|
||||
kind: Kind
|
||||
metadata: name: string | *InternalLabel
|
||||
}
|
||||
|
||||
ClusterRole: [_]: rbacv1.#ClusterRole
|
||||
ClusterRoleBinding: [_]: rbacv1.#ClusterRoleBinding
|
||||
ConfigMap: [_]: corev1.#ConfigMap
|
||||
CronJob: [_]: batchv1.#CronJob
|
||||
Deployment: [_]: appsv1.#Deployment
|
||||
Job: [_]: batchv1.#Job
|
||||
Namespace: [_]: corev1.#Namespace
|
||||
Role: [_]: rbacv1.#Role
|
||||
RoleBinding: [_]: rbacv1.#RoleBinding
|
||||
Service: [_]: corev1.#Service
|
||||
ServiceAccount: [_]: corev1.#ServiceAccount
|
||||
StatefulSet: [_]: appsv1.#StatefulSet
|
||||
...
|
||||
}
|
||||
|
||||
#Helm: {
|
||||
Name: string
|
||||
Version: string
|
||||
Namespace: string
|
||||
Resources: #Resources
|
||||
|
||||
Repo: {
|
||||
name: string | *""
|
||||
url: string | *""
|
||||
}
|
||||
|
||||
Values: {...}
|
||||
|
||||
Chart: core.#HelmChart & {
|
||||
metadata: name: string | *Name
|
||||
metadata: namespace: string | *Namespace
|
||||
chart: name: string | *Name
|
||||
chart: release: chart.name
|
||||
chart: version: string | *Version
|
||||
chart: repository: Repo
|
||||
|
||||
// Render the values to yaml for holos to provide to helm.
|
||||
valuesContent: yaml.Marshal(Values)
|
||||
|
||||
// Kustomize post-processor
|
||||
if EnableKustomizePostProcessor == true {
|
||||
// resourcesFile represents the file helm output is written two and
|
||||
// kustomize reads from. Typically "resources.yaml" but referenced as a
|
||||
// constant to ensure the holos cli uses the same file.
|
||||
kustomize: resourcesFile: core.#ResourcesFile
|
||||
// kustomizeFiles represents the files in a kustomize directory tree.
|
||||
kustomize: kustomizeFiles: core.#FileContentMap
|
||||
for FileName, Object in KustomizeFiles {
|
||||
kustomize: kustomizeFiles: "\(FileName)": yaml.Marshal(Object)
|
||||
}
|
||||
}
|
||||
|
||||
apiObjectMap: (#APIObjects & {apiObjects: Resources}).apiObjectMap
|
||||
}
|
||||
|
||||
// EnableKustomizePostProcessor processes helm output with kustomize if true.
|
||||
EnableKustomizePostProcessor: true | *false
|
||||
// KustomizeFiles represents additional files to include in a Kustomization
|
||||
// resources list. Useful to patch helm output. The implementation is a
|
||||
// struct with filename keys and structs as values. Holos encodes the struct
|
||||
// value to yaml then writes the result to the filename key. Component
|
||||
// authors may then reference the filename in the kustomization.yaml resources
|
||||
// or patches lists.
|
||||
// Requires EnableKustomizePostProcessor: true.
|
||||
KustomizeFiles: {
|
||||
// Embed KustomizeResources
|
||||
KustomizeResources
|
||||
|
||||
// The kustomization.yaml file must be included for kustomize to work.
|
||||
"kustomization.yaml": kc.#Kustomization & {
|
||||
apiVersion: "kustomize.config.k8s.io/v1beta1"
|
||||
kind: "Kustomization"
|
||||
resources: [core.#ResourcesFile, for FileName, _ in KustomizeResources {FileName}]
|
||||
patches: [for x in KustomizePatches {x}]
|
||||
}
|
||||
}
|
||||
// KustomizePatches represents patches to apply to the helm output. Requires
|
||||
// EnableKustomizePostProcessor: true.
|
||||
KustomizePatches: [ArbitraryLabel=string]: kc.#Patch
|
||||
// KustomizeResources represents additional resources files to include in the
|
||||
// kustomize resources list.
|
||||
KustomizeResources: [FileName=string]: {...}
|
||||
|
||||
// ArgoConfig represents the ArgoCD GitOps integration for this Component.
|
||||
ArgoConfig: _
|
||||
|
||||
// output represents the build plan provided to the holos cli.
|
||||
Output: #BuildPlan & {
|
||||
_Name: Name
|
||||
_Namespace: Namespace
|
||||
_ArgoConfig: ArgoConfig
|
||||
spec: components: helmChartList: [Chart]
|
||||
}
|
||||
}
|
||||
|
||||
#BuildPlan: core.#BuildPlan & {
|
||||
_Name: string
|
||||
_Namespace?: string
|
||||
_ArgoConfig: #ArgoConfig
|
||||
|
||||
if _ArgoConfig.Enabled {
|
||||
let NAME = "gitops/\(_Name)"
|
||||
|
||||
// Render the ArgoCD Application for GitOps as an additional Component of
|
||||
// the BuildPlan.
|
||||
spec: components: resources: (NAME): {
|
||||
metadata: name: NAME
|
||||
if _Namespace != _|_ {
|
||||
metadata: namespace: _Namespace
|
||||
}
|
||||
|
||||
deployFiles: (#Argo & {ComponentName: _Name, ArgoConfig: _ArgoConfig}).deployFiles
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// #Argo represents an argocd Application resource for each component, written
|
||||
// using the #HolosComponent.deployFiles field.
|
||||
#Argo: {
|
||||
ComponentName: string
|
||||
ArgoConfig: #ArgoConfig
|
||||
|
||||
Application: app.#Application & {
|
||||
metadata: name: ComponentName
|
||||
metadata: namespace: "argocd"
|
||||
spec: {
|
||||
destination: server: "https://kubernetes.default.svc"
|
||||
project: "default"
|
||||
source: {
|
||||
path: "\(ArgoConfig.DeployRoot)/deploy/clusters/\(ArgoConfig.ClusterName)/components/\(ComponentName)"
|
||||
repoURL: ArgoConfig.RepoURL
|
||||
targetRevision: ArgoConfig.TargetRevision
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// deployFiles represents the output files to write along side the component.
|
||||
deployFiles: "clusters/\(ArgoConfig.ClusterName)/gitops/\(ComponentName).application.gen.yaml": yaml.Marshal(Application)
|
||||
}
|
||||
|
||||
// #ArgoDefaultSyncPolicy represents the default argo sync policy.
|
||||
#ArgoDefaultSyncPolicy: {
|
||||
automated: {
|
||||
prune: bool | *true
|
||||
selfHeal: bool | *true
|
||||
}
|
||||
syncOptions: [
|
||||
"RespectIgnoreDifferences=true",
|
||||
"ServerSideApply=true",
|
||||
]
|
||||
retry: limit: number | *2
|
||||
retry: backoff: {
|
||||
duration: string | *"5s"
|
||||
factor: number | *2
|
||||
maxDuration: string | *"3m0s"
|
||||
}
|
||||
}
|
||||
|
||||
// #APIObjects defines the output format for kubernetes api objects. The holos
|
||||
// cli expects the yaml representation of each api object in the apiObjectMap
|
||||
// field.
|
||||
#APIObjects: core.#APIObjects & {
|
||||
// apiObjects represents the un-marshalled form of each kubernetes api object
|
||||
// managed by a holos component.
|
||||
apiObjects: {
|
||||
[Kind=string]: {
|
||||
[string]: {
|
||||
kind: Kind
|
||||
...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// apiObjectMap holds the marshalled representation of apiObjects
|
||||
for kind, v in apiObjects {
|
||||
for name, obj in v {
|
||||
apiObjectMap: (kind): (name): yaml.Marshal(obj)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Platform: {
|
||||
Name: _
|
||||
Model: _
|
||||
Components: [string]: _
|
||||
Output: metadata: name: Name
|
||||
Output: spec: model: Model
|
||||
Output: spec: components: [for c in Components {c}]
|
||||
}
|
||||
@@ -9,6 +9,9 @@ package platforms
|
||||
//go generate rm -rf cue.mod/gen/github.com/holos-run/holos/api/meta
|
||||
//go:generate cue get go github.com/holos-run/holos/api/meta/...
|
||||
|
||||
//go generate rm -rf cue.mod/gen/github.com/holos-run/holos/api/schema
|
||||
//go:generate cue get go github.com/holos-run/holos/api/schema/...
|
||||
|
||||
//go generate rm -rf cue.mod/gen/github.com/holos-run/holos/service/gen/holos/object
|
||||
//go:generate cue import ../../../service/holos/object/v1alpha1/object.proto -o cue.mod/gen/github.com/holos-run/holos/service/gen/holos/object/v1alpha1/object.proto_gen.cue -I ../../../proto -f
|
||||
//go:generate rm -f cue.mod/gen/github.com/holos-run/holos/service/gen/holos/object/v1alpha1/object.pb_go_gen.cue
|
||||
|
||||
8
internal/generate/platforms/quickstart/.gitignore
vendored
Normal file
8
internal/generate/platforms/quickstart/.gitignore
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
vendor/
|
||||
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -0,0 +1,3 @@
|
||||
package holos
|
||||
|
||||
#Platform.Output
|
||||
@@ -0,0 +1,3 @@
|
||||
package holos
|
||||
|
||||
#Platform: Name: "quickstart"
|
||||
5
internal/generate/platforms/quickstart/readme.md
Normal file
5
internal/generate/platforms/quickstart/readme.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Holos Quickstart
|
||||
|
||||
Generated from the [Holos Quickstart][quickstart] guide.
|
||||
|
||||
[quickstart]: https://holos.run/docs/quickstart/
|
||||
15
internal/generate/platforms/quickstart/schema.gen.cue
Normal file
15
internal/generate/platforms/quickstart/schema.gen.cue
Normal file
@@ -0,0 +1,15 @@
|
||||
package holos
|
||||
|
||||
import schema "github.com/holos-run/holos/api/schema/v1alpha3"
|
||||
|
||||
#Helm: schema.#Helm & {
|
||||
ArgoConfig: #ArgoConfig
|
||||
}
|
||||
|
||||
#ArgoConfig: schema.#ArgoConfig & {
|
||||
ClusterName: _ClusterName
|
||||
}
|
||||
|
||||
#Fleets: schema.#StandardFleets
|
||||
|
||||
#Platform: schema.#Platform
|
||||
14
internal/generate/platforms/quickstart/tags.gen.cue
Normal file
14
internal/generate/platforms/quickstart/tags.gen.cue
Normal file
@@ -0,0 +1,14 @@
|
||||
package holos
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
dto "github.com/holos-run/holos/service/gen/holos/object/v1alpha1:object"
|
||||
)
|
||||
|
||||
// _ClusterName is the --cluster-name flag value provided by the holos cli.
|
||||
_ClusterName: string @tag(cluster, type=string)
|
||||
|
||||
// _PlatformConfig represents all of the data passed from holos to cue, used to
|
||||
// carry the platform and project models.
|
||||
_PlatformConfig: dto.#PlatformConfig & json.Unmarshal(_PlatformConfigJSON)
|
||||
_PlatformConfigJSON: string | *"{}" @tag(platform_config, type=string)
|
||||
@@ -1 +1 @@
|
||||
0
|
||||
2
|
||||
|
||||
Reference in New Issue
Block a user