v2controllers

package
v0.0.25 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 15, 2022 License: BSD-3-Clause Imports: 11 Imported by: 0

README

Readable, Creatable, Editable?

ModelController requires three types to work with a model type:

  • Readable, the set of all fields visible through the API
  • Creatable, the set of all fields that can be set upon creation through the API
  • Editable, the set of all fields that can be mutated through the API

Go's struct nesting means we can have the Readable contain the Creatable type, and the Creatable contain the Editable type. For naming, for a model type called v2models.X, the three types would be X, CreatableX, and EditableX. These types will be picked up by Swaggo and Gin.

Wow, what a lot of struct tags:

Do use:

  • json controls the field name when parsing to/from json (always add)
  • form controls the field name when parsing from query parameters (always add)
  • swaggertype can override the type of the field documented on Swagger, useful for anything recursive (only add when Swaggo is parsing the type incorrectly)
  • enums controls possible values for the field as documented on Swagger (add when reasonable)
  • default controls (add when reasonable):
    • default values for the field on Swagger (as in, Swagger will fill in the default for you)
    • default values applied internally by Sherlock when it goes to create an entry

I suggest tags be in the order above. Swaggo and Gin both use the tags on these structs.

Don't use

  • validate:"required" which will document fields as required on Swagger, but in an over-zealous way that interferes with omitting them in query parameters on list calls

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AppVersion

type AppVersion struct {
	ReadableBaseType
	ChartInfo Chart `json:"chartInfo" form:"chartInfo"`
	CreatableAppVersion
}

type Chart

type Chart struct {
	ReadableBaseType
	CreatableChart
}

type ChartDeployRecord

type ChartDeployRecord struct {
	ReadableBaseType
	ChartReleaseInfo ChartRelease `json:"chartReleaseInfo" form:"chartReleaseInfo"`
	CreatableChartDeployRecord
}

type ChartRelease

type ChartRelease struct {
	ReadableBaseType
	ChartInfo       Chart        `json:"chartInfo" form:"chartInfo"`
	ClusterInfo     *Cluster     `json:"clusterInfo,omitempty" form:"clusterInfo"`
	EnvironmentInfo *Environment `json:"environmentInfo,omitempty" form:"environmentInfo"`
	DestinationType string       `json:"destinationType" form:"destinationType" enum:"environment,cluster"` // Calculated field
	CreatableChartRelease
}

type ChartVersion

type ChartVersion struct {
	ReadableBaseType
	ChartInfo Chart `json:"chartInfo" form:"chartInfo"`
	CreatableChartVersion
}

type Cluster

type Cluster struct {
	ReadableBaseType
	CreatableCluster
}

Cluster @description The full set of Cluster fields that can be read or used for filtering queries

type ControllerSet

type ControllerSet struct {
	ClusterController           *ClusterController
	EnvironmentController       *EnvironmentController
	ChartController             *ChartController
	ChartVersionController      *ChartVersionController
	AppVersionController        *AppVersionController
	ChartReleaseController      *ChartReleaseController
	ChartDeployRecordController *ChartDeployRecordController
}

func NewControllerSet

func NewControllerSet(stores *v2models.StoreSet) *ControllerSet

type Creatable

type Creatable[R Readable] interface {
	// contains filtered or unexported methods
}

Creatable represents the set of fields that can be set upon creation by a user. The fields available on a Creatable are a subset of those available on a Readable. Generally, a Creatable will embed an Editable, since all fields that can be edited can be set upon creation.

type CreatableAppVersion

type CreatableAppVersion struct {
	Chart      string `json:"chart" form:"chart"`           // Required when creating
	AppVersion string `json:"appVersion" form:"appVersion"` // Required when creating
	GitCommit  string `json:"gitCommit" form:"gitCommit"`
	GitBranch  string `json:"gitBranch" form:"gitBranch"`
	EditableAppVersion
}

type CreatableChart

type CreatableChart struct {
	Name string `json:"name" form:"name"` // Required when creating
	EditableChart
}

type CreatableChartDeployRecord

type CreatableChartDeployRecord struct {
	ChartRelease      string `json:"chartRelease" form:"chartRelease"`           // Required when creating
	ExactChartVersion string `json:"exactChartVersion" form:"exactChartVersion"` // When creating, will default to the value currently held by the chart release
	ExactAppVersion   string `json:"exactAppVersion" form:"exactAppVersion"`     // When creating, will default to the value currently held by the chart release
	HelmfileRef       string `json:"helmfileRef" form:"helmfileRef"`             // When creating, will default to the value currently held by the chart release
	EditableChartDeployRecord
}

type CreatableChartRelease

type CreatableChartRelease struct {
	Chart       string `json:"chart" form:"chart"`             // Required when creating
	Cluster     string `json:"cluster" form:"cluster"`         // When creating, will default the environment's default cluster, if provided. Either this or environment must be provided.
	Environment string `json:"environment" form:"environment"` // Either this or cluster must be provided.
	Name        string `json:"name" form:"name"`               // When creating, will be calculated if left empty
	Namespace   string `json:"namespace" form:"namespace"`     // When creating, will default to the environment's default namespace, if provided
	EditableChartRelease
}

type CreatableChartVersion

type CreatableChartVersion struct {
	Chart        string `json:"chart" form:"chart"`               // Required when creating
	ChartVersion string `json:"chartVersion" form:"chartVersion"` // Required when creating
	EditableChartVersion
}

type CreatableCluster

type CreatableCluster struct {
	Name              string `json:"name" validate:"required" form:"name"` // Required when creating
	Provider          string `json:"provider" form:"provider" enums:"google,azure" default:"google"`
	GoogleProject     string `json:"googleProject" form:"googleProject"`         // Required when creating if provider is 'google'
	AzureSubscription string `json:"azureSubscription" form:"azureSubscription"` // Required when creating if providers is 'azure'
	EditableCluster
}

CreatableCluster @description The subset of Cluster fields that can be set upon creation

type CreatableEnvironment

type CreatableEnvironment struct {
	Base                      string `json:"base" form:"base"`                                                          // Required when creating
	ChartReleasesFromTemplate *bool  `json:"chartReleasesFromTemplate" form:"chartReleasesFromTemplate" default:"true"` // Upon creation of a dynamic environment, if this is true the template's chart releases will be copied to the new environment
	Lifecycle                 string `json:"lifecycle" form:"lifecycle" default:"dynamic"`
	Name                      string `json:"name" form:"name"`                               // When creating, will be calculated if dynamic, required otherwise
	TemplateEnvironment       string `json:"templateEnvironment" form:"templateEnvironment"` // Required for dynamic environments
	EditableEnvironment
}

type Editable

type Editable[R Readable, C Creatable[R]] interface {
	// contains filtered or unexported methods
}

Editable represents the set of fields that can be mutated by a user. The fields available on an Editable are a subset of those available on a Creatable.

type EditableAppVersion

type EditableAppVersion struct{}

type EditableChart

type EditableChart struct {
	ChartRepo             *string `json:"chartRepo" form:"chartRepo" default:"terra-helm"`
	AppImageGitRepo       *string `json:"appImageGitRepo" form:"appImageGitRepo"`
	AppImageGitMainBranch *string `json:"appImageGitMainBranch" form:"appImageGitMainBranch"`
}

type EditableChartDeployRecord

type EditableChartDeployRecord struct{}

type EditableChartRelease

type EditableChartRelease struct {
	CurrentAppVersionExact   *string `json:"currentAppVersionExact" form:"currentAppVersionExact"`
	CurrentChartVersionExact *string `json:"currentChartVersionExact" form:"currentChartVersionExact"`
	HelmfileRef              *string `json:"helmfileRef" form:"helmfileRef" default:"HEAD"`
	TargetAppVersionBranch   *string `json:"targetAppVersionBranch" form:"targetAppVersionBranch"` // When creating, will default to the app's main branch if it has one recorded
	TargetAppVersionCommit   *string `json:"targetAppVersionCommit" form:"targetAppVersionCommit"`
	TargetAppVersionExact    *string `json:"targetAppVersionExact" form:"targetAppVersionExact"`
	TargetAppVersionUse      *string `json:"targetAppVersionUse" form:"targetAppVersionUse" enums:"branch,commit,exact"` // When creating, will default to referencing any provided target app version field (exact, then commit, then branch)
	TargetChartVersionExact  *string `json:"targetChartVersionExact" form:"targetChartVersionExact"`
	TargetChartVersionUse    *string `json:"targetChartVersionUse" form:"targetChartVersionUse" enums:"latest,exact"` // When creating, will default to latest unless an exact target chart version is provided
	ThelmaMode               *string `json:"thelmaMode,omitempty" form:"thelmaMode"`
}

EditableChartRelease There's indeed some grouped fields here. Trying to nest them in an object or something will quickly make Swaggo upset. There's four things to worry about: Gin's json parsing, Swaggo's json tag parsing, Gin's form parsing for query params, and Swaggo's apparent parsing of json tags (instead of form ones) for query params. The query param part only shows up on the list method; all the times Jack tried to add nesting, something broke. https://broadinstitute.slack.com/archives/CQ6SL4N5T/p1660059822037769

type EditableChartVersion

type EditableChartVersion struct{}

type EditableCluster

type EditableCluster struct {
	Base                *string `json:"base"  form:"base"`      // Required when creating
	Address             *string `json:"address" form:"address"` // Required when creating
	RequiresSuitability *bool   `json:"requiresSuitability" form:"requiresSuitability" default:"false"`
}

EditableCluster @description The subset of Cluster fields that can be edited after creation

type EditableEnvironment

type EditableEnvironment struct {
	DefaultCluster      *string `json:"defaultCluster" form:"defaultCluster"`
	DefaultNamespace    *string `json:"defaultNamespace" form:"defaultNamespace"`
	Owner               *string `json:"owner" form:"owner"` // When creating, will be set to your email
	RequiresSuitability *bool   `json:"requiresSuitability" default:"false" form:"requiresSuitability"`
}

type Environment

type Environment struct {
	ReadableBaseType
	TemplateEnvironmentInfo *Environment `json:"templateEnvironmentInfo,omitempty" swaggertype:"object" form:"templateEnvironmentInfo"` // Single-layer recursive; provides info of the template environment if this environment has one
	DefaultClusterInfo      *Cluster     `json:"defaultClusterInfo,omitempty" form:"defaultClusterInfo"`
	ValuesName              string       `json:"valuesName" form:"valuesName"`
	CreatableEnvironment
}

type ModelController

type ModelController[M v2models.Model, R Readable, C Creatable[R], E Editable[R, C]] struct {
	// contains filtered or unexported fields
}

ModelController exposes the same "verbs" exposed by a v2models.Store, but it adds the user-type to database-type mapping that provides type safety for what fields can be read/queried, created, and edited. ModelController also handles setting defaults--even complex ones, like from template Environment entries.

Implementation note: this mapping behavior exists at the controller level (rather than in serializers, etc. written elsewhere) because going from a user-type to a database-type actually itself requires a database connection, so it can resolve associations. For example, a user-type would allow an association to be referenced by name, ID, or any other selector, but a database-type would specifically use the ID as the foreign key. ModelController is responsible for doing that translation. A bonus of defining the controller in terms of user-types is that defaults can be handled in terms of the user-type, making for simpler documentation and more obvious behavior.

func (ModelController[M, R, C, E]) Create

func (c ModelController[M, R, C, E]) Create(creatable C, user *auth.User) (R, error)

func (ModelController[M, R, C, E]) Delete

func (c ModelController[M, R, C, E]) Delete(selector string, user *auth.User) (R, error)

func (ModelController[M, R, C, E]) Edit

func (c ModelController[M, R, C, E]) Edit(selector string, editable E, user *auth.User) (R, error)

func (ModelController[M, R, C, E]) Get

func (c ModelController[M, R, C, E]) Get(selector string) (R, error)

func (ModelController[M, R, C, E]) GetOtherValidSelectors

func (c ModelController[M, R, C, E]) GetOtherValidSelectors(selector string) ([]string, error)

func (ModelController[M, R, C, E]) ListAllMatching

func (c ModelController[M, R, C, E]) ListAllMatching(filter R, limit int) ([]R, error)

type Readable

type Readable interface{}

Readable represents the full set of fields that can be read (or queried for) by a user. Generally, a Readable will at east embed a ReadableBaseType and a Creatable inside it, but it can have additional read-only fields. A Readable should map to some database v2models.Model type; see ModelController for more context.

type ReadableBaseType

type ReadableBaseType struct {
	ID        uint      `json:"id" form:"id"`
	CreatedAt time.Time `json:"createdAt" form:"createdAt"`
	UpdatedAt time.Time `json:"updatedAt" form:"updatedAt"`
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL