v2models

package
v0.1.50 Latest Latest
Warning

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

Go to latest
Published: Jun 7, 2023 License: BSD-3-Clause Imports: 23 Imported by: 0

README

Why are references always pointers?

Gorm lets us use structs to represent associations--and we can do so with pointer or value types (link).

So why do we always use pointers, causing us to have to do nil checks in a bunch of places?

The reason why has to do with returning data to the client. When we load something from the database, we load associations too, but only one layer deep.

If we used values for associations, associations at the second/third/fourth layer etc would all appear to be loaded, as zero values. Up at the controller layer, we'd end up returning a bunch of nonsense data to clients.

As a concrete example, suppose you requested a ChartRelease, and the model and controllers all represented associations with value types:

{
  // Fields at this level would be present because this is the top level
  "environmentInfo": {
    // Fields at this level would be present because this is the first layer of associations
    "defaultClusterInfo": {
      // Fields at this level would be EMPTY because this is the second layer of associations, and it doesn't get loaded
    },
    "templateEnvironmentInfo": {
      // Fields at this level would be EMPTY because this is the second layer of associations, and it doesn't get loaded
      "defaultClusterInfo": {
        // Fields at this level would be EMPTY because this is the third layer of associations, and it doesn't get loaded
      }
    }
  }
}

The above is true even if we use omitempty, because structs in Go don't themselves have an empty value.

The solution is to use pointer types for associations at the controller layer, so omitempty works. That gives us this:

{
  // Fields at this level would be present because this is the top level
  "environmentInfo": {
    // Fields at this level would be present because this is the first layer of associations
    // `defaultClusterInfo` and `templateEnvironmentInfo` were nil and so weren't included here
  }
}

If we want to use pointer types for associations at the controller, it is very helpful to use them at the model too. This means that a lot of functions inside the model need to handle pointer types.

Internal stores

There's a concept here of an "internal" store versus a normal store that gets exported. Here's the differences:

internalModelStore ModelStore
Singleton (kept in package-level vars) Instanced
Stateless Stateful (keeps a database reference as state)
Methods require a database reference Methods use database reference from state
Methods accept full model type as queries Methods accept selector strings as queries

(This table references model stores but event stores follow the same principle)

The basic idea is that internal stores can all call each other, even passing transaction references when necessary, while the exported stores are encapsulated things suitable for a controller to carry around.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func KeepMetricsUpdated added in v0.0.110

func KeepMetricsUpdated(ctx context.Context, db *gorm.DB)

func UpdateMetrics added in v0.0.110

func UpdateMetrics(ctx context.Context, db *gorm.DB) error

Types

type AppVersion

type AppVersion struct {
	gorm.Model
	CiIdentifier       *CiIdentifier `gorm:"polymorphic:Resource; polymorphicValue:app-version"`
	Chart              *Chart
	ChartID            uint   `gorm:"not null: default:null"`
	AppVersion         string `gorm:"not null: default:null"`
	GitCommit          string
	GitBranch          string
	Description        string
	ParentAppVersion   *AppVersion
	ParentAppVersionID *uint
}

func (AppVersion) GetCiIdentifier added in v0.1.43

func (a AppVersion) GetCiIdentifier() *CiIdentifier

func (AppVersion) TableName

func (a AppVersion) TableName() string

type Changeset added in v0.0.50

type Changeset struct {
	gorm.Model
	CiIdentifier   *CiIdentifier `gorm:"polymorphic:Resource; polymorphicValue:changeset"`
	ChartRelease   *ChartRelease
	ChartReleaseID uint

	From             ChartReleaseVersion `gorm:"embedded;embeddedPrefix:from_"`
	To               ChartReleaseVersion `gorm:"embedded;embeddedPrefix:to_"`
	AppliedAt        *time.Time
	SupersededAt     *time.Time
	NewAppVersions   []*AppVersion   `gorm:"many2many:v2_changeset_new_app_versions;constraint:OnDelete:CASCADE,OnUpdate:CASCADE;"`
	NewChartVersions []*ChartVersion `gorm:"many2many:v2_changeset_new_chart_versions;constraint:OnDelete:CASCADE,OnUpdate:CASCADE;"`
}

func (Changeset) GetCiIdentifier added in v0.1.43

func (c Changeset) GetCiIdentifier() *CiIdentifier

func (Changeset) TableName added in v0.0.50

func (c Changeset) TableName() string

type ChangesetStore added in v0.1.32

type ChangesetStore struct {
	*ModelStore[Changeset]
}

func (*ChangesetStore) Apply added in v0.1.32

func (s *ChangesetStore) Apply(selectors []string, user *auth_models.User) ([]Changeset, error)

func (*ChangesetStore) Plan added in v0.1.32

func (s *ChangesetStore) Plan(changesets []Changeset, user *auth_models.User) ([]Changeset, error)

func (*ChangesetStore) PlanAndApply added in v0.1.32

func (s *ChangesetStore) PlanAndApply(changesets []Changeset, user *auth_models.User) ([]Changeset, error)

func (*ChangesetStore) QueryApplied added in v0.1.32

func (s *ChangesetStore) QueryApplied(chartReleaseSelector string, offset int, limit int) ([]Changeset, error)

type Chart

type Chart struct {
	gorm.Model
	CiIdentifier *CiIdentifier `gorm:"polymorphic:Resource; polymorphicValue:chart"`
	Name         string        `gorm:"not null; default:null; unique"`
	// Mutable
	ChartRepo             *string `gorm:"not null; default:null"`
	AppImageGitRepo       *string
	AppImageGitMainBranch *string
	ChartExposesEndpoint  *bool
	DefaultSubdomain      *string
	DefaultProtocol       *string
	DefaultPort           *uint
	LegacyConfigsEnabled  *bool
	Description           *string
	PlaybookURL           *string
}

func (Chart) GetCiIdentifier added in v0.1.43

func (c Chart) GetCiIdentifier() *CiIdentifier

func (Chart) TableName

func (c Chart) TableName() string

type ChartRelease

type ChartRelease struct {
	gorm.Model
	CiIdentifier    *CiIdentifier `gorm:"polymorphic:Resource; polymorphicValue:chart-release"`
	Chart           *Chart
	ChartID         uint
	Cluster         *Cluster
	ClusterID       *uint
	DestinationType string
	Environment     *Environment
	EnvironmentID   *uint
	Name            string `gorm:"not null; default:null"`
	Namespace       string
	ChartReleaseVersion
	Subdomain               *string
	Protocol                *string
	Port                    *uint
	PagerdutyIntegration    *PagerdutyIntegration
	PagerdutyIntegrationID  *uint
	IncludeInBulkChangesets *bool
}

func (ChartRelease) GetCiIdentifier added in v0.1.43

func (c ChartRelease) GetCiIdentifier() *CiIdentifier

func (ChartRelease) TableName

func (c ChartRelease) TableName() string

type ChartReleaseVersion added in v0.0.50

type ChartReleaseVersion struct {
	ResolvedAt *time.Time

	AppVersionResolver             *string
	AppVersionExact                *string
	AppVersionBranch               *string
	AppVersionCommit               *string
	AppVersionFollowChartRelease   *ChartRelease
	AppVersionFollowChartReleaseID *uint
	AppVersion                     *AppVersion
	AppVersionID                   *uint

	ChartVersionResolver             *string
	ChartVersionExact                *string
	ChartVersionFollowChartRelease   *ChartRelease
	ChartVersionFollowChartReleaseID *uint
	ChartVersion                     *ChartVersion
	ChartVersionID                   *uint

	HelmfileRef         *string
	FirecloudDevelopRef *string
}

ChartReleaseVersion isn't stored in the database on its own, it is included as a part of a ChartRelease or Changeset. It has especially strict validation that requires it being fully loaded from the database. The resolve method will help "load" it fully from the database so it can survive validation.

type ChartVersion

type ChartVersion struct {
	gorm.Model
	CiIdentifier         *CiIdentifier `gorm:"polymorphic:Resource; polymorphicValue:chart-version"`
	Chart                *Chart
	ChartID              uint   `gorm:"not null: default:null"`
	ChartVersion         string `gorm:"not null: default:null"`
	Description          string
	ParentChartVersion   *ChartVersion
	ParentChartVersionID *uint
}

func (ChartVersion) GetCiIdentifier added in v0.1.43

func (c ChartVersion) GetCiIdentifier() *CiIdentifier

func (ChartVersion) TableName

func (c ChartVersion) TableName() string

type CiIdentifiable added in v0.1.43

type CiIdentifiable interface {
	// GetCiIdentifier should return either a type's loaded CiIdentifier or a generated one based on resource type and
	// resource ID. It's important for the caller to understand that this function can return things not in the
	// database yet.
	//
	// In reality, this function is meant to go hand-in-hand with createCiRunIdentifiersJustInTime. This function will
	// return CiIdentifier instances that may or may not exist, and that function will create them all before the
	// CiRun actually enters the database. If there's a breakdown in communication, it's actually fine for superfluous
	// creates to be attempted -- rejectDuplicateCiIdentifier will make it so that the creates will behave just like
	// gets.
	GetCiIdentifier() *CiIdentifier
}

CiIdentifiable is an interface to help align functionality across other types that can have a CiIdentifier.

type CiIdentifier added in v0.1.43

type CiIdentifier struct {
	gorm.Model
	ResourceType string `gorm:"index:idx_v2_ci_identifiers_polymorphic_index,priority:1"`
	ResourceID   uint   `gorm:"index:idx_v2_ci_identifiers_polymorphic_index,priority:2"`
	// Mutable
	CiRuns []*CiRun `gorm:"many2many:v2_ci_runs_for_identifiers; constraint:OnDelete:CASCADE,OnUpdate:CASCADE;"`
}

func (CiIdentifier) TableName added in v0.1.43

func (c CiIdentifier) TableName() string

type CiRun added in v0.1.43

type CiRun struct {
	gorm.Model
	Platform                   string
	GithubActionsOwner         string
	GithubActionsRepo          string
	GithubActionsRunID         uint
	GithubActionsAttemptNumber uint
	GithubActionsWorkflowPath  string
	ArgoWorkflowsNamespace     string
	ArgoWorkflowsName          string
	ArgoWorkflowsTemplate      string
	// Mutable
	RelatedResources []*CiIdentifier `gorm:"many2many:v2_ci_runs_for_identifiers; constraint:OnDelete:CASCADE,OnUpdate:CASCADE;"`
	TerminalAt       *time.Time
	Status           *string
}

func (CiRun) TableName added in v0.1.43

func (c CiRun) TableName() string

type Cluster

type Cluster struct {
	gorm.Model
	CiIdentifier      *CiIdentifier `gorm:"polymorphic:Resource; polymorphicValue:cluster"`
	Name              string        `gorm:"not null; default:null; unique"`
	Provider          string        `gorm:"not null; default:null"`
	GoogleProject     string
	AzureSubscription string
	Location          string `gorm:"not null; default:null"`
	// Mutable
	Base                *string `gorm:"not null; default:null"`
	Address             *string `gorm:"not null; default:null"`
	RequiresSuitability *bool   `gorm:"not null; default:null"`
	HelmfileRef         *string `gorm:"not null; default:null"`
}

func (Cluster) GetCiIdentifier added in v0.1.43

func (c Cluster) GetCiIdentifier() *CiIdentifier

func (Cluster) TableName

func (c Cluster) TableName() string

type DatabaseInstance added in v0.1.14

type DatabaseInstance struct {
	gorm.Model
	ChartRelease   *ChartRelease
	ChartReleaseID uint

	Platform      *string
	GoogleProject *string
	InstanceName  *string

	DefaultDatabase *string
}

func (DatabaseInstance) TableName added in v0.1.14

func (d DatabaseInstance) TableName() string

type Environment

type Environment struct {
	gorm.Model
	CiIdentifier              *CiIdentifier `gorm:"polymorphic:Resource; polymorphicValue:environment"`
	Base                      string
	Lifecycle                 string `gorm:"not null; default:null"`
	Name                      string `gorm:"not null; default:null"`
	NamePrefix                string
	TemplateEnvironment       *Environment
	TemplateEnvironmentID     *uint
	ValuesName                string
	AutoPopulateChartReleases *bool
	UniqueResourcePrefix      string `gorm:"not null; default:null"`
	DefaultNamespace          string
	// Mutable
	DefaultCluster              *Cluster
	DefaultClusterID            *uint
	DefaultFirecloudDevelopRef  *string
	Owner                       *User
	OwnerID                     *uint
	LegacyOwner                 *string
	RequiresSuitability         *bool
	BaseDomain                  *string
	NamePrefixesDomain          *bool
	HelmfileRef                 *string `gorm:"not null; default:null"`
	PreventDeletion             *bool
	AutoDelete                  *environment.AutoDelete `gorm:"column:delete_after; -:migration"`
	Description                 *string
	PagerdutyIntegration        *PagerdutyIntegration
	PagerdutyIntegrationID      *uint
	Offline                     *bool
	OfflineScheduleBeginEnabled *bool
	OfflineScheduleBeginTime    *string
	OfflineScheduleEndEnabled   *bool
	OfflineScheduleEndTime      *string
	OfflineScheduleEndWeekends  *bool
}

func (Environment) GetCiIdentifier added in v0.1.43

func (e Environment) GetCiIdentifier() *CiIdentifier

func (Environment) TableName

func (e Environment) TableName() string

type MiddlewareUserStore added in v0.1.17

type MiddlewareUserStore struct {
	// contains filtered or unexported fields
}

func NewMiddlewareUserStore added in v0.1.17

func NewMiddlewareUserStore(db *gorm.DB) *MiddlewareUserStore

func (*MiddlewareUserStore) GetGithubUserIfExists added in v0.1.18

func (s *MiddlewareUserStore) GetGithubUserIfExists(githubID string) (*User, error)

func (*MiddlewareUserStore) GetOrCreateUser added in v0.1.17

func (s *MiddlewareUserStore) GetOrCreateUser(email, googleID string) (User, error)

type Model

type Model interface {
	TableName() string
	// contains filtered or unexported methods
}

type ModelStore added in v0.0.50

type ModelStore[M Model] struct {
	// contains filtered or unexported fields
}

func (ModelStore[M]) Create added in v0.0.50

func (s ModelStore[M]) Create(model M, user *auth_models.User) (M, bool, error)

func (ModelStore[M]) Delete added in v0.0.50

func (s ModelStore[M]) Delete(selector string, user *auth_models.User) (M, error)

func (ModelStore[M]) Edit added in v0.0.50

func (s ModelStore[M]) Edit(selector string, editsToMake M, user *auth_models.User) (M, error)

func (ModelStore[M]) Get added in v0.0.50

func (s ModelStore[M]) Get(selector string) (M, error)

func (ModelStore[M]) GetOtherValidSelectors added in v0.0.50

func (s ModelStore[M]) GetOtherValidSelectors(selector string) ([]string, error)

GetOtherValidSelectors is basically just a human debug method. Different model types have different selectors to try to make it easier to refer to them than by having to directly query them and use their numeric ID primary key. Under the hood, models are already required to be able to generate selectors from an entry for uniqueness-validation purposes, so this is a simple method that uses that existing code to translate one selector for an existing entry into all possible selectors that would match.

func (ModelStore[M]) ListAllMatchingByCreated added in v0.0.74

func (s ModelStore[M]) ListAllMatchingByCreated(filter M, limit int) ([]M, error)

func (ModelStore[M]) ListAllMatchingByUpdated added in v0.0.74

func (s ModelStore[M]) ListAllMatchingByUpdated(filter M, limit int) ([]M, error)

type PagerdutyIntegration added in v0.1.1

type PagerdutyIntegration struct {
	gorm.Model
	PagerdutyID string
	Name        *string
	Key         *string
	Type        *string
}

func (PagerdutyIntegration) TableName added in v0.1.1

func (p PagerdutyIntegration) TableName() string

type StoreSet

type StoreSet struct {
	ClusterStore          *ModelStore[Cluster]
	EnvironmentStore      *ModelStore[Environment]
	ChartStore            *ModelStore[Chart]
	ChartVersionStore     *TreeModelStore[ChartVersion]
	AppVersionStore       *TreeModelStore[AppVersion]
	ChartReleaseStore     *ModelStore[ChartRelease]
	PagerdutyIntegration  *ModelStore[PagerdutyIntegration]
	DatabaseInstanceStore *ModelStore[DatabaseInstance]
	UserStore             *ModelStore[User]
	ChangesetStore        *ChangesetStore
	CiIdentifierStore     *ModelStore[CiIdentifier]
	CiRunStore            *ModelStore[CiRun]
	// contains filtered or unexported fields
}

func NewStoreSet

func NewStoreSet(db *gorm.DB) *StoreSet

type TreeModel added in v0.1.32

type TreeModel interface {
	Model
	// contains filtered or unexported methods
}

type TreeModelStore added in v0.1.32

type TreeModelStore[M TreeModel] struct {
	*ModelStore[M]
	// contains filtered or unexported fields
}

func (TreeModelStore[M]) GetChildrenPathToParent added in v0.1.32

func (s TreeModelStore[M]) GetChildrenPathToParent(originChild string, destinationParent string) (path []*M, connected bool, err error)

type User added in v0.1.16

func (User) TableName added in v0.1.16

func (u User) TableName() string

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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