Skip to content

Commit

Permalink
feat: add implementation of variable set
Browse files Browse the repository at this point in the history
  • Loading branch information
liu-hm19 committed Feb 12, 2025
1 parent 7dd6763 commit fc8dc41
Show file tree
Hide file tree
Showing 31 changed files with 4,369 additions and 28 deletions.
987 changes: 983 additions & 4 deletions api/openapispec/docs.go

Large diffs are not rendered by default.

987 changes: 983 additions & 4 deletions api/openapispec/swagger.json

Large diffs are not rendered by default.

647 changes: 645 additions & 2 deletions api/openapispec/swagger.yaml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions pkg/domain/constant/global.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const (
ResourcePageSizeLarge = 1000
CommonPageDefault = 1
CommonPageSizeDefault = 10
CommonMaxResultLimit = 1000
SortByCreateTimestamp = "createTimestamp"
SortByModifiedTimestamp = "modifiedTimestamp"
SortByName = "name"
Expand Down
9 changes: 9 additions & 0 deletions pkg/domain/constant/variable.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package constant

import "errors"

var (
ErrInvalidVariableName = errors.New("variable name can only have alphanumeric characters and underscores with [a-zA-Z0-9_]")
ErrInvalidVariableType = errors.New("invalid variable type, only PlainText and CipherText supported")
ErrEmptyVariableSet = errors.New("variable set should not be empty")
)
8 changes: 8 additions & 0 deletions pkg/domain/constant/variable_set.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package constant

import "errors"

var (
ErrInvalidVariableSetName = errors.New("variable set name can only have alphanumeric characters and underscores with [a-zA-Z0-9_]")
ErrEmptyVariableSetLabels = errors.New("variable set labels should not be empty")
)
59 changes: 59 additions & 0 deletions pkg/domain/entity/variable.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package entity

import "errors"

type VariableType string

const (
PlainTextType VariableType = "PlainText"
CipherTextType VariableType = "CipherText"
)

// Variable represents a specific configuration code variable,
// which usually includes the global configuration for Terraform providers like
// api host, access key and secret key.
type Variable struct {
// Name is the name of the variable.
Name string `yaml:"name,omitempty" json:"name,omitempty"`
// Value is the value of the variable.
Value string `yaml:"value,omitempty" json:"value,omitempty"`
// Type is the text type of the variable.
Type VariableType `yaml:"type,omitempty" json:"type,omitempty"`
// VariableSet is the variable set to which the variable belongs.
VariableSet string `yaml:"variableSet,omitempty" json:"variableSet,omitempty"`
}

// VariableFilter represents the filter conditions to list variables.
type VariableFilter struct {
Name string
VariableSet string
Pagination *Pagination
FetchAll bool
}

// VariableListResult represents the result of listing variables.
type VariableListResult struct {
Variables []*Variable
Total int
}

// Validate checks if the variable is valid.
func (v *Variable) Validate() error {
if v == nil {
return errors.New("variable is nil")
}

if v.Name == "" {
return errors.New("empty variable name")
}

if v.Type != PlainTextType && v.Type != CipherTextType {
return errors.New("invalid variable type")
}

if v.VariableSet == "" {
return errors.New("empty variable set name")
}

return nil
}
41 changes: 41 additions & 0 deletions pkg/domain/entity/variable_set.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package entity

import "errors"

// VariableSet represents a set of the global configuration variables.
type VariableSet struct {
// Name is the name of the variable set.
Name string `yaml:"name,omitempty" json:"name,omitempty"`
// Labels clarifies the scope of the variable set.
Labels map[string]string `yaml:"labels,omitempty" json:"labels,omitempty"`
}

// VariableSetFilter represents the filter conditions to list variable sets.
type VariableSetFilter struct {
Name string
Pagination *Pagination
FetchAll bool
}

// VariableSetListResult represents the result of listing variable sets.
type VariableSetListResult struct {
VariableSets []*VariableSet
Total int
}

// Validate checks if the variable set is valid.
func (vs *VariableSet) Validate() error {
if vs == nil {
return errors.New("variable set is nil")
}

if vs.Name == "" {
return errors.New("empty variable set name")
}

if len(vs.Labels) == 0 {
return errors.New("empty variable set labels")
}

return nil
}
30 changes: 30 additions & 0 deletions pkg/domain/repository/repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,33 @@ type RunRepository interface {
// List retrieves all existing run.
List(ctx context.Context, filter *entity.RunFilter, sortOptions *entity.SortOptions) (*entity.RunListResult, error)
}

// VariableSetRepository is an interface that defines the repository operations
// for variable sets. It follows the principles of domain-driven design (DDD).
type VariableSetRepository interface {
// Create creates a new variable set.
Create(ctx context.Context, vs *entity.VariableSet) error
// Delete deletes a variable set by its name.
Delete(ctx context.Context, name string) error
// Update updates an existing variable set.
Update(ctx context.Context, vs *entity.VariableSet) error
// Get retrieves a variable set by its name.
Get(ctx context.Context, name string) (*entity.VariableSet, error)
// List retrieves existing variable sets with filter and sort options.
List(ctx context.Context, filter *entity.VariableSetFilter, sortOptions *entity.SortOptions) (*entity.VariableSetListResult, error)
}

// VariableRepository is an interface that defines the repository operations
// for variables. It follows the principles of domain-driven design (DDD).
type VariableRepository interface {
// Create creates a new variable.
Create(ctx context.Context, v *entity.Variable) error
// Delete deletes a variable by its name and the variable set it belongs to.
Delete(ctx context.Context, name, variableSet string) error
// Update updates an existing variable.
Update(ctx context.Context, v *entity.Variable) error
// Get retrieves a variable by its name and the variable set it belogs to.
Get(ctx context.Context, name, variableSet string) (*entity.Variable, error)
// List retrieves existing variable with filter and sort options.
List(ctx context.Context, filter *entity.VariableFilter, sortOptions *entity.SortOptions) (*entity.VariableListResult, error)
}
18 changes: 0 additions & 18 deletions pkg/domain/request/stack_request.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import (
"net/http"

"kusionstack.io/kusion/pkg/domain/constant"
"kusionstack.io/kusion/pkg/domain/entity"
)

// CreateStackRequest represents the create request structure for
Expand All @@ -30,19 +29,6 @@ type CreateStackRequest struct {
Owners []string `json:"owners"`
}

type UpdateVariableRequest struct {
// Project is the project related to stack
Project string `json:"project,omitempty"`
// Path is the relative path of the stack within the source.
Path string `json:"path,omitempty"`
IsSecret bool `json:"isSecret,omitempty"`
// key is the unique index to use value in specific stack
Key string `json:"key,omitempty"`
// value is the plain value of no sensitive data
Value string `json:"value,omitempty"`
SecretValue *entity.SecretValue `json:"secretValue,omitempty"`
}

// UpdateStackRequest represents the update request structure for
// stack.
type UpdateStackRequest struct {
Expand Down Expand Up @@ -76,10 +62,6 @@ func (payload *UpdateStackRequest) Decode(r *http.Request) error {
return decode(r, payload)
}

func (payload *UpdateVariableRequest) Decode(r *http.Request) error {
return decode(r, payload)
}

func (payload *CreateStackRequest) Validate() error {
if payload.ProjectID == 0 && payload.ProjectName == "" {
return constant.ErrProjectNameOrIDRequired
Expand Down
82 changes: 82 additions & 0 deletions pkg/domain/request/variable_request.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package request

import (
"net/http"

"kusionstack.io/kusion/pkg/domain/constant"
"kusionstack.io/kusion/pkg/domain/entity"
)

// CreateVariableRequest represents the create request structure
// for a variable.
type CreateVariableRequest struct {
// Name is the name of the variable.
Name string `json:"name" binding:"required"`
// Value is the value of the variable.
Value string `json:"value"`
// Type is the type of the variable.
Type entity.VariableType `json:"type"`
// VariableSet is the variable set to which the variable belongs.
VariableSet string `json:"variableSet" binding:"required"`
}

// UpdateVariableRequest represents the update request structure
// for a variable.
type UpdateVariableRequest struct {
// Name is the name of the variable.
Name string `json:"name" binding:"required"`
// Value is the value of the variable.
Value string `json:"value"`
// Type is the type of the variable.
Type entity.VariableType `json:"type"`
// VariableSet is the variable set to which the variable belongs.
VariableSet string `json:"variableSet" binding:"required"`
}

func (payload *CreateVariableRequest) Validate() error {
// Validate variable name.
if validName(payload.Name) {
return constant.ErrInvalidVariableName
}

// Validate variable set name. .
if validName(payload.VariableSet) {
return constant.ErrInvalidVariableSetName
}

// Validate variable type.
if payload.Type != "" &&
payload.Type != entity.PlainTextType && payload.Type != entity.CipherTextType {
return constant.ErrInvalidVariableType
}

return nil
}

func (payload *UpdateVariableRequest) Validate() error {
// Validate variable name.
if validName(payload.Name) {
return constant.ErrInvalidVariableName
}

// Validate variable set name. .
if validName(payload.VariableSet) {
return constant.ErrInvalidVariableSetName
}

// Validate variable type.
if payload.Type != "" &&
payload.Type != entity.PlainTextType && payload.Type != entity.CipherTextType {
return constant.ErrInvalidVariableType
}

return nil
}

func (payload *CreateVariableRequest) Decode(r *http.Request) error {
return decode(r, payload)
}

func (payload *UpdateVariableRequest) Decode(r *http.Request) error {
return decode(r, payload)
}
59 changes: 59 additions & 0 deletions pkg/domain/request/variable_set_request.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
package request

import (
"net/http"

"kusionstack.io/kusion/pkg/domain/constant"
)

// CreateVariableSetRequest represents the create request structure
// for a variable set.
type CreateVariableSetRequest struct {
// Name is the name of the variable set.
Name string `json:"name" binding:"required"`
// Labels clarifies the scope of the variable set.
Labels map[string]string `json:"labels" binding:"required"`
}

// UpdateVariableSetRequest represents the update request structure
// for a variable set.
type UpdateVariableSetRequest struct {
// Name is the name of the variable set.
Name string `json:"name" binding:"required"`
// Labels clarifies the scope of the variable set.
Labels map[string]string `json:"labels" binding:"required"`
}

func (payload *CreateVariableSetRequest) Validate() error {
// Validate variable set name.
if validName(payload.Name) {
return constant.ErrInvalidVariableSetName
}

if len(payload.Labels) == 0 {
return constant.ErrEmptyVariableSetLabels
}

return nil
}

func (payload *UpdateVariableSetRequest) Validate() error {
// Validate variable set name.
if payload.Name != "" && validName(payload.Name) {
return constant.ErrInvalidVariableSetName
}

if len(payload.Labels) == 0 {
return constant.ErrEmptyVariableSetLabels
}

return nil
}

func (payload *CreateVariableSetRequest) Decode(r *http.Request) error {
return decode(r, payload)
}

func (payload *UpdateVariableSetRequest) Decode(r *http.Request) error {
return decode(r, payload)
}
10 changes: 10 additions & 0 deletions pkg/domain/response/variable_response.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package response

import "kusionstack.io/kusion/pkg/domain/entity"

type PaginatedVariableResponse struct {
Variables []*entity.Variable `json:"variable"`
Total int `json:"total"`
CurrentPage int `json:"currentPage"`
PageSize int `json:"pageSize"`
}
15 changes: 15 additions & 0 deletions pkg/domain/response/variable_set_response.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package response

import "kusionstack.io/kusion/pkg/domain/entity"

type PaginatedVariableSetResponse struct {
VariableSets []*entity.VariableSet `json:"variableSets"`
Total int `json:"total"`
CurrentPage int `json:"currentPage"`
PageSize int `json:"pageSize"`
}

type SelectedVariableSetResponse struct {
VariableSets []*entity.VariableSet `json:"variableSets"`
Total int `json:"total"`
}
2 changes: 2 additions & 0 deletions pkg/infra/persistence/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ var (
ErrResourceModelNil = errors.New("resource model can't be nil")
ErrFailedToGetModuleDocRemote = errors.New("failed to parse module doc remote")
ErrRunModelNil = errors.New("run model can't be nil")
ErrVariableSetModelNil = errors.New("variable set model can't be nil")
ErrVariableModelNil = errors.New("variable model can't be nil")
ErrFailedToGetRunType = errors.New("failed to parse run type")
ErrFailedToGetRunStatus = errors.New("failed to parse run status")
)
Loading

0 comments on commit fc8dc41

Please sign in to comment.