Skip to content

Commit

Permalink
api: establish core v1alpha3 for quickstart
Browse files Browse the repository at this point in the history
Switch holos to use v1alpha3 so we can establish more of the CUE
structures in the documented API using Go structs.
  • Loading branch information
jeffmccune committed Sep 6, 2024
1 parent f3a1aea commit e3c3ab6
Show file tree
Hide file tree
Showing 31 changed files with 1,117 additions and 38 deletions.
2 changes: 2 additions & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
"clusterissuer",
"cookiesecret",
"coredns",
"CRD's",
"crds",
"creds",
"crossplane",
Expand Down Expand Up @@ -92,6 +93,7 @@
"Traceid",
"traefik",
"uibutton",
"untar",
"Upsert",
"urandom",
"usecases",
Expand Down
47 changes: 47 additions & 0 deletions api/core/v1alpha3/apiobjects.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package v1alpha3

import "google.golang.org/protobuf/types/known/structpb"

// InternalLabel is an arbitrary unique identifier internal to holos itself.
// The holos cli is expected to never write a InternalLabel value to rendered
// output files, therefore use a [InternalLabel] when the identifier must be
// unique and internal. Defined as a type for clarity and type checking.
//
// A InternalLabel is useful to convert a CUE struct to a list, for example
// producing a list of [APIObject] resources from an [APIObjectMap]. A CUE
// struct using InternalLabel keys is guaranteed to not lose data when rendering
// output because a InternalLabel is expected to never be written to the final
// output.
type InternalLabel string

// Kind is a kubernetes api object kind. Defined as a type for clarity and type
// checking.
type Kind string

// APIObject represents the most basic generic form of a single kubernetes api
// object. Represented as a JSON object internally for compatibility between
// tools, for example loading from CUE.
type APIObject structpb.Struct

// APIObjectMap represents the marshalled yaml representation of kubernetes api
// objects. Do not produce an APIObjectMap directly, instead use [APIObjects]
// to produce the marshalled yaml representation from CUE data, then provide the
// result to [Component].
type APIObjectMap map[Kind]map[InternalLabel]string

// APIObjects represents Kubernetes API objects defined directly from CUE code.
// Useful to mix in resources to any kind of [Component], for example
// adding an ExternalSecret resource to a [HelmChart].
//
// [Kind] must be the resource kind, e.g. Deployment or Service.
//
// [InternalLabel] is an arbitrary internal identifier to uniquely identify the resource
// within the context of a `holos` command. Holos will never write the
// intermediate label to rendered output.
//
// Refer to [Component] which accepts an [APIObjectMap] field provided by
// [APIObjects].
type APIObjects struct {
APIObjects map[Kind]map[InternalLabel]APIObject `json:"apiObjects"`
APIObjectMap APIObjectMap `json:"apiObjectMap"`
}
52 changes: 52 additions & 0 deletions api/core/v1alpha3/buildplan.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package v1alpha3

// FilePath represents a file path.
type FilePath string

// FileContent represents file contents.
type FileContent string

// FileContentMap represents a mapping of file paths to file contents.
type FileContentMap map[FilePath]FileContent

// BuildPlan represents a build plan for the holos cli to execute. The purpose
// of a BuildPlan is to define one or more [Component] kinds. For example a
// [HelmChart], [KustomizeBuild], or [KubernetesObjects].
//
// A BuildPlan usually has an additional empty [KubernetesObjects] for the
// purpose of using the [Component] DeployFiles field to deploy an ArgoCD
// or Flux gitops resource for the holos component.
type BuildPlan struct {
Kind string `json:"kind" cue:"\"BuildPlan\""`
APIVersion string `json:"apiVersion" cue:"string | *\"v1alpha3\""`
Spec BuildPlanSpec `json:"spec"`
}

// BuildPlanSpec represents the specification of the build plan.
type BuildPlanSpec struct {
// Disabled causes the holos cli to take no action over the [BuildPlan].
Disabled bool `json:"disabled,omitempty"`
// Components represents multiple [HolosComponent] kinds to manage.
Components BuildPlanComponents `json:"components,omitempty"`
}

type BuildPlanComponents struct {
Resources map[InternalLabel]KubernetesObjects `json:"resources,omitempty"`
KubernetesObjectsList []KubernetesObjects `json:"kubernetesObjectsList,omitempty"`
HelmChartList []HelmChart `json:"helmChartList,omitempty"`
KustomizeBuildList []KustomizeBuild `json:"kustomizeBuildList,omitempty"`
}

// Kustomize represents resources necessary to execute a kustomize build.
// Intended for at least two use cases:
//
// 1. Process a [KustomizeBuild] [Component] which represents raw yaml
// file resources in a holos component directory.
// 2. Post process a [HelmChart] [Component] to inject istio, patch jobs,
// add custom labels, etc...
type Kustomize struct {
// KustomizeFiles holds file contents for kustomize, e.g. patch files.
KustomizeFiles FileContentMap `json:"kustomizeFiles,omitempty"`
// ResourcesFile is the file name used for api objects in kustomization.yaml
ResourcesFile string `json:"resourcesFile,omitempty"`
}
43 changes: 43 additions & 0 deletions api/core/v1alpha3/component.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package v1alpha3

// Component defines the fields common to all holos component kinds. Every
// holos component kind should embed Component.
type Component struct {
// Kind is a string value representing the resource this object represents.
Kind string `json:"kind"`
// APIVersion represents the versioned schema of this representation of an object.
APIVersion string `json:"apiVersion" cue:"\"v1alpha3\""`
// Metadata represents data about the holos component such as the Name.
Metadata Metadata `json:"metadata"`

// APIObjectMap holds the marshalled representation of api objects. Useful to
// mix in resources to each Component type, for example adding an
// ExternalSecret to a [HelmChart] Component. Refer to [APIObjects].
APIObjectMap APIObjectMap `json:"apiObjectMap,omitempty"`

// DeployFiles represents file paths relative to the cluster deploy directory
// with the value representing the file content. Intended for defining the
// ArgoCD Application resource or Flux Kustomization resource from within CUE,
// but may be used to render any file related to the build plan from CUE.
DeployFiles FileContentMap `json:"deployFiles,omitempty"`

// Kustomize represents a kubectl kustomize build post-processing step.
Kustomize `json:"kustomize,omitempty"`

// Skip causes holos to take no action regarding this component.
Skip bool `json:"skip" cue:"bool | *false"`
}

// Metadata represents data about the object such as the Name.
type Metadata struct {
// Name represents the name of the holos component.
Name string `json:"name"`
// Namespace is the primary namespace of the holos component. A holos
// component may manage resources in multiple namespaces, in this case
// consider setting the component namespace to default.
//
// This field is optional because not all resources require a namespace,
// particularly CRDs and DeployFiles functionality.
// +optional
Namespace string `json:"namespace,omitempty"`
}
11 changes: 11 additions & 0 deletions api/core/v1alpha3/constants.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package v1alpha3

const (
APIVersion = "v1alpha3"
BuildPlanKind = "BuildPlan"
HelmChartKind = "HelmChart"
// ChartDir is the directory name created in the holos component directory to cache a chart.
ChartDir = "vendor"
// ResourcesFile is the file name used to store component output when post-processing with kustomize.
ResourcesFile = "resources.yaml"
)
26 changes: 26 additions & 0 deletions api/core/v1alpha3/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// Package v1alpha3 contains the core API contract between the holos cli and CUE
// configuration code. Platform designers, operators, and software developers
// use this API to write configuration in CUE which `holos` loads. The overall
// shape of the API defines imperative actions `holos` should carry out to
// render the complete yaml that represents a Platform.
//
// [Platform] defines the complete configuration of a platform. With the holos
// reference platform this takes the shape of one management cluster and at
// least two workload cluster. Each cluster has multiple [Component]
// resources applied to it.
//
// Each holos component path, e.g. `components/namespaces` produces exactly one
// [BuildPlan] which in turn contains a set of [Component] kinds.
//
// The primary kinds of [Component] are:
//
// 1. [HelmChart] to render config from a helm chart.
// 2. [KustomizeBuild] to render config from [Kustomize]
// 3. [KubernetesObjects] to render [APIObjects] defined directly in CUE
// configuration.
//
// Note that Holos operates as a data pipeline, so the output of a [HelmChart]
// may be provided to [Kustomize] for post-processing.
package v1alpha3

//go:generate ../../../hack/gendoc
38 changes: 38 additions & 0 deletions api/core/v1alpha3/helm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package v1alpha3

// HelmChart represents a holos component which wraps around an upstream helm
// chart. Holos orchestrates helm by providing values obtained from CUE,
// renders the output using `helm template`, then post-processes the helm output
// yaml using the general functionality provided by [Component], for
// example [Kustomize] post-rendering and mixing in additional kubernetes api
// objects.
type HelmChart struct {
Component `json:",inline"`
Kind string `json:"kind" cue:"\"HelmChart\""`

// Chart represents a helm chart to manage.
Chart Chart `json:"chart"`
// ValuesContent represents the values.yaml file holos passes to the `helm
// template` command.
ValuesContent string `json:"valuesContent"`
// EnableHooks enables helm hooks when executing the `helm template` command.
EnableHooks bool `json:"enableHooks" cue:"bool | *false"`
}

// Chart represents a helm chart.
type Chart struct {
// Name represents the chart name.
Name string `json:"name"`
// Version represents the chart version.
Version string `json:"version"`
// Release represents the chart release when executing helm template.
Release string `json:"release"`
// Repository represents the repository to fetch the chart from.
Repository Repository `json:"repository,omitempty"`
}

// Repository represents a helm chart repository.
type Repository struct {
Name string `json:"name"`
URL string `json:"url"`
}
10 changes: 10 additions & 0 deletions api/core/v1alpha3/kubernetesobjects.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package v1alpha3

const KubernetesObjectsKind = "KubernetesObjects"

// KubernetesObjects represents a [Component] composed of Kubernetes API
// objects provided directly from CUE using [APIObjects].
type KubernetesObjects struct {
Component `json:",inline"`
Kind string `json:"kind" cue:"\"KubernetesObjects\""`
}
8 changes: 8 additions & 0 deletions api/core/v1alpha3/kustomizebuild.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package v1alpha3

// KustomizeBuild represents a [Component] that renders plain yaml files in
// the holos component directory using `kubectl kustomize build`.
type KustomizeBuild struct {
Component `json:",inline"`
Kind string `json:"kind" cue:"\"KustomizeBuild\""`
}
44 changes: 44 additions & 0 deletions api/core/v1alpha3/platform.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
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
// primary use case is to collect the cluster names, cluster types, platform
// model, and holos components to build into one resource.
type Platform struct {
// Kind is a string value representing the resource this object represents.
Kind string `json:"kind" cue:"\"Platform\""`
// APIVersion represents the versioned schema of this representation of an object.
APIVersion string `json:"apiVersion" cue:"string | *\"v1alpha3\""`
// Metadata represents data about the object such as the Name.
Metadata PlatformMetadata `json:"metadata"`

// Spec represents the specification.
Spec PlatformSpec `json:"spec"`
}

// 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"`
// Components represents a list of holos components to manage.
Components []PlatformSpecComponent `json:"components"`
}

// PlatformSpecComponent represents a holos component to build or render.
type PlatformSpecComponent struct {
// Path is the path of the component relative to the platform root.
Path string `json:"path"`
// Cluster is the cluster name to provide when rendering the component.
Cluster string `json:"cluster"`
}
Loading

0 comments on commit e3c3ab6

Please sign in to comment.