Skip to content

Commit

Permalink
feat: implement variable set
Browse files Browse the repository at this point in the history
  • Loading branch information
liu-hm19 committed Dec 17, 2024
1 parent 4e63425 commit ecf0c3f
Show file tree
Hide file tree
Showing 33 changed files with 6,033 additions and 2,521 deletions.
2,637 changes: 1,690 additions & 947 deletions api/openapispec/docs.go

Large diffs are not rendered by default.

2,637 changes: 1,690 additions & 947 deletions api/openapispec/swagger.json

Large diffs are not rendered by default.

1,055 changes: 790 additions & 265 deletions api/openapispec/swagger.yaml

Large diffs are not rendered by default.

58 changes: 58 additions & 0 deletions pkg/domain/entity/variable.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package entity

import "errors"

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

// Variable represents the specific configuration code variable,
// which usually includes the global configurations for Terraform providers like
// api host, ak and sk.
type Variable struct {
// VariableKey is the access path for the variable.
VariableKey string `yaml:"variableKey,omitempty" json:"variableKey,omitempty"`
// Value is the value of the variable.
Value string `yaml:"value,omitempty" json:"value,omitempty"`
// Type is the type of the variable.
Type string `yaml:"type,omitempty" json:"type,omitempty"`
// Labels clarifies the scope of the variable.
Labels map[string]string `yaml:"labels,omitempty" json:"labels,omitempty"`
// Fqn is the fully qualified name of the variable.
Fqn string `yaml:"fqn,omitempty" json:"fqn,omitempty"`
}

// VariableFilter represents the filter conditions to list variables.
type VariableFilter struct {
Key string
Pagination *Pagination
}

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

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

if v.VariableKey == "" {
return errors.New("empty variable key")
}

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

if v.Fqn == "" {
return errors.New("empty fqn")
}

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

import "errors"

// VariableLabels records the labels of the specific configuration code variable,
// and the labels are sorted in ascending order of priority.
type VariableLabels struct {
// VariableKey is the access path for the variable.
VariableKey string `yaml:"variableKey,omitempty" json:"variableKey,omitempty"`
// Labels is the list of variable labels, which should be sorted
// in ascending order of priority.
Labels []string `yaml:"labels,omitempty" json:"labels,omitempty"`
}

// VariableLabelsFilter represents the filter conditions to list variable labels.
type VariableLabelsFilter struct {
Labels []string
Pagination *Pagination
}

// VariableLabelsListResult represents the result of listing variable labels.
type VariableLabelsListResult struct {
VariableLabels []*VariableLabels
Total int
}

// Validate checks if the variable labels are valid.
// It returns an error if the variable labels are not valid.
func (vl *VariableLabels) Validate() error {
if vl == nil {
return errors.New("nil variable labels")
}

if vl.VariableKey == "" {
return errors.New("empty key for variable labels")
}

if len(vl.Labels) == 0 {
return errors.New("empty variable 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) (*entity.RunListResult, error)
}

// VariableLabelsRepository is an interface that defines the repository
// for variable labels. It follows the principles of domain-driven design (DDD).
type VariableLabelsRepository interface {
// Create creates a new set of variable labels.
Create(ctx context.Context, vl *entity.VariableLabels) error
// Delete deletes a set of variable labels by its key.
Delete(ctx context.Context, key string) error
// Update updates an existing set of variable labels.
Update(ctx context.Context, vl *entity.VariableLabels) error
// GetByKey retrieves a set of variable labels by its key.
GetByKey(ctx context.Context, key string) (*entity.VariableLabels, error)
// List retrieves all existing variable labels.
List(ctx context.Context, filter *entity.VariableLabelsFilter) (*entity.VariableLabelsListResult, 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 fqn.
Delete(ctx context.Context, fqn string) error
// Update updates an existing variable.
Update(ctx context.Context, v *entity.Variable) error
// GetByFqn retrieves a variable by its fqn.
GetByFqn(ctx context.Context, fqn string) (*entity.Variable, error)
// List retrieves all existing variables.
List(ctx context.Context, filter *entity.VariableFilter) (*entity.VariableListResult, error)
}
31 changes: 31 additions & 0 deletions pkg/domain/request/variable_labels_request.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package request

import "net/http"

// CreateVariableLabelsRequest represents the create request structure
// for variable labels.
type CreateVariableLabelsRequest struct {
// VariableKey is the access path for the variable.
VariableKey string `json:"variableKey" binding:"required"`
// Labels is the list of variable labels, which should be sorted
// in ascending order of priority.
Labels []string `json:"labels" binding:"required"`
}

// UpdateVariableLabelsRequest represents the update request structure
// for variable labels.
type UpdateVariableLabelsRequest struct {
// VariableKey is the access path for the variable.
VariableKey string `json:"variableKey" binding:"required"`
// Labels is the list of variable labels, which should be sorted
// in ascending order of priority.
Labels []string `json:"labels" binding:"required"`
}

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

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

import "net/http"

// CreateVariableSetRequest represents the create request structure
// for a variable in the variable set.
type CreateVariableSetRequest struct {
// VariableKey is the access path for the variable.
VariableKey string `json:"variableKey" binding:"required"`
// Value is the value of the variable.
Value string `json:"value" binding:"required"`
// Type is the type of the variable.
Type string `json:"type" binding:"required"`
// Labels clarifies the scope of the variable.
Labels map[string]string `json:"labels,omitempty"`
}

// UpdateVariableSetRequest represents the update request structure
// for a variable in the variable set.
type UpdateVariableSetRequest struct {
// VariableKey is the access path for the variable.
VariableKey string `json:"variableKey" binding:"required"`
// Value is the value of the variable.
Value string `json:"value" binding:"required"`
// Type is the type of the variable.
Type string `json:"type" binding:"required"`
// Labels clarifies the scope of the variable.
Labels map[string]string `json:"labels" binding:"required"`
// Fqn is the fully qualified name of the variable.
Fqn string `json:"fqn" binding:"required"`
}

// ListVariableSetRequest represents the list request structure
// for variables matched to the labels in the variable set.
type ListVariableSetRequest struct {
// Labels clarifies the scope of the variables.
Labels map[string]string `json:"labels" binding:"required"`
}

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

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

func (payload *ListVariableSetRequest) Decode(r *http.Request) error {
return decode(r, payload)
}
10 changes: 10 additions & 0 deletions pkg/domain/response/variable.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:"variables"`
Total int `json:"total"`
CurrentPage int `json:"currentPage"`
PageSize int `json:"pageSize"`
}
10 changes: 10 additions & 0 deletions pkg/domain/response/variable_labels.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 PaginatedVariableLabelsResponse struct {
VariableLabels []*entity.VariableLabels `json:"variableLabels"`
Total int `json:"total"`
CurrentPage int `json:"currentPage"`
PageSize int `json:"pageSize"`
}
2 changes: 2 additions & 0 deletions pkg/infra/persistence/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ var (
ErrAppConfigModelNil = errors.New("appconfig model can't be nil")
ErrFailedToGetModuleRemote = errors.New("failed to parse module remote")
ErrResourceModelNil = errors.New("resource model can't be nil")
ErrVariableLabelsModelNil = errors.New("variable labels model can't be nil")
ErrVariableModelNil = errors.New("variable model can't be nil")
ErrFailedToGetModuleDocRemote = errors.New("failed to parse module doc remote")
ErrRunModelNil = errors.New("run model can't be nil")
ErrFailedToGetRunType = errors.New("failed to parse run type")
Expand Down
34 changes: 34 additions & 0 deletions pkg/infra/persistence/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,34 @@ func GetRunQuery(filter *entity.RunFilter) (string, []interface{}) {
return CombineQueryParts(pattern), args
}

func GetVariableLabelsQuery(filter *entity.VariableLabelsFilter) (string, []interface{}) {
pattern := make([]string, 0)
args := make([]interface{}, 0)

if len(filter.Labels) != 0 {
var labelsPattern []string
for _, label := range filter.Labels {
labelsPattern = append(labelsPattern, "labels LIKE ?")
args = append(args, "%"+label+"%")
}
pattern = append(pattern, "("+strings.Join(labelsPattern, " OR ")+")")
}

return CombineQueryParts(pattern), args
}

func GetVariableQuery(filter *entity.VariableFilter) (string, []interface{}) {
pattern := make([]string, 0)
args := make([]interface{}, 0)

if filter.Key != "" {
pattern = append(pattern, "variable_key = ?")
args = append(args, fmt.Sprintf(filter.Key))
}

return CombineQueryParts(pattern), args
}

func CombineQueryParts(queryParts []string) string {
queryString := ""
if len(queryParts) > 0 {
Expand Down Expand Up @@ -218,5 +246,11 @@ func AutoMigrate(db *gorm.DB) error {
if err := db.AutoMigrate(&RunModel{}); err != nil {
return err
}
if err := db.AutoMigrate(&VariableLabelsModel{}); err != nil {
return err
}
if err := db.AutoMigrate(&VariableModel{}); err != nil {
return err
}
return nil
}
Loading

0 comments on commit ecf0c3f

Please sign in to comment.