diff --git a/pkg/apis/core/v1/types.go b/pkg/apis/core/v1/types.go index 6b4baa6d6..7af93c6cd 100644 --- a/pkg/apis/core/v1/types.go +++ b/pkg/apis/core/v1/types.go @@ -5,6 +5,13 @@ type ( MonitorType string ) +const ( + KCLBuilder BuilderType = "KCL" + AppConfigurationBuilder BuilderType = "AppConfiguration" + PodMonitorType MonitorType = "Pod" + ServiceMonitorType MonitorType = "Service" +) + // Project is a definition of Kusion Project resource. // // A project is composed of one or more applications and is linked to a Git repository, @@ -18,8 +25,17 @@ type Project struct { // Labels is the list of labels that are assigned to this project. Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"` + // Path is a directory path within the Git repository. + Path string `json:"path,omitempty" yaml:"path,omitempty"` + // Generator controls how to generate the Intent. Generator *GeneratorConfig `json:"generator,omitempty" yaml:"generator,omitempty"` + + // Prometheus configs + Prometheus *PrometheusConfig `json:"prometheus,omitempty" yaml:"prometheus,omitempty"` + + // The set of stacks that are known about this project. + Stacks []*Stack `json:"stacks,omitempty" yaml:"stacks,omitempty"` } // GeneratorConfig holds the intent generation configurations defined in Project resource. @@ -30,6 +46,12 @@ type GeneratorConfig struct { Configs map[string]interface{} `json:"configs,omitempty" yaml:"configs,omitempty"` } +// PrometheusConfig represent Prometheus configs saved in project.yaml +type PrometheusConfig struct { + OperatorMode bool `yaml:"operatorMode,omitempty" json:"operatorMode,omitempty"` + MonitorType MonitorType `yaml:"monitorType,omitempty" json:"monitorType,omitempty"` +} + // Stack is a definition of Kusion Stack resource. // // Stack provides a mechanism to isolate multiple deploys of same application, @@ -43,4 +65,7 @@ type Stack struct { Description *string `json:"description,omitempty" yaml:"description,omitempty"` // Labels is the list of labels that are assigned to this stack. Labels map[string]string `json:"labels,omitempty" yaml:"labels,omitempty"` + + // Path is a directory path within the Git repository. + Path string `json:"path,omitempty" yaml:"path,omitempty"` } diff --git a/pkg/cmd/apply/options.go b/pkg/cmd/apply/options.go index 1ef1a5c7a..fb615af64 100644 --- a/pkg/cmd/apply/options.go +++ b/pkg/cmd/apply/options.go @@ -11,7 +11,6 @@ import ( "github.com/pterm/pterm" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" "kusionstack.io/kusion/pkg/apis/status" "kusionstack.io/kusion/pkg/cmd/build" cmdintent "kusionstack.io/kusion/pkg/cmd/build/builders" @@ -22,6 +21,7 @@ import ( opsmodels "kusionstack.io/kusion/pkg/engine/operation/models" "kusionstack.io/kusion/pkg/engine/states" "kusionstack.io/kusion/pkg/log" + "kusionstack.io/kusion/pkg/project" "kusionstack.io/kusion/pkg/util/pretty" ) @@ -286,7 +286,7 @@ func Apply( cluster := o.Arguments["cluster"] _, st := ac.Apply(&operation.ApplyRequest{ Request: opsmodels.Request{ - Tenant: changes.Project().Tenant, + Tenant: "", Project: changes.Project(), Stack: changes.Stack(), Cluster: cluster, diff --git a/pkg/cmd/apply/options_test.go b/pkg/cmd/apply/options_test.go index 9d0da6c6b..044e3e31d 100644 --- a/pkg/cmd/apply/options_test.go +++ b/pkg/cmd/apply/options_test.go @@ -12,9 +12,8 @@ import ( "github.com/bytedance/mockey" "github.com/stretchr/testify/assert" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/apis/status" "kusionstack.io/kusion/pkg/cmd/build" "kusionstack.io/kusion/pkg/cmd/build/builders" @@ -24,14 +23,15 @@ import ( "kusionstack.io/kusion/pkg/engine/runtime" "kusionstack.io/kusion/pkg/engine/runtime/kubernetes" "kusionstack.io/kusion/pkg/engine/states/local" + "kusionstack.io/kusion/pkg/project" ) func TestApplyOptions_Run(t *testing.T) { mockey.PatchConvey("Detail is true", t, func() { - mockeyPatchDetectProjectAndStack() - mockeyPatchBuildIntent() - mockeyPatchNewKubernetesRuntime() - mockeyPatchOperationPreview() + mockPatchDetectProjectAndStack() + mockPatchBuildIntent() + mockPatchNewKubernetesRuntime() + mockPatchOperationPreview() o := NewApplyOptions() o.Detail = true @@ -42,10 +42,10 @@ func TestApplyOptions_Run(t *testing.T) { }) mockey.PatchConvey("DryRun is true", t, func() { - mockeyPatchDetectProjectAndStack() - mockeyPatchBuildIntent() - mockeyPatchNewKubernetesRuntime() - mockeyPatchOperationPreview() + mockPatchDetectProjectAndStack() + mockPatchBuildIntent() + mockPatchNewKubernetesRuntime() + mockPatchOperationPreview() mockOperationApply(opsmodels.Success) o := NewApplyOptions() @@ -57,38 +57,33 @@ func TestApplyOptions_Run(t *testing.T) { } var ( - p = &project.Project{ - Configuration: project.Configuration{ - Name: "testdata", - Tenant: "admin", - }, + p = &apiv1.Project{ + Name: "testdata", } - s = &stack.Stack{ - Configuration: stack.Configuration{ - Name: "dev", - }, + s = &apiv1.Stack{ + Name: "dev", } ) -func mockeyPatchDetectProjectAndStack() *mockey.Mocker { - return mockey.Mock(project.DetectProjectAndStack).To(func(stackDir string) (*project.Project, *stack.Stack, error) { +func mockPatchDetectProjectAndStack() *mockey.Mocker { + return mockey.Mock(project.DetectProjectAndStack).To(func(stackDir string) (*apiv1.Project, *apiv1.Stack, error) { p.Path = stackDir s.Path = stackDir return p, s, nil }).Build() } -func mockeyPatchBuildIntent() *mockey.Mocker { +func mockPatchBuildIntent() *mockey.Mocker { return mockey.Mock(build.Intent).To(func( o *builders.Options, - project *project.Project, - stack *stack.Stack, + project *apiv1.Project, + stack *apiv1.Stack, ) (*intent.Intent, error) { return &intent.Intent{Resources: []intent.Resource{sa1, sa2, sa3}}, nil }).Build() } -func mockeyPatchNewKubernetesRuntime() *mockey.Mocker { +func mockPatchNewKubernetesRuntime() *mockey.Mocker { return mockey.Mock(kubernetes.NewKubernetesRuntime).To(func() (runtime.Runtime, error) { return &fakerRuntime{}, nil }).Build() @@ -130,7 +125,7 @@ func (f *fakerRuntime) Watch(ctx context.Context, request *runtime.WatchRequest) return nil } -func mockeyPatchOperationPreview() *mockey.Mocker { +func mockPatchOperationPreview() *mockey.Mocker { return mockey.Mock((*operation.PreviewOperation).Preview).To(func( *operation.PreviewOperation, *operation.PreviewRequest, diff --git a/pkg/cmd/build/builders/appconfig_builder.go b/pkg/cmd/build/builders/appconfig_builder.go index b7d3dda92..d35137dff 100644 --- a/pkg/cmd/build/builders/appconfig_builder.go +++ b/pkg/cmd/build/builders/appconfig_builder.go @@ -3,8 +3,6 @@ package builders import ( "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/modules" "kusionstack.io/kusion/pkg/modules/generators" "kusionstack.io/kusion/pkg/modules/inputs" @@ -17,8 +15,8 @@ type AppsConfigBuilder struct { func (acg *AppsConfigBuilder) Build( _ *Options, - project *project.Project, - stack *stack.Stack, + project *v1.Project, + stack *v1.Stack, ) (*intent.Intent, error) { i := &intent.Intent{ Resources: []intent.Resource{}, diff --git a/pkg/cmd/build/builders/appconfig_builder_test.go b/pkg/cmd/build/builders/appconfig_builder_test.go index 257db5a48..b3e8d9b74 100644 --- a/pkg/cmd/build/builders/appconfig_builder_test.go +++ b/pkg/cmd/build/builders/appconfig_builder_test.go @@ -6,8 +6,6 @@ import ( "github.com/stretchr/testify/assert" "kusionstack.io/kusion/pkg/apis/core/v1" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" appmodel "kusionstack.io/kusion/pkg/modules/inputs" "kusionstack.io/kusion/pkg/modules/inputs/workload" "kusionstack.io/kusion/pkg/modules/inputs/workload/network" @@ -86,17 +84,13 @@ func buildMockWorkspace() *v1.Workspace { } } -func buildMockProjectAndStack() (*project.Project, *stack.Stack) { - p := &project.Project{ - Configuration: project.Configuration{ - Name: "test-project", - }, +func buildMockProjectAndStack() (*v1.Project, *v1.Stack) { + p := &v1.Project{ + Name: "test-project", } - s := &stack.Stack{ - Configuration: stack.Configuration{ - Name: "test-stack", - }, + s := &v1.Stack{ + Name: "test-project", } return p, s diff --git a/pkg/cmd/build/builders/builder.go b/pkg/cmd/build/builders/builder.go index 6570164c3..0fa5abff7 100644 --- a/pkg/cmd/build/builders/builder.go +++ b/pkg/cmd/build/builders/builder.go @@ -1,16 +1,15 @@ package builders import ( + v1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" ) // Builder represents a method to build an Intent. Typically, it is implemented by the AppConfigureBuilder, // but we have designed it as an interface to allow for more general usage. Any struct that implements this interface // is considered a Builder and can be integrated into the Kusion workflow. type Builder interface { - Build(o *Options, project *project.Project, stack *stack.Stack) (*intent.Intent, error) + Build(o *Options, project *v1.Project, stack *v1.Stack) (*intent.Intent, error) } type Options struct { diff --git a/pkg/cmd/build/builders/kcl/kcl_builder.go b/pkg/cmd/build/builders/kcl/kcl_builder.go index 69f466cd9..22b8cd634 100644 --- a/pkg/cmd/build/builders/kcl/kcl_builder.go +++ b/pkg/cmd/build/builders/kcl/kcl_builder.go @@ -16,9 +16,8 @@ import ( "kcl-lang.io/kpm/pkg/api" "kcl-lang.io/kpm/pkg/opt" + v1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/cmd/build/builders" "kusionstack.io/kusion/pkg/cmd/build/builders/crd" "kusionstack.io/kusion/pkg/cmd/build/builders/kcl/rest" @@ -52,7 +51,7 @@ func EnableRPC() bool { return !enableRest } -func (g *Builder) Build(o *builders.Options, _ *project.Project, stack *stack.Stack) (*intent.Intent, error) { +func (g *Builder) Build(o *builders.Options, _ *v1.Project, stack *v1.Stack) (*intent.Intent, error) { compileResult, err := Run(o, stack) if err != nil { return nil, err @@ -66,7 +65,7 @@ func (g *Builder) Build(o *builders.Options, _ *project.Project, stack *stack.St return i, nil } -func Run(o *builders.Options, stack *stack.Stack) (*CompileResult, error) { +func Run(o *builders.Options, stack *v1.Stack) (*CompileResult, error) { optList, err := BuildKCLOptions(o) if err != nil { return nil, err diff --git a/pkg/cmd/build/options.go b/pkg/cmd/build/options.go index bc3ce5e10..76ed4d055 100644 --- a/pkg/cmd/build/options.go +++ b/pkg/cmd/build/options.go @@ -9,9 +9,12 @@ import ( yamlv2 "gopkg.in/yaml.v2" "kcl-lang.io/kpm/pkg/api" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/cmd/build/builders" + "kusionstack.io/kusion/pkg/project" +) + +const ( + KclFile = "kcl.yaml" ) type Options struct { @@ -42,7 +45,7 @@ func NewBuildOptions() *Options { func (o *Options) Complete(args []string) error { o.Filenames = args - return o.PreSet(stack.IsStack) + return o.PreSet(project.IsStack) } func (o *Options) Validate() error { @@ -124,7 +127,7 @@ func (o *Options) PreSet(preCheck func(cur string) bool) error { } if len(o.Settings) == 0 { - o.Settings = []string{project.KclFile} + o.Settings = []string{KclFile} } return nil } diff --git a/pkg/cmd/build/options_test.go b/pkg/cmd/build/options_test.go index 2e6721be0..fe581b9f1 100644 --- a/pkg/cmd/build/options_test.go +++ b/pkg/cmd/build/options_test.go @@ -9,11 +9,11 @@ import ( "github.com/bytedance/mockey" "github.com/stretchr/testify/assert" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/cmd/build/builders" "kusionstack.io/kusion/pkg/engine" + "kusionstack.io/kusion/pkg/project" ) var ( @@ -21,16 +21,11 @@ var ( kind = "ServiceAccount" namespace = "test-ns" - p = &project.Project{ - Configuration: project.Configuration{ - Name: "testdata", - Tenant: "admin", - }, + p = &apiv1.Project{ + Name: "testdata", } - s = &stack.Stack{ - Configuration: stack.Configuration{ - Name: "dev", - }, + s = &apiv1.Stack{ + Name: "dev", } sa1 = newSA("sa1") @@ -140,7 +135,7 @@ func newSA(name string) intent.Resource { } func mockDetectProjectAndStack() *mockey.Mocker { - return mockey.Mock(project.DetectProjectAndStack).To(func(stackDir string) (*project.Project, *stack.Stack, error) { + return mockey.Mock(project.DetectProjectAndStack).To(func(stackDir string) (*apiv1.Project, *apiv1.Stack, error) { p.Path = stackDir s.Path = stackDir return p, s, nil @@ -148,7 +143,7 @@ func mockDetectProjectAndStack() *mockey.Mocker { } func mockDetectProjectAndStackFail() *mockey.Mocker { - return mockey.Mock(project.DetectProjectAndStack).To(func(stackDir string) (*project.Project, *stack.Stack, error) { + return mockey.Mock(project.DetectProjectAndStack).To(func(stackDir string) (*apiv1.Project, *apiv1.Stack, error) { p.Path = stackDir s.Path = stackDir return p, s, errTest @@ -158,8 +153,8 @@ func mockDetectProjectAndStackFail() *mockey.Mocker { func mockGenerateIntent() *mockey.Mocker { return mockey.Mock(IntentWithSpinner).To(func( o *builders.Options, - project *project.Project, - stack *stack.Stack, + project *apiv1.Project, + stack *apiv1.Stack, ) (*intent.Intent, error) { return &intent.Intent{Resources: []intent.Resource{sa1, sa2, sa3}}, nil }).Build() @@ -168,8 +163,8 @@ func mockGenerateIntent() *mockey.Mocker { func mockGenerateIntentFail() *mockey.Mocker { return mockey.Mock(IntentWithSpinner).To(func( o *builders.Options, - project *project.Project, - stack *stack.Stack, + project *apiv1.Project, + stack *apiv1.Stack, ) (*intent.Intent, error) { return &intent.Intent{Resources: []intent.Resource{sa1, sa2, sa3}}, errTest }).Build() diff --git a/pkg/cmd/build/util.go b/pkg/cmd/build/util.go index fd184ac11..0e2d4d12b 100644 --- a/pkg/cmd/build/util.go +++ b/pkg/cmd/build/util.go @@ -12,9 +12,8 @@ import ( "gopkg.in/yaml.v2" yamlv3 "gopkg.in/yaml.v3" + v1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/cmd/build/builders" "kusionstack.io/kusion/pkg/cmd/build/builders/kcl" "kusionstack.io/kusion/pkg/log" @@ -23,7 +22,7 @@ import ( workspace "kusionstack.io/kusion/pkg/workspace" ) -func IntentWithSpinner(o *builders.Options, project *project.Project, stack *stack.Stack) (*intent.Intent, error) { +func IntentWithSpinner(o *builders.Options, project *v1.Project, stack *v1.Stack) (*intent.Intent, error) { var sp *pterm.SpinnerPrinter if o.NoStyle { fmt.Printf("Generating Intent in the Stack %s...\n", stack.Name) @@ -56,29 +55,29 @@ func IntentWithSpinner(o *builders.Options, project *project.Project, stack *sta return i, nil } -func Intent(o *builders.Options, p *project.Project, s *stack.Stack) (*intent.Intent, error) { +func Intent(o *builders.Options, p *v1.Project, s *v1.Stack) (*intent.Intent, error) { // Choose the generator var builder builders.Builder pg := p.Generator // default AppsConfigBuilder - var bt project.BuilderType + var bt v1.BuilderType if pg == nil { - bt = project.AppConfigurationBuilder + bt = v1.AppConfigurationBuilder } else { bt = pg.Type } // we can add more generators here switch bt { - case project.KCLBuilder: + case v1.KCLBuilder: builder = &kcl.Builder{} - case project.AppConfigurationBuilder: + case v1.AppConfigurationBuilder: appConfigs, err := buildAppConfigs(o, s) if err != nil { return nil, err } - ws, err := workspace.GetWorkspaceByDefaultOperator(s.GetName()) + ws, err := workspace.GetWorkspaceByDefaultOperator(s.Name) if err != nil { return nil, err } @@ -97,7 +96,7 @@ func Intent(o *builders.Options, p *project.Project, s *stack.Stack) (*intent.In return i, nil } -func buildAppConfigs(o *builders.Options, stack *stack.Stack) (map[string]inputs.AppConfiguration, error) { +func buildAppConfigs(o *builders.Options, stack *v1.Stack) (map[string]inputs.AppConfiguration, error) { o.Arguments[kcl.IncludeSchemaTypePath] = "true" compileResult, err := kcl.Run(o, stack) if err != nil { diff --git a/pkg/cmd/build/util_test.go b/pkg/cmd/build/util_test.go index e54ca9eab..694b8e89b 100644 --- a/pkg/cmd/build/util_test.go +++ b/pkg/cmd/build/util_test.go @@ -12,8 +12,6 @@ import ( "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/cmd/build/builders" "kusionstack.io/kusion/pkg/cmd/build/builders/kcl" appconfigmodel "kusionstack.io/kusion/pkg/modules/inputs" @@ -207,8 +205,8 @@ func TestBuildIntent(t *testing.T) { type args struct { o *builders.Options - project *project.Project - stack *stack.Stack + project *v1.Project + stack *v1.Stack mockers []*mockey.MockBuilder } tests := []struct { @@ -220,16 +218,14 @@ func TestBuildIntent(t *testing.T) { { name: "nil builder", args: struct { o *builders.Options - project *project.Project - stack *stack.Stack + project *v1.Project + stack *v1.Stack mockers []*mockey.MockBuilder }{ o: &builders.Options{Arguments: map[string]string{}}, - project: &project.Project{ - Configuration: project.Configuration{ - Name: "default", - }, - }, stack: &stack.Stack{}, + project: &v1.Project{ + Name: "default", + }, stack: &v1.Stack{}, mockers: []*mockey.MockBuilder{ mockey.Mock(kcl.Run).Return(&kcl.CompileResult{Documents: []kclgo.KCLResult{apcMap}}, nil), mockey.Mock(workspace.GetWorkspaceByDefaultOperator).Return(ws, nil), @@ -240,19 +236,17 @@ func TestBuildIntent(t *testing.T) { { name: "kcl builder", args: struct { o *builders.Options - project *project.Project - stack *stack.Stack + project *v1.Project + stack *v1.Stack mockers []*mockey.MockBuilder }{ o: &builders.Options{}, - project: &project.Project{ - Configuration: project.Configuration{ - Generator: &project.GeneratorConfig{ - Type: project.KCLBuilder, - }, + project: &v1.Project{ + Generator: &v1.GeneratorConfig{ + Type: v1.KCLBuilder, }, }, - stack: &stack.Stack{}, + stack: &v1.Stack{}, mockers: []*mockey.MockBuilder{ mockey.Mock((*kcl.Builder).Build).Return(nil, nil), }, @@ -262,23 +256,19 @@ func TestBuildIntent(t *testing.T) { { name: "app builder", args: struct { o *builders.Options - project *project.Project - stack *stack.Stack + project *v1.Project + stack *v1.Stack mockers []*mockey.MockBuilder }{ o: &builders.Options{Arguments: map[string]string{}}, - project: &project.Project{ - Configuration: project.Configuration{ - Name: "default", - Generator: &project.GeneratorConfig{ - Type: project.AppConfigurationBuilder, - }, + project: &v1.Project{ + Name: "default", + Generator: &v1.GeneratorConfig{ + Type: v1.AppConfigurationBuilder, }, }, - stack: &stack.Stack{ - Configuration: stack.Configuration{ - Name: "default", - }, + stack: &v1.Stack{ + Name: "default", }, mockers: []*mockey.MockBuilder{ mockey.Mock(kcl.Run).Return(&kcl.CompileResult{Documents: []kclgo.KCLResult{apcMap}}, nil), diff --git a/pkg/cmd/deps/deps_test.go b/pkg/cmd/deps/deps_test.go index d89fe36ca..88ed45e24 100644 --- a/pkg/cmd/deps/deps_test.go +++ b/pkg/cmd/deps/deps_test.go @@ -8,7 +8,7 @@ import ( "github.com/stretchr/testify/assert" - "kusionstack.io/kusion/pkg/apis/project" + "kusionstack.io/kusion/pkg/project" ) var workDir string diff --git a/pkg/cmd/deps/options.go b/pkg/cmd/deps/options.go index 7a51a8aa0..0c272df4b 100644 --- a/pkg/cmd/deps/options.go +++ b/pkg/cmd/deps/options.go @@ -10,7 +10,12 @@ import ( kcl "kcl-lang.io/kcl-go" "kcl-lang.io/kcl-go/pkg/tools/list" - "kusionstack.io/kusion/pkg/apis/project" + v1 "kusionstack.io/kusion/pkg/apis/core/v1" + "kusionstack.io/kusion/pkg/project" +) + +const ( + KclFile = "kcl.yaml" ) type Options struct { @@ -140,7 +145,7 @@ func (o *Options) Run() (err error) { } // 3. Find all the projects under the workdir - var projects []*project.Project + var projects []*v1.Project if projects, err = project.FindAllProjectsFrom(workDir); err != nil { return } @@ -179,7 +184,7 @@ func (o *Options) Run() (err error) { // Do not call this function with high frequency and please ensure at least 10 seconds interval when calling. func findDownStreams( workDir string, - projects []*project.Project, + projects []*v1.Project, focusPaths, shouldIgnore stringSet, projectOnly bool, ) (downStreams stringSet, err error) { @@ -191,10 +196,10 @@ func findDownStreams( // To list downstream stacks/projects, wee need to go through all the entrance files under each project/stack, // then filter out the ones that are downstream of the focus files for _, p := range projects { - projectRel, _ := filepath.Rel(workDir, p.GetPath()) + projectRel, _ := filepath.Rel(workDir, p.Path) for _, stack := range p.Stacks { // 1.1 Get the relative path of project/stack - stackRel, _ := filepath.Rel(workDir, stack.GetPath()) + stackRel, _ := filepath.Rel(workDir, stack.Path) var stackProjectPath string if projectOnly { stackProjectPath = projectRel @@ -222,7 +227,7 @@ func findDownStreams( continue } // 1.3 Collect and index all the entrance files of the stack by loading the settings file - settingsPath := filepath.Join(stack.GetPath(), project.KclFile) + settingsPath := filepath.Join(stack.Path, KclFile) opt := kcl.WithSettings(settingsPath) if opt.Err != nil { // The stack settings is invalid diff --git a/pkg/cmd/destroy/options.go b/pkg/cmd/destroy/options.go index b03e5c93e..c808def74 100644 --- a/pkg/cmd/destroy/options.go +++ b/pkg/cmd/destroy/options.go @@ -9,9 +9,8 @@ import ( "github.com/AlecAivazis/survey/v2" "github.com/pterm/pterm" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/apis/status" "kusionstack.io/kusion/pkg/cmd/build" "kusionstack.io/kusion/pkg/engine/backend" @@ -19,6 +18,7 @@ import ( opsmodels "kusionstack.io/kusion/pkg/engine/operation/models" "kusionstack.io/kusion/pkg/engine/states" "kusionstack.io/kusion/pkg/log" + "kusionstack.io/kusion/pkg/project" jsonutil "kusionstack.io/kusion/pkg/util/json" "kusionstack.io/kusion/pkg/util/signals" ) @@ -71,7 +71,7 @@ func (o *Options) Run() error { // only destroy resources we managed // todo add the `cluster` field in query query := &states.StateQuery{ - Tenant: project.Tenant, + Tenant: "", Stack: stack.Name, Project: project.Name, } @@ -134,8 +134,8 @@ func (o *Options) Run() error { } func (o *Options) preview( - planResources *intent.Intent, project *project.Project, - stack *stack.Stack, stateStorage states.StateStorage, + planResources *intent.Intent, project *apiv1.Project, + stack *apiv1.Stack, stateStorage states.StateStorage, ) (*opsmodels.Changes, error) { log.Info("Start compute preview changes ...") @@ -152,7 +152,7 @@ func (o *Options) preview( rsp, s := pc.Preview(&operation.PreviewRequest{ Request: opsmodels.Request{ - Tenant: project.Tenant, + Tenant: "", Project: project, Operator: o.Operator, Stack: stack, @@ -244,7 +244,7 @@ func (o *Options) destroy(planResources *intent.Intent, changes *opsmodels.Chang st := do.Destroy(&operation.DestroyRequest{ Request: opsmodels.Request{ - Tenant: changes.Project().Tenant, + Tenant: "", Project: changes.Project(), Operator: o.Operator, Stack: changes.Stack(), diff --git a/pkg/cmd/destroy/options_test.go b/pkg/cmd/destroy/options_test.go index 863c0af02..6d0b2766b 100644 --- a/pkg/cmd/destroy/options_test.go +++ b/pkg/cmd/destroy/options_test.go @@ -11,9 +11,8 @@ import ( "github.com/bytedance/mockey" "github.com/stretchr/testify/assert" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/apis/status" "kusionstack.io/kusion/pkg/engine" "kusionstack.io/kusion/pkg/engine/operation" @@ -22,6 +21,7 @@ import ( "kusionstack.io/kusion/pkg/engine/runtime/kubernetes" "kusionstack.io/kusion/pkg/engine/states" "kusionstack.io/kusion/pkg/engine/states/local" + "kusionstack.io/kusion/pkg/project" ) func TestDestroyOptions_Run(t *testing.T) { @@ -64,21 +64,16 @@ func TestDestroyOptions_Run(t *testing.T) { } var ( - p = &project.Project{ - Configuration: project.Configuration{ - Name: "testdata", - Tenant: "admin", - }, + p = &apiv1.Project{ + Name: "testdata", } - s = &stack.Stack{ - Configuration: stack.Configuration{ - Name: "dev", - }, + s = &apiv1.Stack{ + Name: "dev", } ) func mockDetectProjectAndStack() { - mockey.Mock(project.DetectProjectAndStack).To(func(stackDir string) (*project.Project, *stack.Stack, error) { + mockey.Mock(project.DetectProjectAndStack).To(func(stackDir string) (*apiv1.Project, *apiv1.Stack, error) { p.Path = stackDir s.Path = stackDir return p, s, nil diff --git a/pkg/cmd/preview/options.go b/pkg/cmd/preview/options.go index 663189969..2939648ca 100644 --- a/pkg/cmd/preview/options.go +++ b/pkg/cmd/preview/options.go @@ -10,9 +10,8 @@ import ( "github.com/pkg/errors" + "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/apis/status" "kusionstack.io/kusion/pkg/cmd/build" "kusionstack.io/kusion/pkg/cmd/build/builders" @@ -21,6 +20,7 @@ import ( opsmodels "kusionstack.io/kusion/pkg/engine/operation/models" "kusionstack.io/kusion/pkg/engine/states" "kusionstack.io/kusion/pkg/log" + "kusionstack.io/kusion/pkg/project" "kusionstack.io/kusion/pkg/util/pretty" ) @@ -229,8 +229,8 @@ func Preview( o *Options, storage states.StateStorage, planResources *intent.Intent, - project *project.Project, - stack *stack.Stack, + project *v1.Project, + stack *v1.Stack, ) (*opsmodels.Changes, error) { log.Info("Start compute preview changes ...") @@ -251,7 +251,7 @@ func Preview( cluster := o.Arguments["cluster"] rsp, s := pc.Preview(&operation.PreviewRequest{ Request: opsmodels.Request{ - Tenant: project.Tenant, + Tenant: "", Project: project, Stack: stack, Operator: o.Operator, diff --git a/pkg/cmd/preview/options_test.go b/pkg/cmd/preview/options_test.go index a09fde7e7..0522ef531 100644 --- a/pkg/cmd/preview/options_test.go +++ b/pkg/cmd/preview/options_test.go @@ -10,9 +10,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/apis/status" "kusionstack.io/kusion/pkg/cmd/build" "kusionstack.io/kusion/pkg/cmd/build/builders" @@ -22,6 +21,7 @@ import ( "kusionstack.io/kusion/pkg/engine/runtime" "kusionstack.io/kusion/pkg/engine/runtime/kubernetes" "kusionstack.io/kusion/pkg/engine/states/local" + "kusionstack.io/kusion/pkg/project" ) var ( @@ -29,16 +29,11 @@ var ( kind = "ServiceAccount" namespace = "test-ns" - p = &project.Project{ - Configuration: project.Configuration{ - Name: "testdata", - Tenant: "admin", - }, + p = &apiv1.Project{ + Name: "testdata", } - s = &stack.Stack{ - Configuration: stack.Configuration{ - Name: "dev", - }, + s = &apiv1.Stack{ + Name: "dev", } sa1 = newSA("sa1") @@ -229,7 +224,7 @@ func newSA(name string) intent.Resource { } func mockDetectProjectAndStack() *mockey.Mocker { - return mockey.Mock(project.DetectProjectAndStack).To(func(stackDir string) (*project.Project, *stack.Stack, error) { + return mockey.Mock(project.DetectProjectAndStack).To(func(stackDir string) (*apiv1.Project, *apiv1.Stack, error) { p.Path = stackDir s.Path = stackDir return p, s, nil @@ -239,8 +234,8 @@ func mockDetectProjectAndStack() *mockey.Mocker { func mockBuildIntent() *mockey.Mocker { return mockey.Mock(build.Intent).To(func( o *builders.Options, - project *project.Project, - stack *stack.Stack, + project *apiv1.Project, + stack *apiv1.Stack, ) (*intent.Intent, error) { return &intent.Intent{Resources: []intent.Resource{sa1, sa2, sa3}}, nil }).Build() @@ -249,8 +244,8 @@ func mockBuildIntent() *mockey.Mocker { func mockPatchBuildIntentWithSpinner() *mockey.Mocker { return mockey.Mock(build.IntentWithSpinner).To(func( o *builders.Options, - project *project.Project, - stack *stack.Stack, + project *apiv1.Project, + stack *apiv1.Stack, ) (*intent.Intent, error) { return &intent.Intent{Resources: []intent.Resource{sa1, sa2, sa3}}, nil }).Build() diff --git a/pkg/engine/backend/util.go b/pkg/engine/backend/util.go index e78931124..5ebee4173 100644 --- a/pkg/engine/backend/util.go +++ b/pkg/engine/backend/util.go @@ -4,13 +4,12 @@ import ( "fmt" "kusionstack.io/kusion/pkg/apis/core/v1" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/engine/states" "kusionstack.io/kusion/pkg/workspace" ) // NewStateStorage news a StateStorage by configs of workspace, cli backend options, and environment variables. -func NewStateStorage(stack *stack.Stack, opts *BackendOptions) (states.StateStorage, error) { +func NewStateStorage(stack *v1.Stack, opts *BackendOptions) (states.StateStorage, error) { var backendConfigs *v1.BackendConfigs wsOperator, err := workspace.NewValidDefaultOperator() if err != nil { diff --git a/pkg/engine/operation/apply_test.go b/pkg/engine/operation/apply_test.go index 5d2f5529f..ee2158963 100644 --- a/pkg/engine/operation/apply_test.go +++ b/pkg/engine/operation/apply_test.go @@ -10,9 +10,8 @@ import ( _ "github.com/go-sql-driver/mysql" "github.com/stretchr/testify/assert" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/apis/status" "kusionstack.io/kusion/pkg/engine/operation/graph" opsmodels "kusionstack.io/kusion/pkg/engine/operation/models" @@ -68,7 +67,7 @@ func TestOperation_Apply(t *testing.T) { StateResourceIndex map[string]*intent.Resource Order *opsmodels.ChangeOrder RuntimeMap map[intent.Type]runtime.Runtime - Stack *stack.Stack + Stack *apiv1.Stack MsgCh chan opsmodels.Message resultState *states.State lock *sync.Mutex @@ -110,17 +109,14 @@ func TestOperation_Apply(t *testing.T) { }, } - s := &stack.Stack{ - Configuration: stack.Configuration{Name: "fakeStack"}, - Path: "fakePath", + s := &apiv1.Stack{ + Name: "fakeStack", + Path: "fakePath", } - p := &project.Project{ - Configuration: project.Configuration{ - Name: "fakeProject", - Tenant: "fakeTenant", - }, + p := &apiv1.Project{ + Name: "fakeProject", Path: "fakePath", - Stacks: []*stack.Stack{s}, + Stacks: []*apiv1.Stack{s}, } tests := []struct { diff --git a/pkg/engine/operation/destory_test.go b/pkg/engine/operation/destory_test.go index 7773f5488..864b46089 100644 --- a/pkg/engine/operation/destory_test.go +++ b/pkg/engine/operation/destory_test.go @@ -10,9 +10,8 @@ import ( "github.com/bytedance/mockey" "github.com/stretchr/testify/assert" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/apis/status" "kusionstack.io/kusion/pkg/engine/operation/graph" opsmodels "kusionstack.io/kusion/pkg/engine/operation/models" @@ -28,17 +27,14 @@ func TestOperation_Destroy(t *testing.T) { operator = "foo_user" ) - s := &stack.Stack{ - Configuration: stack.Configuration{Name: "fake-name"}, - Path: "fake-path", + s := &apiv1.Stack{ + Name: "fake-name", + Path: "fake-path", } - p := &project.Project{ - Configuration: project.Configuration{ - Name: "fake-name", - Tenant: "fake-tenant", - }, + p := &apiv1.Project{ + Name: "fake-name", Path: "fake-path", - Stacks: []*stack.Stack{s}, + Stacks: []*apiv1.Stack{s}, } resourceState := intent.Resource{ diff --git a/pkg/engine/operation/models/change.go b/pkg/engine/operation/models/change.go index 6db1e6b55..88f1cf46b 100644 --- a/pkg/engine/operation/models/change.go +++ b/pkg/engine/operation/models/change.go @@ -9,9 +9,8 @@ import ( "github.com/AlecAivazis/survey/v2" "github.com/pterm/pterm" + "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/log" "kusionstack.io/kusion/pkg/util/diff" "kusionstack.io/kusion/pkg/util/pretty" @@ -85,8 +84,8 @@ var ( type Changes struct { *ChangeOrder `json:",inline" yaml:",inline"` - project *project.Project // the project of current changes - stack *stack.Stack // the stack of current changes + project *v1.Project // the project of current changes + stack *v1.Stack // the stack of current changes } type ChangeOrder struct { @@ -94,7 +93,7 @@ type ChangeOrder struct { ChangeSteps map[string]*ChangeStep `json:"changeSteps,omitempty" yaml:"changeSteps,omitempty"` } -func NewChanges(p *project.Project, s *stack.Stack, order *ChangeOrder) *Changes { +func NewChanges(p *v1.Project, s *v1.Stack, order *ChangeOrder) *Changes { return &Changes{ ChangeOrder: order, project: p, @@ -129,11 +128,11 @@ func (o *ChangeOrder) Values(filters ...ChangeStepFilterFunc) []*ChangeStep { return result } -func (p *Changes) Stack() *stack.Stack { +func (p *Changes) Stack() *v1.Stack { return p.stack } -func (p *Changes) Project() *project.Project { +func (p *Changes) Project() *v1.Project { return p.project } diff --git a/pkg/engine/operation/models/change_test.go b/pkg/engine/operation/models/change_test.go index 703b412ae..80d8259cb 100644 --- a/pkg/engine/operation/models/change_test.go +++ b/pkg/engine/operation/models/change_test.go @@ -7,9 +7,8 @@ import ( "github.com/stretchr/testify/assert" + "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/util/pretty" ) @@ -150,8 +149,8 @@ func TestChangeStep_Diff(t *testing.T) { func TestChanges_Get(t *testing.T) { type fields struct { order *ChangeOrder - project *project.Project - stack *stack.Stack + project *v1.Project + stack *v1.Stack } type args struct { key string @@ -194,8 +193,8 @@ func TestChanges_Get(t *testing.T) { func TestChanges_Values(t *testing.T) { type fields struct { order *ChangeOrder - project *project.Project - stack *stack.Stack + project *v1.Project + stack *v1.Stack } type args struct { filters []ChangeStepFilterFunc @@ -276,30 +275,26 @@ func TestChanges_Values(t *testing.T) { func TestChanges_Stack(t *testing.T) { type fields struct { order *ChangeOrder - project *project.Project - stack *stack.Stack + project *v1.Project + stack *v1.Stack } tests := []struct { name string fields fields - want *stack.Stack + want *v1.Stack }{ { name: "t1", fields: fields{ order: &ChangeOrder{StepKeys: []string{}, ChangeSteps: map[string]*ChangeStep{}}, - project: &project.Project{}, - stack: &stack.Stack{ - Configuration: stack.Configuration{ - Name: "test-name", - }, + project: &v1.Project{}, + stack: &v1.Stack{ + Name: "test-name", Path: "test-path", }, }, - want: &stack.Stack{ - Configuration: stack.Configuration{ - Name: "test-name", - }, + want: &v1.Stack{ + Name: "test-name", Path: "test-path", }, }, @@ -321,30 +316,24 @@ func TestChanges_Stack(t *testing.T) { func TestChanges_Project(t *testing.T) { type fields struct { order *ChangeOrder - project *project.Project - stack *stack.Stack + project *v1.Project + stack *v1.Stack } tests := []struct { name string fields fields - want *project.Project + want *v1.Project }{ { name: "t1", fields: fields{ - project: &project.Project{ - Configuration: project.Configuration{ - Name: "test-name", - Tenant: "test-tenant", - }, + project: &v1.Project{ + Name: "test-name", Path: "test-path", }, }, - want: &project.Project{ - Configuration: project.Configuration{ - Name: "test-name", - Tenant: "test-tenant", - }, + want: &v1.Project{ + Name: "test-name", Path: "test-path", }, }, @@ -362,8 +351,8 @@ func TestChanges_Project(t *testing.T) { func TestChanges_Diffs(t *testing.T) { type fields struct { order *ChangeOrder - project *project.Project - stack *stack.Stack + project *v1.Project + stack *v1.Stack } tests := []struct { name string @@ -404,8 +393,8 @@ func TestChanges_Diffs(t *testing.T) { func TestChanges_Preview(t *testing.T) { type fields struct { order *ChangeOrder - project *project.Project - stack *stack.Stack + project *v1.Project + stack *v1.Stack } tests := []struct { name string @@ -420,10 +409,8 @@ func TestChanges_Preview(t *testing.T) { "test-key": TestChangeStepOpCreate, }, }, - stack: &stack.Stack{ - Configuration: stack.Configuration{ - Name: "test-name", - }, + stack: &v1.Stack{ + Name: "test-name", }, }, }, diff --git a/pkg/engine/operation/models/operation_context.go b/pkg/engine/operation/models/operation_context.go index cac2e3add..3b65791d1 100644 --- a/pkg/engine/operation/models/operation_context.go +++ b/pkg/engine/operation/models/operation_context.go @@ -6,9 +6,8 @@ import ( "github.com/jinzhu/copier" + "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/engine/runtime" "kusionstack.io/kusion/pkg/engine/states" "kusionstack.io/kusion/pkg/log" @@ -43,7 +42,7 @@ type Operation struct { RuntimeMap map[intent.Type]runtime.Runtime // Stack contains info about where this command is invoked - Stack *stack.Stack + Stack *v1.Stack // MsgCh is used to send operation status like Success, Failed or Skip to Kusion CTl, // and this message will be displayed in the terminal @@ -63,12 +62,12 @@ type Message struct { } type Request struct { - Tenant string `json:"tenant"` - Project *project.Project `json:"project"` - Stack *stack.Stack `json:"stack"` - Cluster string `json:"cluster"` - Operator string `json:"operator"` - Intent *intent.Intent `json:"intent"` + Tenant string `json:"tenant"` + Project *v1.Project `json:"project"` + Stack *v1.Stack `json:"stack"` + Cluster string `json:"cluster"` + Operator string `json:"operator"` + Intent *intent.Intent `json:"intent"` } type OpResult string diff --git a/pkg/engine/operation/preview_test.go b/pkg/engine/operation/preview_test.go index 6eaf19f81..667490ac9 100644 --- a/pkg/engine/operation/preview_test.go +++ b/pkg/engine/operation/preview_test.go @@ -9,9 +9,8 @@ import ( "github.com/bytedance/mockey" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/apis/status" opsmodels "kusionstack.io/kusion/pkg/engine/operation/models" "kusionstack.io/kusion/pkg/engine/runtime" @@ -102,17 +101,14 @@ func TestOperation_Preview(t *testing.T) { type args struct { request *PreviewRequest } - s := &stack.Stack{ - Configuration: stack.Configuration{Name: "fake-name"}, - Path: "fake-path", + s := &apiv1.Stack{ + Name: "fake-name", + Path: "fake-path", } - p := &project.Project{ - Configuration: project.Configuration{ - Name: "fake-name", - Tenant: "fake-tenant", - }, + p := &apiv1.Project{ + Name: "fake-name", Path: "fake-path", - Stacks: []*stack.Stack{s}, + Stacks: []*apiv1.Stack{s}, } tests := []struct { name string diff --git a/pkg/engine/runtime/runtime.go b/pkg/engine/runtime/runtime.go index 2a4664cd7..b90e7b366 100644 --- a/pkg/engine/runtime/runtime.go +++ b/pkg/engine/runtime/runtime.go @@ -5,8 +5,8 @@ import ( "k8s.io/apimachinery/pkg/watch" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/apis/status" ) @@ -50,7 +50,7 @@ type ApplyRequest struct { PlanResource *intent.Resource // Stack contains info about where this command is invoked - Stack *stack.Stack + Stack *apiv1.Stack // DryRun means this a dry-run request and will not make any changes in actual infra DryRun bool @@ -72,7 +72,7 @@ type ReadRequest struct { PlanResource *intent.Resource // Stack contains info about where this command is invoked - Stack *stack.Stack + Stack *apiv1.Stack } type ReadResponse struct { @@ -88,7 +88,7 @@ type ImportRequest struct { PlanResource *intent.Resource // Stack contains info about where this command is invoked - Stack *stack.Stack + Stack *apiv1.Stack } type ImportResponse struct { @@ -104,7 +104,7 @@ type DeleteRequest struct { Resource *intent.Resource // Stack contains info about where this command is invoked - Stack *stack.Stack + Stack *apiv1.Stack } type DeleteResponse struct { diff --git a/pkg/engine/runtime/terraform/terraform_runtime.go b/pkg/engine/runtime/terraform/terraform_runtime.go index dfd27be82..ac81391d2 100644 --- a/pkg/engine/runtime/terraform/terraform_runtime.go +++ b/pkg/engine/runtime/terraform/terraform_runtime.go @@ -38,7 +38,7 @@ func (t *TerraformRuntime) Apply(ctx context.Context, request *runtime.ApplyRequ defer t.mu.Unlock() plan := request.PlanResource - stackPath := request.Stack.GetPath() + stackPath := request.Stack.Path tfCacheDir := filepath.Join(stackPath, "."+plan.ResourceKey()) t.WorkSpace.SetStackDir(stackPath) t.WorkSpace.SetCacheDir(tfCacheDir) @@ -136,7 +136,7 @@ func (t *TerraformRuntime) Read(ctx context.Context, request *runtime.ReadReques t.mu.Lock() defer t.mu.Unlock() - stackPath := request.Stack.GetPath() + stackPath := request.Stack.Path tfCacheDir := filepath.Join(stackPath, "."+planResource.ResourceKey()) t.WorkSpace.SetStackDir(stackPath) t.WorkSpace.SetCacheDir(tfCacheDir) @@ -197,7 +197,7 @@ func (t *TerraformRuntime) Import(ctx context.Context, request *runtime.ImportRe // Delete terraform resource and remove workspace func (t *TerraformRuntime) Delete(ctx context.Context, request *runtime.DeleteRequest) (res *runtime.DeleteResponse) { - stackPath := request.Stack.GetPath() + stackPath := request.Stack.Path tfCacheDir := filepath.Join(stackPath, "."+request.Resource.ResourceKey()) t.mu.Lock() defer t.mu.Unlock() diff --git a/pkg/modules/generators/accessories/database/alicloud_rds_test.go b/pkg/modules/generators/accessories/database/alicloud_rds_test.go index 1915698ae..105ca2c44 100644 --- a/pkg/modules/generators/accessories/database/alicloud_rds_test.go +++ b/pkg/modules/generators/accessories/database/alicloud_rds_test.go @@ -7,24 +7,19 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/modules/inputs" "kusionstack.io/kusion/pkg/modules/inputs/accessories/database" "kusionstack.io/kusion/pkg/modules/inputs/workload" ) func TestGenerateAlicloudResources(t *testing.T) { - project := &project.Project{ - Configuration: project.Configuration{ - Name: "testproject", - }, + project := &apiv1.Project{ + Name: "testproject", } - stack := &stack.Stack{ - Configuration: stack.Configuration{ - Name: "teststack", - }, + stack := &apiv1.Stack{ + Name: "teststack", } appName := "testapp" workload := &workload.Workload{} @@ -82,15 +77,11 @@ func TestGenerateAlicloudDBInstance(t *testing.T) { alicloudProvider := &inputs.Provider{} alicloudProvider.SetString(defaultAlicloudProvider) - project := &project.Project{ - Configuration: project.Configuration{ - Name: "testproject", - }, + project := &apiv1.Project{ + Name: "testproject", } - stack := &stack.Stack{ - Configuration: stack.Configuration{ - Name: "teststack", - }, + stack := &apiv1.Stack{ + Name: "teststack", } appName := "testapp" workload := &workload.Workload{} @@ -158,15 +149,11 @@ func TestGenerateAlicloudDBConnection(t *testing.T) { alicloudProvider := &inputs.Provider{} alicloudProvider.SetString(defaultAlicloudProvider) - project := &project.Project{ - Configuration: project.Configuration{ - Name: "testproject", - }, + project := &apiv1.Project{ + Name: "testproject", } - stack := &stack.Stack{ - Configuration: stack.Configuration{ - Name: "teststack", - }, + stack := &apiv1.Stack{ + Name: "teststack", } appName := "testapp" workload := &workload.Workload{} @@ -219,15 +206,11 @@ func TestGenerateAlicloudRDSAccount(t *testing.T) { alicloudProvider := &inputs.Provider{} alicloudProvider.SetString(defaultAlicloudProvider) - project := &project.Project{ - Configuration: project.Configuration{ - Name: "testproject", - }, + project := &apiv1.Project{ + Name: "testproject", } - stack := &stack.Stack{ - Configuration: stack.Configuration{ - Name: "teststack", - }, + stack := &apiv1.Stack{ + Name: "teststack", } appName := "testapp" workload := &workload.Workload{} diff --git a/pkg/modules/generators/accessories/database/aws_rds_test.go b/pkg/modules/generators/accessories/database/aws_rds_test.go index ca9a5fce1..efebe064d 100644 --- a/pkg/modules/generators/accessories/database/aws_rds_test.go +++ b/pkg/modules/generators/accessories/database/aws_rds_test.go @@ -7,24 +7,19 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/modules/inputs" "kusionstack.io/kusion/pkg/modules/inputs/accessories/database" "kusionstack.io/kusion/pkg/modules/inputs/workload" ) func TestGenerateAWSResources(t *testing.T) { - project := &project.Project{ - Configuration: project.Configuration{ - Name: "testproject", - }, + project := &apiv1.Project{ + Name: "testproject", } - stack := &stack.Stack{ - Configuration: stack.Configuration{ - Name: "teststack", - }, + stack := &apiv1.Stack{ + Name: "teststack", } appName := "testapp" workload := &workload.Workload{} @@ -76,15 +71,11 @@ func TestGenerateAWSSecurityGroup(t *testing.T) { awsProvider.SetString(defaultAWSProvider) awsProviderRegion = "us-east-1" - project := &project.Project{ - Configuration: project.Configuration{ - Name: "testproject", - }, + project := &apiv1.Project{ + Name: "testproject", } - stack := &stack.Stack{ - Configuration: stack.Configuration{ - Name: "teststack", - }, + stack := &apiv1.Stack{ + Name: "teststack", } appName := "testapp" workload := &workload.Workload{} @@ -147,15 +138,11 @@ func TestGenerateAWSDBInstance(t *testing.T) { awsProvider.SetString(defaultAWSProvider) awsProviderRegion = "us-east-1" - project := &project.Project{ - Configuration: project.Configuration{ - Name: "testproject", - }, + project := &apiv1.Project{ + Name: "testproject", } - stack := &stack.Stack{ - Configuration: stack.Configuration{ - Name: "teststack", - }, + stack := &apiv1.Stack{ + Name: "teststack", } appName := "testapp" workload := &workload.Workload{} diff --git a/pkg/modules/generators/accessories/database/database_generator.go b/pkg/modules/generators/accessories/database/database_generator.go index ac4f423f5..9e127a75b 100644 --- a/pkg/modules/generators/accessories/database/database_generator.go +++ b/pkg/modules/generators/accessories/database/database_generator.go @@ -9,9 +9,8 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/modules" "kusionstack.io/kusion/pkg/modules/inputs" "kusionstack.io/kusion/pkg/modules/inputs/accessories/database" @@ -28,16 +27,16 @@ const ( ) type databaseGenerator struct { - project *project.Project - stack *stack.Stack + project *apiv1.Project + stack *apiv1.Stack appName string workload *workload.Workload database *database.Database } func NewDatabaseGenerator( - project *project.Project, - stack *stack.Stack, + project *apiv1.Project, + stack *apiv1.Stack, appName string, workload *workload.Workload, database *database.Database, @@ -56,8 +55,8 @@ func NewDatabaseGenerator( } func NewDatabaseGeneratorFunc( - project *project.Project, - stack *stack.Stack, + project *apiv1.Project, + stack *apiv1.Stack, appName string, workload *workload.Workload, database *database.Database, diff --git a/pkg/modules/generators/accessories/database/database_generator_test.go b/pkg/modules/generators/accessories/database/database_generator_test.go index 3a58bab3d..abb5422db 100644 --- a/pkg/modules/generators/accessories/database/database_generator_test.go +++ b/pkg/modules/generators/accessories/database/database_generator_test.go @@ -8,9 +8,8 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/modules/inputs" "kusionstack.io/kusion/pkg/modules/inputs/accessories/database" "kusionstack.io/kusion/pkg/modules/inputs/workload" @@ -18,15 +17,11 @@ import ( ) func TestNewDatabaseGenerator(t *testing.T) { - project := &project.Project{ - Configuration: project.Configuration{ - Name: "testproject", - }, + project := &apiv1.Project{ + Name: "testproject", } - stack := &stack.Stack{ - Configuration: stack.Configuration{ - Name: "teststack", - }, + stack := &apiv1.Stack{ + Name: "teststack", } appName := "testapp" workload := &workload.Workload{} @@ -38,15 +33,11 @@ func TestNewDatabaseGenerator(t *testing.T) { } func TestGenerate(t *testing.T) { - project := &project.Project{ - Configuration: project.Configuration{ - Name: "testproject", - }, + project := &apiv1.Project{ + Name: "testproject", } - stack := &stack.Stack{ - Configuration: stack.Configuration{ - Name: "teststack", - }, + stack := &apiv1.Stack{ + Name: "teststack", } appName := "testapp" workload := &workload.Workload{} @@ -166,15 +157,11 @@ func TestGenerate(t *testing.T) { } func TestInjectSecret(t *testing.T) { - project := &project.Project{ - Configuration: project.Configuration{ - Name: "testproject", - }, + project := &apiv1.Project{ + Name: "testproject", } - stack := &stack.Stack{ - Configuration: stack.Configuration{ - Name: "teststack", - }, + stack := &apiv1.Stack{ + Name: "teststack", } appName := "testapp" workload := &workload.Workload{ @@ -246,15 +233,11 @@ func TestInjectSecret(t *testing.T) { } func TestGenerateTFRandomPassword(t *testing.T) { - project := &project.Project{ - Configuration: project.Configuration{ - Name: "testproject", - }, + project := &apiv1.Project{ + Name: "testproject", } - stack := &stack.Stack{ - Configuration: stack.Configuration{ - Name: "teststack", - }, + stack := &apiv1.Stack{ + Name: "teststack", } appName := "testapp" workload := &workload.Workload{} @@ -292,15 +275,11 @@ func TestGenerateTFRandomPassword(t *testing.T) { } func TestGenerateDBSeret(t *testing.T) { - project := &project.Project{ - Configuration: project.Configuration{ - Name: "testproject", - }, + project := &apiv1.Project{ + Name: "testproject", } - stack := &stack.Stack{ - Configuration: stack.Configuration{ - Name: "teststack", - }, + stack := &apiv1.Stack{ + Name: "teststack", } appName := "testapp" workload := &workload.Workload{} diff --git a/pkg/modules/generators/accessories/database/local_database_test.go b/pkg/modules/generators/accessories/database/local_database_test.go index 144024721..35b29a69e 100644 --- a/pkg/modules/generators/accessories/database/local_database_test.go +++ b/pkg/modules/generators/accessories/database/local_database_test.go @@ -7,23 +7,18 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/modules/inputs/accessories/database" "kusionstack.io/kusion/pkg/modules/inputs/workload" ) func TestGenerateLocalResources(t *testing.T) { - project := &project.Project{ - Configuration: project.Configuration{ - Name: "testproject", - }, + project := &apiv1.Project{ + Name: "testproject", } - stack := &stack.Stack{ - Configuration: stack.Configuration{ - Name: "teststack", - }, + stack := &apiv1.Stack{ + Name: "teststack", } appName := "testapp" workload := &workload.Workload{} @@ -69,15 +64,11 @@ func TestGenerateLocalResources(t *testing.T) { } func TestGenerateLocalSecret(t *testing.T) { - project := &project.Project{ - Configuration: project.Configuration{ - Name: "testproject", - }, + project := &apiv1.Project{ + Name: "testproject", } - stack := &stack.Stack{ - Configuration: stack.Configuration{ - Name: "teststack", - }, + stack := &apiv1.Stack{ + Name: "teststack", } appName := "testapp" workload := &workload.Workload{} @@ -105,15 +96,11 @@ func TestGenerateLocalSecret(t *testing.T) { } func TestGenerateLocalPVC(t *testing.T) { - project := &project.Project{ - Configuration: project.Configuration{ - Name: "testproject", - }, + project := &apiv1.Project{ + Name: "testproject", } - stack := &stack.Stack{ - Configuration: stack.Configuration{ - Name: "teststack", - }, + stack := &apiv1.Stack{ + Name: "teststack", } appName := "testapp" workload := &workload.Workload{} @@ -139,15 +126,11 @@ func TestGenerateLocalPVC(t *testing.T) { } func TestGenerateLocalDeployment(t *testing.T) { - project := &project.Project{ - Configuration: project.Configuration{ - Name: "testproject", - }, + project := &apiv1.Project{ + Name: "testproject", } - stack := &stack.Stack{ - Configuration: stack.Configuration{ - Name: "teststack", - }, + stack := &apiv1.Stack{ + Name: "teststack", } appName := "testapp" workload := &workload.Workload{} @@ -173,15 +156,11 @@ func TestGenerateLocalDeployment(t *testing.T) { } func TestGenerateLocalService(t *testing.T) { - project := &project.Project{ - Configuration: project.Configuration{ - Name: "testproject", - }, + project := &apiv1.Project{ + Name: "testproject", } - stack := &stack.Stack{ - Configuration: stack.Configuration{ - Name: "teststack", - }, + stack := &apiv1.Stack{ + Name: "teststack", } appName := "testapp" workload := &workload.Workload{} diff --git a/pkg/modules/generators/app_configurations_generator.go b/pkg/modules/generators/app_configurations_generator.go index 01ae09c65..4e372bcd8 100644 --- a/pkg/modules/generators/app_configurations_generator.go +++ b/pkg/modules/generators/app_configurations_generator.go @@ -6,8 +6,6 @@ import ( "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/modules" accessories "kusionstack.io/kusion/pkg/modules/generators/accessories/database" "kusionstack.io/kusion/pkg/modules/generators/monitoring" @@ -20,16 +18,16 @@ import ( ) type appConfigurationGenerator struct { - project *project.Project - stack *stack.Stack + project *v1.Project + stack *v1.Stack appName string app *inputs.AppConfiguration ws *v1.Workspace } func NewAppConfigurationGenerator( - project *project.Project, - stack *stack.Stack, + project *v1.Project, + stack *v1.Stack, appName string, app *inputs.AppConfiguration, ws *v1.Workspace, @@ -50,7 +48,7 @@ func NewAppConfigurationGenerator( return nil, errors.New("workspace must not be empty") // AppConfiguration asks for non-empty workspace } if err := workspace.ValidateWorkspace(ws); err != nil { - return nil, fmt.Errorf("invalid config of workspace %s, %w", stack.GetName(), err) + return nil, fmt.Errorf("invalid config of workspace %s, %w", stack.Name, err) } return &appConfigurationGenerator{ @@ -63,8 +61,8 @@ func NewAppConfigurationGenerator( } func NewAppConfigurationGeneratorFunc( - project *project.Project, - stack *stack.Stack, + project *v1.Project, + stack *v1.Stack, appName string, app *inputs.AppConfiguration, ws *v1.Workspace, diff --git a/pkg/modules/generators/app_configurations_generator_test.go b/pkg/modules/generators/app_configurations_generator_test.go index 749e936a1..1dadc9761 100644 --- a/pkg/modules/generators/app_configurations_generator_test.go +++ b/pkg/modules/generators/app_configurations_generator_test.go @@ -7,8 +7,6 @@ import ( "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" appmodel "kusionstack.io/kusion/pkg/modules/inputs" "kusionstack.io/kusion/pkg/modules/inputs/workload" "kusionstack.io/kusion/pkg/modules/inputs/workload/network" @@ -131,17 +129,13 @@ func buildMockWorkspace() *v1.Workspace { } } -func buildMockProjectAndStack() (*project.Project, *stack.Stack) { - project := &project.Project{ - Configuration: project.Configuration{ - Name: "testproject", - }, +func buildMockProjectAndStack() (*v1.Project, *v1.Stack) { + project := &v1.Project{ + Name: "testproject", } - stack := &stack.Stack{ - Configuration: stack.Configuration{ - Name: "test", - }, + stack := &v1.Stack{ + Name: "test", } return project, stack diff --git a/pkg/modules/generators/monitoring/monitoring_generator.go b/pkg/modules/generators/monitoring/monitoring_generator.go index 44ad399e4..f0bae84bb 100644 --- a/pkg/modules/generators/monitoring/monitoring_generator.go +++ b/pkg/modules/generators/monitoring/monitoring_generator.go @@ -6,20 +6,20 @@ import ( prometheusv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" "kusionstack.io/kusion/pkg/modules" "kusionstack.io/kusion/pkg/modules/inputs/monitoring" ) type monitoringGenerator struct { - project *project.Project + project *apiv1.Project monitor *monitoring.Monitor appName string } func NewMonitoringGenerator( - project *project.Project, + project *apiv1.Project, monitor *monitoring.Monitor, appName string, ) (modules.Generator, error) { @@ -38,7 +38,7 @@ func NewMonitoringGenerator( } func NewMonitoringGeneratorFunc( - project *project.Project, + project *apiv1.Project, monitor *monitoring.Monitor, appName string, ) modules.NewGeneratorFunc { @@ -67,8 +67,8 @@ func (g *monitoringGenerator) Generate(spec *intent.Intent) error { "kusion_monitoring_appname": g.appName, } - if g.project.Configuration.Prometheus != nil && g.project.Configuration.Prometheus.OperatorMode && g.monitor != nil { - if g.project.Configuration.Prometheus.MonitorType == project.ServiceMonitorType { + if g.project.Prometheus != nil && g.project.Prometheus.OperatorMode && g.monitor != nil { + if g.project.Prometheus.MonitorType == apiv1.ServiceMonitorType { serviceEndpoint := prometheusv1.Endpoint{ Interval: g.monitor.Interval, ScrapeTimeout: g.monitor.Timeout, @@ -99,7 +99,7 @@ func (g *monitoringGenerator) Generate(spec *intent.Intent) error { if err != nil { return err } - } else if g.project.Configuration.Prometheus.MonitorType == project.PodMonitorType { + } else if g.project.Prometheus.MonitorType == apiv1.PodMonitorType { podMetricsEndpoint := prometheusv1.PodMetricsEndpoint{ Interval: g.monitor.Interval, ScrapeTimeout: g.monitor.Timeout, @@ -133,7 +133,7 @@ func (g *monitoringGenerator) Generate(spec *intent.Intent) error { return err } } else { - return fmt.Errorf("MonitorType should either be service or pod %s", g.project.Configuration.Prometheus.MonitorType) + return fmt.Errorf("MonitorType should either be service or pod %s", g.project.Prometheus.MonitorType) } } diff --git a/pkg/modules/generators/monitoring/monitoring_generator_test.go b/pkg/modules/generators/monitoring/monitoring_generator_test.go index 2bc2c5ce0..02977a59c 100644 --- a/pkg/modules/generators/monitoring/monitoring_generator_test.go +++ b/pkg/modules/generators/monitoring/monitoring_generator_test.go @@ -8,13 +8,13 @@ import ( prometheusv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1" "github.com/stretchr/testify/require" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" "kusionstack.io/kusion/pkg/modules/inputs/monitoring" ) type Fields struct { - project *project.Project + project *apiv1.Project monitor *monitoring.Monitor appName string } @@ -35,11 +35,11 @@ func BuildMonitoringTestCase( projectName, appName string, interval, timeout prometheusv1.Duration, path, port, scheme string, - monitorType project.MonitorType, + monitorType apiv1.MonitorType, operatorMode bool, ) *TestCase { var endpointType string - var monitorKind project.MonitorType + var monitorKind apiv1.MonitorType if monitorType == "Service" { monitorKind = "ServiceMonitor" endpointType = "endpoints" @@ -92,13 +92,11 @@ func BuildMonitoringTestCase( testCase := &TestCase{ name: fmt.Sprintf("%s-%s", projectName, appName), fields: Fields{ - project: &project.Project{ - Configuration: project.Configuration{ - Name: projectName, - Prometheus: &project.PrometheusConfig{ - OperatorMode: operatorMode, - MonitorType: monitorType, - }, + project: &apiv1.Project{ + Name: projectName, + Prometheus: &apiv1.PrometheusConfig{ + OperatorMode: operatorMode, + MonitorType: monitorType, }, Path: "/test-project", }, diff --git a/pkg/modules/generators/trait/ops_rule_generator.go b/pkg/modules/generators/trait/ops_rule_generator.go index 0939ef906..f51b70274 100644 --- a/pkg/modules/generators/trait/ops_rule_generator.go +++ b/pkg/modules/generators/trait/ops_rule_generator.go @@ -5,24 +5,23 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "kusionstack.io/kube-api/apps/v1alpha1" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/modules" appmodule "kusionstack.io/kusion/pkg/modules/inputs" "kusionstack.io/kusion/pkg/modules/inputs/workload" ) type opsRuleGenerator struct { - project *project.Project - stack *stack.Stack + project *apiv1.Project + stack *apiv1.Stack appName string app *appmodule.AppConfiguration } func NewOpsRuleGenerator( - project *project.Project, - stack *stack.Stack, + project *apiv1.Project, + stack *apiv1.Stack, appName string, app *appmodule.AppConfiguration, ) (modules.Generator, error) { @@ -35,8 +34,8 @@ func NewOpsRuleGenerator( } func NewOpsRuleGeneratorFunc( - project *project.Project, - stack *stack.Stack, + project *apiv1.Project, + stack *apiv1.Stack, appName string, app *appmodule.AppConfiguration, ) modules.NewGeneratorFunc { diff --git a/pkg/modules/generators/trait/ops_rule_generator_test.go b/pkg/modules/generators/trait/ops_rule_generator_test.go index 476b0cfe6..78aba56d9 100644 --- a/pkg/modules/generators/trait/ops_rule_generator_test.go +++ b/pkg/modules/generators/trait/ops_rule_generator_test.go @@ -5,9 +5,8 @@ import ( "github.com/stretchr/testify/require" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" appmodule "kusionstack.io/kusion/pkg/modules/inputs" "kusionstack.io/kusion/pkg/modules/inputs/trait" "kusionstack.io/kusion/pkg/modules/inputs/workload" @@ -15,21 +14,19 @@ import ( func Test_opsRuleGenerator_Generate(t *testing.T) { type fields struct { - project *project.Project - stack *stack.Stack + project *apiv1.Project + stack *apiv1.Stack appName string app *appmodule.AppConfiguration } type args struct { spec *intent.Intent } - project := &project.Project{ - Configuration: project.Configuration{ - Name: "default", - }, + project := &apiv1.Project{ + Name: "default", } - stack := &stack.Stack{ - Configuration: stack.Configuration{Name: "dev"}, + stack := &apiv1.Stack{ + Name: "dev", } appName := "foo" tests := []struct { @@ -143,8 +140,8 @@ func Test_opsRuleGenerator_Generate(t *testing.T) { func TestNewOpsRuleGeneratorFunc(t *testing.T) { type args struct { - project *project.Project - stack *stack.Stack + project *apiv1.Project + stack *apiv1.Stack appName string app *appmodule.AppConfiguration } diff --git a/pkg/modules/generators/workload/job_generator.go b/pkg/modules/generators/workload/job_generator.go index 359bf478a..b29a00f55 100644 --- a/pkg/modules/generators/workload/job_generator.go +++ b/pkg/modules/generators/workload/job_generator.go @@ -5,23 +5,22 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/modules" "kusionstack.io/kusion/pkg/modules/inputs/workload" ) type jobGenerator struct { - project *project.Project - stack *stack.Stack + project *apiv1.Project + stack *apiv1.Stack appName string job *workload.Job } func NewJobGenerator( - project *project.Project, - stack *stack.Stack, + project *apiv1.Project, + stack *apiv1.Stack, appName string, job *workload.Job, ) (modules.Generator, error) { @@ -34,8 +33,8 @@ func NewJobGenerator( } func NewJobGeneratorFunc( - project *project.Project, - stack *stack.Stack, + project *apiv1.Project, + stack *apiv1.Stack, appName string, job *workload.Job, ) modules.NewGeneratorFunc { diff --git a/pkg/modules/generators/workload/job_generator_test.go b/pkg/modules/generators/workload/job_generator_test.go index d42a2f41c..de347154b 100644 --- a/pkg/modules/generators/workload/job_generator_test.go +++ b/pkg/modules/generators/workload/job_generator_test.go @@ -6,20 +6,17 @@ import ( "github.com/stretchr/testify/assert" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/modules" "kusionstack.io/kusion/pkg/modules/inputs/workload" ) func TestNewJobGenerator(t *testing.T) { - expectedProject := &project.Project{ - Configuration: project.Configuration{ - Name: "test", - }, + expectedProject := &apiv1.Project{ + Name: "test", } - expectedStack := &stack.Stack{} + expectedStack := &apiv1.Stack{} expectedAppName := "test" expectedJob := &workload.Job{} actual, err := NewJobGenerator(expectedProject, expectedStack, expectedAppName, expectedJob) @@ -33,12 +30,10 @@ func TestNewJobGenerator(t *testing.T) { } func TestNewJobGeneratorFunc(t *testing.T) { - expectedProject := &project.Project{ - Configuration: project.Configuration{ - Name: "test", - }, + expectedProject := &apiv1.Project{ + Name: "test", } - expectedStack := &stack.Stack{} + expectedStack := &apiv1.Stack{} expectedAppName := "test" expectedJob := &workload.Job{} generatorFunc := NewJobGeneratorFunc(expectedProject, expectedStack, expectedAppName, expectedJob) @@ -55,19 +50,17 @@ func TestNewJobGeneratorFunc(t *testing.T) { func TestJobGenerator_Generate(t *testing.T) { testCases := []struct { name string - expectedProject *project.Project - expectedStack *stack.Stack + expectedProject *apiv1.Project + expectedStack *apiv1.Stack expectedAppName string expectedJob *workload.Job }{ { name: "test generate", - expectedProject: &project.Project{ - Configuration: project.Configuration{ - Name: "test", - }, + expectedProject: &apiv1.Project{ + Name: "test", }, - expectedStack: &stack.Stack{}, + expectedStack: &apiv1.Stack{}, expectedAppName: "test", expectedJob: &workload.Job{}, }, diff --git a/pkg/modules/generators/workload/secret/secret_generator.go b/pkg/modules/generators/workload/secret/secret_generator.go index 585dd5452..9a630cdf7 100644 --- a/pkg/modules/generators/workload/secret/secret_generator.go +++ b/pkg/modules/generators/workload/secret/secret_generator.go @@ -7,19 +7,19 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" "kusionstack.io/kusion/pkg/modules" "kusionstack.io/kusion/pkg/modules/inputs/workload" ) type secretGenerator struct { - project *project.Project + project *apiv1.Project secrets map[string]workload.Secret } func NewSecretGenerator( - project *project.Project, + project *apiv1.Project, secrets map[string]workload.Secret, ) (modules.Generator, error) { if len(project.Name) == 0 { @@ -33,7 +33,7 @@ func NewSecretGenerator( } func NewSecretGeneratorFunc( - project *project.Project, + project *apiv1.Project, secrets map[string]workload.Secret, ) modules.NewGeneratorFunc { return func() (modules.Generator, error) { @@ -70,7 +70,7 @@ func (g *secretGenerator) Generate(spec *intent.Intent) error { // generateSecret generates target secret based on secret type. Most of these secret types are just semantic wrapper // of native Kubernetes secret types:https://kubernetes.io/docs/concepts/configuration/secret/#secret-types, and more // detailed usage info can be found in public documentation. -func generateSecret(project *project.Project, secretName string, secretRef workload.Secret) (*v1.Secret, error) { +func generateSecret(project *apiv1.Project, secretName string, secretRef workload.Secret) (*v1.Secret, error) { switch secretRef.Type { case "basic": return generateBasic(project, secretName, secretRef) @@ -87,7 +87,7 @@ func generateSecret(project *project.Project, secretName string, secretRef workl // generateBasic generates secret used for basic authentication. The basic secret type // is used for username / password pairs. -func generateBasic(project *project.Project, secretName string, secretRef workload.Secret) (*v1.Secret, error) { +func generateBasic(project *apiv1.Project, secretName string, secretRef workload.Secret) (*v1.Secret, error) { secret := &v1.Secret{ TypeMeta: metav1.TypeMeta{ APIVersion: v1.SchemeGroupVersion.String(), @@ -114,7 +114,7 @@ func generateBasic(project *project.Project, secretName string, secretRef worklo // generateToken generates secret used for password. Token secrets are useful for generating // a password or secure string used for passwords when the user is already known or not required. -func generateToken(project *project.Project, secretName string, secretRef workload.Secret) (*v1.Secret, error) { +func generateToken(project *apiv1.Project, secretName string, secretRef workload.Secret) (*v1.Secret, error) { secret := &v1.Secret{ TypeMeta: metav1.TypeMeta{ APIVersion: v1.SchemeGroupVersion.String(), @@ -138,7 +138,7 @@ func generateToken(project *project.Project, secretName string, secretRef worklo } // generateOpaque generates secret used for arbitrary user-defined data. -func generateOpaque(project *project.Project, secretName string, secretRef workload.Secret) (*v1.Secret, error) { +func generateOpaque(project *apiv1.Project, secretName string, secretRef workload.Secret) (*v1.Secret, error) { secret := &v1.Secret{ TypeMeta: metav1.TypeMeta{ APIVersion: v1.SchemeGroupVersion.String(), @@ -159,7 +159,7 @@ func generateOpaque(project *project.Project, secretName string, secretRef workl // generateCertificate generates secret used for storing a certificate and its associated key. // One common use for TLS Secrets is to configure encryption in transit for an Ingress, but // you can also use it with other resources or directly in your workload. -func generateCertificate(project *project.Project, secretName string, secretRef workload.Secret) (*v1.Secret, error) { +func generateCertificate(project *apiv1.Project, secretName string, secretRef workload.Secret) (*v1.Secret, error) { secret := &v1.Secret{ TypeMeta: metav1.TypeMeta{ APIVersion: v1.SchemeGroupVersion.String(), diff --git a/pkg/modules/generators/workload/secret/secret_generator_test.go b/pkg/modules/generators/workload/secret/secret_generator_test.go index 7b7e04f3b..6c1910ab5 100644 --- a/pkg/modules/generators/workload/secret/secret_generator_test.go +++ b/pkg/modules/generators/workload/secret/secret_generator_test.go @@ -5,8 +5,8 @@ import ( "github.com/stretchr/testify/require" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" "kusionstack.io/kusion/pkg/modules/inputs/workload" ) @@ -70,10 +70,8 @@ func TestGenerateSecret(t *testing.T) { }, } - project := &project.Project{ - Configuration: project.Configuration{ - Name: "helloworld", - }, + project := &apiv1.Project{ + Name: "helloworld", } // run all the tests for name, test := range tests { diff --git a/pkg/modules/generators/workload/service_generator.go b/pkg/modules/generators/workload/service_generator.go index 6e01ce5ea..1f8b1a6a9 100644 --- a/pkg/modules/generators/workload/service_generator.go +++ b/pkg/modules/generators/workload/service_generator.go @@ -8,9 +8,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "kusionstack.io/kube-api/apps/v1alpha1" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/modules" "kusionstack.io/kusion/pkg/modules/inputs/workload" @@ -19,16 +18,16 @@ import ( // workloadServiceGenerator is a struct for generating service workload resources. type workloadServiceGenerator struct { - project *project.Project - stack *stack.Stack + project *apiv1.Project + stack *apiv1.Stack appName string service *workload.Service } // NewWorkloadServiceGenerator returns a new workloadServiceGenerator instance. func NewWorkloadServiceGenerator( - project *project.Project, - stack *stack.Stack, + project *apiv1.Project, + stack *apiv1.Stack, appName string, service *workload.Service, ) (modules.Generator, error) { @@ -54,8 +53,8 @@ func NewWorkloadServiceGenerator( // NewWorkloadServiceGeneratorFunc returns a new NewGeneratorFunc that returns a workloadServiceGenerator instance. func NewWorkloadServiceGeneratorFunc( - project *project.Project, - stack *stack.Stack, + project *apiv1.Project, + stack *apiv1.Stack, appName string, service *workload.Service, ) modules.NewGeneratorFunc { diff --git a/pkg/modules/generators/workload/service_generator_test.go b/pkg/modules/generators/workload/service_generator_test.go index 0b214b157..bea4dfad6 100644 --- a/pkg/modules/generators/workload/service_generator_test.go +++ b/pkg/modules/generators/workload/service_generator_test.go @@ -6,9 +6,8 @@ import ( "github.com/stretchr/testify/require" "gopkg.in/yaml.v3" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/modules/inputs/workload" "kusionstack.io/kusion/pkg/modules/inputs/workload/container" "kusionstack.io/kusion/pkg/modules/inputs/workload/network" @@ -125,8 +124,8 @@ spec: status: {} ` type fields struct { - project *project.Project - stack *stack.Stack + project *apiv1.Project + stack *apiv1.Stack appName string service *workload.Service } @@ -144,14 +143,12 @@ status: {} { name: "CollaSet", fields: fields{ - project: &project.Project{ - Configuration: project.Configuration{ - Name: "default", - }, + project: &apiv1.Project{ + Name: "default", Path: "/test", }, - stack: &stack.Stack{ - Configuration: stack.Configuration{Name: "dev"}, + stack: &apiv1.Stack{ + Name: "dev", }, appName: "foo", service: &workload.Service{ @@ -189,14 +186,12 @@ status: {} { name: "Deployment", fields: fields{ - project: &project.Project{ - Configuration: project.Configuration{ - Name: "default", - }, + project: &apiv1.Project{ + Name: "default", Path: "/test", }, - stack: &stack.Stack{ - Configuration: stack.Configuration{Name: "dev"}, + stack: &apiv1.Stack{ + Name: "dev", }, appName: "foo", service: &workload.Service{ diff --git a/pkg/modules/generators/workload/workload_generator.go b/pkg/modules/generators/workload/workload_generator.go index 98d19b6d5..95361c280 100644 --- a/pkg/modules/generators/workload/workload_generator.go +++ b/pkg/modules/generators/workload/workload_generator.go @@ -14,9 +14,8 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/modules" "kusionstack.io/kusion/pkg/modules/inputs/workload" "kusionstack.io/kusion/pkg/modules/inputs/workload/container" @@ -26,15 +25,15 @@ import ( ) type workloadGenerator struct { - project *project.Project - stack *stack.Stack + project *apiv1.Project + stack *apiv1.Stack appName string workload *workload.Workload } func NewWorkloadGenerator( - project *project.Project, - stack *stack.Stack, + project *apiv1.Project, + stack *apiv1.Stack, appName string, workload *workload.Workload, ) (modules.Generator, error) { @@ -51,8 +50,8 @@ func NewWorkloadGenerator( } func NewWorkloadGeneratorFunc( - project *project.Project, - stack *stack.Stack, + project *apiv1.Project, + stack *apiv1.Stack, appName string, workload *workload.Workload, ) modules.NewGeneratorFunc { diff --git a/pkg/modules/generators/workload/workload_generator_test.go b/pkg/modules/generators/workload/workload_generator_test.go index e6e232ac4..6f565ad33 100644 --- a/pkg/modules/generators/workload/workload_generator_test.go +++ b/pkg/modules/generators/workload/workload_generator_test.go @@ -6,9 +6,8 @@ import ( "github.com/stretchr/testify/assert" "gopkg.in/yaml.v2" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" - "kusionstack.io/kusion/pkg/apis/stack" "kusionstack.io/kusion/pkg/modules" "kusionstack.io/kusion/pkg/modules/inputs/workload" "kusionstack.io/kusion/pkg/modules/inputs/workload/container" @@ -17,12 +16,10 @@ import ( func TestNewWorkloadGenerator(t *testing.T) { t.Run("NewWorkloadGenerator should return a valid generator", func(t *testing.T) { - expectedProject := &project.Project{ - Configuration: project.Configuration{ - Name: "test", - }, + expectedProject := &apiv1.Project{ + Name: "test", } - expectedStack := &stack.Stack{} + expectedStack := &apiv1.Stack{} expectedWorkload := &workload.Workload{} expectedAppName := "test" @@ -39,12 +36,10 @@ func TestNewWorkloadGenerator(t *testing.T) { func TestNewWorkloadGeneratorFunc(t *testing.T) { t.Run("NewWorkloadGeneratorFunc should return a valid generator function", func(t *testing.T) { - expectedProject := &project.Project{ - Configuration: project.Configuration{ - Name: "test", - }, + expectedProject := &apiv1.Project{ + Name: "test", } - expectedStack := &stack.Stack{} + expectedStack := &apiv1.Stack{} expectedWorkload := &workload.Workload{} expectedAppName := "test" @@ -101,19 +96,15 @@ func TestWorkloadGenerator_Generate(t *testing.T) { for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { - expectedProject := &project.Project{ - Configuration: project.Configuration{ - Name: "test", - Prometheus: &project.PrometheusConfig{ - OperatorMode: false, - MonitorType: "Pod", - }, + expectedProject := &apiv1.Project{ + Name: "test", + Prometheus: &apiv1.PrometheusConfig{ + OperatorMode: false, + MonitorType: "Pod", }, } - expectedStack := &stack.Stack{ - Configuration: stack.Configuration{ - Name: "teststack", - }, + expectedStack := &apiv1.Stack{ + Name: "teststack", } expectedAppName := "test" diff --git a/pkg/modules/patchers/monitoring/monitoring_patcher.go b/pkg/modules/patchers/monitoring/monitoring_patcher.go index 232bd4604..a8c5f0e47 100644 --- a/pkg/modules/patchers/monitoring/monitoring_patcher.go +++ b/pkg/modules/patchers/monitoring/monitoring_patcher.go @@ -5,8 +5,8 @@ import ( "kusionstack.io/kube-api/apps/v1alpha1" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" "kusionstack.io/kusion/pkg/modules" modelsapp "kusionstack.io/kusion/pkg/modules/inputs" ) @@ -14,11 +14,11 @@ import ( type monitoringPatcher struct { appName string app *modelsapp.AppConfiguration - project *project.Project + project *apiv1.Project } // NewMonitoringPatcher returns a Patcher. -func NewMonitoringPatcher(appName string, app *modelsapp.AppConfiguration, project *project.Project) (modules.Patcher, error) { +func NewMonitoringPatcher(appName string, app *modelsapp.AppConfiguration, project *apiv1.Project) (modules.Patcher, error) { return &monitoringPatcher{ appName: appName, app: app, @@ -27,7 +27,7 @@ func NewMonitoringPatcher(appName string, app *modelsapp.AppConfiguration, proje } // NewMonitoringPatcherFunc returns a NewPatcherFunc. -func NewMonitoringPatcherFunc(appName string, app *modelsapp.AppConfiguration, project *project.Project) modules.NewPatcherFunc { +func NewMonitoringPatcherFunc(appName string, app *modelsapp.AppConfiguration, project *apiv1.Project) modules.NewPatcherFunc { return func() (modules.Patcher, error) { return NewMonitoringPatcher(appName, app, project) } @@ -35,7 +35,7 @@ func NewMonitoringPatcherFunc(appName string, app *modelsapp.AppConfiguration, p // Patch implements Patcher interface. func (p *monitoringPatcher) Patch(resources map[string][]*intent.Resource) error { - if p.app.Monitoring == nil || p.project.Configuration.Prometheus == nil { + if p.app.Monitoring == nil || p.project.Prometheus == nil { return nil } @@ -53,7 +53,7 @@ func (p *monitoringPatcher) Patch(resources map[string][]*intent.Resource) error monitoringLabels := make(map[string]string) monitoringAnnotations := make(map[string]string) - if p.project.Configuration.Prometheus.OperatorMode { + if p.project.Prometheus.OperatorMode { monitoringLabels["kusion_monitoring_appname"] = p.appName } else { // If Prometheus doesn't run as an operator, kusion will generate the diff --git a/pkg/modules/patchers/monitoring/monitoring_patcher_test.go b/pkg/modules/patchers/monitoring/monitoring_patcher_test.go index 300b287c6..be799dbae 100644 --- a/pkg/modules/patchers/monitoring/monitoring_patcher_test.go +++ b/pkg/modules/patchers/monitoring/monitoring_patcher_test.go @@ -9,8 +9,8 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" + apiv1 "kusionstack.io/kusion/pkg/apis/core/v1" "kusionstack.io/kusion/pkg/apis/intent" - "kusionstack.io/kusion/pkg/apis/project" "kusionstack.io/kusion/pkg/modules" modelsapp "kusionstack.io/kusion/pkg/modules/inputs" "kusionstack.io/kusion/pkg/modules/inputs/monitoring" @@ -26,7 +26,7 @@ func Test_monitoringPatcher_Patch(t *testing.T) { type fields struct { appName string app *modelsapp.AppConfiguration - project *project.Project + project *apiv1.Project } type args struct { resources map[string][]*intent.Resource @@ -44,11 +44,9 @@ func Test_monitoringPatcher_Patch(t *testing.T) { app: &modelsapp.AppConfiguration{ Monitoring: &monitoring.Monitor{}, }, - project: &project.Project{ - Configuration: project.Configuration{ - Prometheus: &project.PrometheusConfig{ - OperatorMode: true, - }, + project: &apiv1.Project{ + Prometheus: &apiv1.PrometheusConfig{ + OperatorMode: true, }, }, }, @@ -64,11 +62,9 @@ func Test_monitoringPatcher_Patch(t *testing.T) { app: &modelsapp.AppConfiguration{ Monitoring: &monitoring.Monitor{}, }, - project: &project.Project{ - Configuration: project.Configuration{ - Prometheus: &project.PrometheusConfig{ - OperatorMode: false, - }, + project: &apiv1.Project{ + Prometheus: &apiv1.PrometheusConfig{ + OperatorMode: false, }, }, }, @@ -130,7 +126,7 @@ func TestNewMonitoringPatcherFunc(t *testing.T) { type args struct { appName string app *modelsapp.AppConfiguration - project *project.Project + project *apiv1.Project } tests := []struct { name string @@ -142,7 +138,7 @@ func TestNewMonitoringPatcherFunc(t *testing.T) { args: args{ appName: "test", app: &modelsapp.AppConfiguration{}, - project: &project.Project{}, + project: &apiv1.Project{}, }, }, } diff --git a/pkg/project/paths.go b/pkg/project/paths.go new file mode 100644 index 000000000..cb7940357 --- /dev/null +++ b/pkg/project/paths.go @@ -0,0 +1,238 @@ +package project + +import ( + "errors" + "fmt" + "io/fs" + "os" + "path/filepath" + + "github.com/pulumi/pulumi/sdk/v3/go/common/util/fsutil" + yamlv3 "gopkg.in/yaml.v3" + "k8s.io/apimachinery/pkg/util/sets" + + v1 "kusionstack.io/kusion/pkg/apis/core/v1" + "kusionstack.io/kusion/pkg/log" +) + +var ( + ErrNotProjectDirectory = errors.New("path must be a project directory") + ErrProjectNotUnique = errors.New("the project obtained is not unique") + ErrNotStackDirectory = errors.New("path must be a stack directory") + ErrStackNotUnique = errors.New("the stack obtained is not unique") +) + +const ( + ProjectFile = "project.yaml" + StackFile = "stack.yaml" +) + +// DetectProjectAndStack try to get stack and project from given path +func DetectProjectAndStack(stackDir string) (p *v1.Project, s *v1.Stack, err error) { + stackDir, err = filepath.Abs(stackDir) + if err != nil { + return nil, nil, err + } + + s, err = GetStackFrom(stackDir) + if err != nil { + return nil, nil, err + } + + projectDir, err := findProjectPathFrom(stackDir) + if err != nil { + return nil, nil, err + } + + p, err = getProjectFrom(projectDir) + if err != nil { + return nil, nil, err + } + + return p, s, nil +} + +// isProjectFile determine whether the given path is Project file +func isProjectFile(path string) bool { + f, err := os.Stat(path) + return err == nil && !f.IsDir() && f.Mode().IsRegular() && filepath.Base(path) == ProjectFile +} + +// isProject determine whether the given path is Project directory +func isProject(path string) bool { + f, err := os.Stat(path) + f2, err2 := os.Stat(filepath.Join(path, ProjectFile)) + + if (err == nil && f.IsDir()) && (err2 == nil && f2.Mode().IsRegular()) { + return true + } + + return false +} + +// getProjectFrom get project from the given path +func getProjectFrom(path string) (*v1.Project, error) { + if !isProject(path) { + return nil, ErrNotProjectDirectory + } + + projects, err := FindAllProjectsFrom(path) + if err != nil { + return nil, err + } + + if len(projects) != 1 { + return nil, ErrProjectNotUnique + } + + return projects[0], nil +} + +// findProjectPathFrom locates the closest project from the given path, searching "upwards" in the directory +// hierarchy. If no project is found, an empty path is returned. +func findProjectPathFrom(path string) (string, error) { + file, err := fsutil.WalkUp(path, isProjectFile, func(s string) bool { + return true + }) + if err != nil { + return "", err + } + + return filepath.Dir(file), nil +} + +// FindAllProjectsFrom find all project from the given path +func FindAllProjectsFrom(path string) ([]*v1.Project, error) { + var projects []*v1.Project + s := sets.NewString() + err := filepath.WalkDir(path, func(p string, _ fs.DirEntry, _ error) error { + if isProject(p) && !s.Has(p) { + // Parse project.yaml + project, err := parseProjectYamlFile(path) + if err != nil { + log.Error(err) + return fmt.Errorf("parse project.yaml failed. %w", err) + } + + // Find all stacks + stacks, err := FindAllStacksFrom(p) + if err != nil { + log.Error(err) + return fmt.Errorf("parse stacks failed. %w", err) + } + + // Get absolute path + absPath, err := filepath.Abs(p) + if err != nil { + log.Error(err) + return fmt.Errorf("project path failed. %w", err) + } + + project.Stacks = stacks + project.Path = absPath + projects = append(projects, project) + } + return nil + }) + + return projects, err +} + +// IsStack determine whether the given path is Stack directory +func IsStack(path string) bool { + f, err := os.Stat(path) + f2, err2 := os.Stat(filepath.Join(path, StackFile)) + + if (err == nil && f.IsDir()) && (err2 == nil && f2.Mode().IsRegular()) { + return true + } + + return false +} + +// GetStackFrom get stack from the given path +func GetStackFrom(path string) (*v1.Stack, error) { + if !IsStack(path) { + return nil, ErrNotStackDirectory + } + + stacks, err := FindAllStacksFrom(path) + if err != nil { + return nil, err + } + + if len(stacks) != 1 { + return nil, ErrStackNotUnique + } + + return stacks[0], nil +} + +// FindAllStacksFrom find all stacks from the given path +func FindAllStacksFrom(path string) ([]*v1.Stack, error) { + var stacks []*v1.Stack + s := sets.NewString() + _ = filepath.WalkDir(path, func(p string, _ fs.DirEntry, _ error) (err error) { + if IsStack(p) && !s.Has(p) { + // Parse stack.yaml + stack, err := parseStackYamlFile(p) + if err != nil { + log.Error(err) + return nil + } + + // Get absolute path + absPath, err := filepath.Abs(p) + if err != nil { + log.Error(err) + return nil + } + + stack.Path = absPath + stacks = append(stacks, stack) + } + + return nil + }) + + return stacks, nil +} + +// ParseProjectConfiguration parse the project configuration by the given directory +func parseProjectYamlFile(path string) (*v1.Project, error) { + var project v1.Project + + err := parseYamlFile(filepath.Join(path, ProjectFile), &project) + if err != nil { + return nil, err + } + + return &project, nil +} + +// parseStackConfiguration parse the stack configuration by the given directory +func parseStackYamlFile(path string) (*v1.Stack, error) { + var stack v1.Stack + + err := parseYamlFile(filepath.Join(path, StackFile), &stack) + if err != nil { + return nil, err + } + + return &stack, nil +} + +// Parse yaml data by file name +func parseYamlFile(filename string, target interface{}) error { + content, err := os.ReadFile(filename) + if err != nil { + return err + } + + err = yamlv3.Unmarshal(content, target) + if err != nil { + return err + } + + return nil +} diff --git a/pkg/project/paths_test.go b/pkg/project/paths_test.go new file mode 100644 index 000000000..28b221f6c --- /dev/null +++ b/pkg/project/paths_test.go @@ -0,0 +1,255 @@ +package project + +import ( + "errors" + "os" + "path/filepath" + "reflect" + "testing" + + "github.com/bytedance/mockey" + + "kusionstack.io/kusion/pkg/apis/core/v1" + "kusionstack.io/kusion/pkg/util/json" +) + +// merge project tests and stack tests together to reuse test data +var ( + // Inject into the TestMain + TestCurrentDir string + TestProjectPathA string + TestStackPathAA string + TestProjectPathB string + TestStackPathBA string + TestStackPathBB string + ErrFake = errors.New("fake error") +) + +const ( + TestProjectA string = "http-echo" + TestProjectB string = "nginx-example" + TestStackA string = "dev" + TestStackB string = "prod" +) + +func TestMain(m *testing.M) { + TestCurrentDir, _ = os.Getwd() + TestProjectPathA = filepath.Join("testdata", "appops", TestProjectA) + TestStackPathAA = filepath.Join("testdata", "appops", TestProjectA, TestStackA) + TestProjectPathB = filepath.Join("testdata", "appops", TestProjectB) + TestStackPathBA = filepath.Join("testdata", "appops", TestProjectB, TestStackA) + TestStackPathBB = filepath.Join("testdata", "appops", TestProjectB, TestStackB) + + os.Exit(m.Run()) +} + +func TestFindAllProjectsFrom(t *testing.T) { + type args struct { + path string + } + tests := []struct { + name string + args args + want []*v1.Project + wantErr bool + }{ + { + name: "given-project-path", + args: args{ + path: "./testdata/appops/http-echo", + }, + want: []*v1.Project{ + { + Name: TestProjectA, + Path: filepath.Join(TestCurrentDir, TestProjectPathA), + Stacks: []*v1.Stack{ + { + Name: TestStackA, + Path: filepath.Join(TestCurrentDir, TestStackPathAA), + }, + }, + }, + }, + wantErr: false, + }, + { + name: "give-project-path-with-two-stacks", + args: args{ + path: "./testdata/appops/nginx-example", + }, + want: []*v1.Project{ + { + Name: TestProjectB, + Path: filepath.Join(TestCurrentDir, TestProjectPathB), + Stacks: []*v1.Stack{ + { + Name: TestStackA, + Path: filepath.Join(TestCurrentDir, TestStackPathBA), + }, + { + Name: TestStackB, + Path: filepath.Join(TestCurrentDir, TestStackPathBB), + }, + }, + }, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := FindAllProjectsFrom(tt.args.path) + if (err != nil) != tt.wantErr { + t.Errorf("FindAllProjectsFrom() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("FindAllProjectsFrom() = %v, want %v", json.MustMarshal2PrettyString(got), json.MustMarshal2PrettyString(tt.want)) + } + }) + } +} + +func TestDetectProjectAndStack(t *testing.T) { + /*FakeProject := &v1.Project{ + Name: TestProjectA, + Path: filepath.Join(TestCurrentDir, TestProjectPathA), + Stacks: []*v1.Stack{ + { + Name: TestStackA, + Path: filepath.Join(TestCurrentDir, TestStackPathAA), + }, + }, + } + FakeStack := &v1.Stack{ + Name: TestStackA, + Path: filepath.Join(TestCurrentDir, TestStackPathAA), + }*/ + + type args struct { + stackDir string + } + tests := []struct { + name string + args args + project *v1.Project + stack *v1.Stack + wantErr bool + preRun func() + postRun func() + }{ + /*{ + name: "success", + args: args{ + stackDir: "./testdata/appops/http-echo/dev/", + }, + project: FakeProject, + stack: FakeStack, + wantErr: false, + preRun: func() {}, + postRun: func() {}, + },*/ + { + name: "fail-for-abs", + args: args{ + stackDir: "./testdata/appops/http-echo/dev/", + }, + project: nil, + stack: nil, + wantErr: true, + preRun: func() { + mockAbs("", ErrFake) + }, + postRun: func() {}, + }, + /*{ + name: "fail-for-GetStackFrom", + args: args{ + stackDir: "./testdata/appops/http-echo/dev/", + }, + project: nil, + stack: nil, + wantErr: true, + preRun: func() { + mockGetStackFrom(ErrFake) + }, + postRun: func() {}, + }, + { + name: "fail-for-FindProjectPathFrom", + args: args{ + stackDir: "./testdata/appops/http-echo/dev/", + }, + project: nil, + stack: nil, + wantErr: true, + preRun: func() { + mockFindProjectPathFrom("", ErrFake) + }, + postRun: func() {}, + }, + { + name: "fail-for-GetProjectFrom", + args: args{ + stackDir: "./testdata/appops/http-echo/dev/", + }, + project: nil, + stack: nil, + wantErr: true, + preRun: func() { + mockGetProjectFrom(ErrFake) + }, + postRun: func() {}, + },*/ + } + for _, tt := range tests { + mockey.PatchConvey(tt.name, t, func() { + tt.preRun() + project, stack, err := DetectProjectAndStack(tt.args.stackDir) + tt.postRun() + if (err != nil) != tt.wantErr { + t.Errorf("DetectProjectAndStack() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(project, tt.project) { + t.Errorf("DetectProjectAndStack() got = %v, want %v", project, tt.project) + } + if !reflect.DeepEqual(stack, tt.stack) { + t.Errorf("DetectProjectAndStack() gosuccess = %v, want %v", stack, tt.stack) + } + }) + } +} + +func mockAbs(mockAbs string, mockErr error) { + mockey.Mock(filepath.Abs).To(func(_ string) (string, error) { + return mockAbs, mockErr + }).Build() +} + +func mockGetStackFrom(mockErr error) { + mockey.Mock(GetStackFrom).To(func(_ string) (*v1.Stack, error) { + if mockErr == nil { + return &v1.Stack{}, nil + } + return nil, mockErr + }).Build() +} + +func mockGetProjectFrom(mockErr error) { + mockey.Mock(getProjectFrom).To(func(_ string) (*v1.Project, error) { + if mockErr == nil { + return &v1.Project{}, nil + } + return nil, mockErr + }).Build() +} + +func mockFindProjectPathFrom(mockProjectDir string, mockErr error) { + mockey.Mock(findProjectPathFrom).To(func(_ string) (string, error) { + if mockErr == nil { + return mockProjectDir, nil + } + return "", mockErr + }).Build() +} diff --git a/pkg/project/testdata/appops/empty-app/base/base.k b/pkg/project/testdata/appops/empty-app/base/base.k new file mode 100644 index 000000000..e69de29bb diff --git a/pkg/project/testdata/appops/empty-app/dev/ci-test/settings.yaml b/pkg/project/testdata/appops/empty-app/dev/ci-test/settings.yaml new file mode 100644 index 000000000..c3c9d4063 --- /dev/null +++ b/pkg/project/testdata/appops/empty-app/dev/ci-test/settings.yaml @@ -0,0 +1,3 @@ +kcl_options: + - key: cluster + value: default diff --git a/pkg/project/testdata/appops/empty-app/dev/kcl.yaml b/pkg/project/testdata/appops/empty-app/dev/kcl.yaml new file mode 100644 index 000000000..1744ec07e --- /dev/null +++ b/pkg/project/testdata/appops/empty-app/dev/kcl.yaml @@ -0,0 +1,5 @@ +# 当前文件记录编译出最终 YAML 所需要的文件,给平台侧使用,不建议修改和重命名,未来会和 ci-test 中的 settings.yaml 部分合并 +kcl_cli_configs: + file: + - ../base/base.k + - main.k diff --git a/pkg/project/testdata/appops/empty-app/dev/main.k b/pkg/project/testdata/appops/empty-app/dev/main.k new file mode 100644 index 000000000..e69de29bb diff --git a/pkg/project/testdata/appops/empty-app/dev/stack.yaml b/pkg/project/testdata/appops/empty-app/dev/stack.yaml new file mode 100644 index 000000000..1be7264fd --- /dev/null +++ b/pkg/project/testdata/appops/empty-app/dev/stack.yaml @@ -0,0 +1,2 @@ +# The stack basic info +name: dev diff --git a/pkg/project/testdata/appops/empty-app/project.yaml b/pkg/project/testdata/appops/empty-app/project.yaml new file mode 100644 index 000000000..fa7ddd963 --- /dev/null +++ b/pkg/project/testdata/appops/empty-app/project.yaml @@ -0,0 +1 @@ +name: empty-app diff --git a/pkg/project/testdata/appops/http-echo/README.md b/pkg/project/testdata/appops/http-echo/README.md new file mode 100644 index 000000000..9469bf881 --- /dev/null +++ b/pkg/project/testdata/appops/http-echo/README.md @@ -0,0 +1,51 @@ +# 前言 + +> 本 README.md 包括配置代码仓库目录/文件说明及如何本地使用 Kusion+Minikube 进行测试 + +## 快速开始 + +```bash +$ cd dev +$ kusion apply +SUCCESS Compiling in stack dev... + +Stack: dev Provider Type Name Plan + * ├─ kubernetes v1:Namespace http-echo Create + * ├─ kubernetes apps/v1:Deployment http-echodev Create + * ├─ kubernetes v1:Service apple-service Create + * └─ kubernetes networking.k8s.io/v1:Ingress example-ingress Create + +✔ yes +Start applying diffs...... +SUCCESS Creating Namespace/http-echo +SUCCESS Creating Deployment/http-echodev +SUCCESS Creating Service/apple-service +SUCCESS Creating Ingress/example-ingress + +Creating Ingress/example-ingress [4/4] ████████████████████████████████ 100% | 0s + +$ minikube service apple-service -n http-echo --url +http://192.168.99.102:30206 + +$ curl http://192.168.99.102:30206/apple +apple + +$ kusion destroy +``` + +## 目录和文件说明 + +```bash +. +├── base // 各环境通用配置 +│ ├── base.k // 应用的环境通用配置 +├── prod // 环境目录 +│ └── ci-test // ci 测试目录,放置测试脚本和数据 +│ └── settings.yaml // 测试数据和编译文件配置 +│ └── stdout.golden.yaml // 期望的 YAML,可通过 make 更新 +│ └── kcl.yaml // 当前 Stack 的多文件编译配置 +│ └── main.k // 应用在当前环境的配置清单 +│ └── stack.yaml // Stack 元信息 +└── project.yaml // Project 元信息 +└── README.md // 说明文档 +``` diff --git a/pkg/project/testdata/appops/http-echo/base/base.k b/pkg/project/testdata/appops/http-echo/base/base.k new file mode 100644 index 000000000..49e1de803 --- /dev/null +++ b/pkg/project/testdata/appops/http-echo/base/base.k @@ -0,0 +1,42 @@ +import base.pkg.kusion_models.kube.frontend +import base.pkg.kusion_models.kube.frontend.container +import base.pkg.kusion_models.kube.templates.resource as res_tpl +import base.pkg.kusion_models.kube.frontend.service +import base.pkg.kusion_models.kube.frontend.ingress + +# Application Configuration +appConfiguration: frontend.Server { + # Main Container Configuration + mainContainer = container.Main { + name = "apple-app" + args = ["-text=apple"] + } + image = "hashicorp/http-echo" + schedulingStrategy.resource = res_tpl.medium + services = [ + service.Service { + name = "apple-service" + type = "NodePort" + ports = [{port = 5678}] + } + ] + ingresses = [ + ingress.Ingress { + name = "example-ingress" + rules = [ + { + http.paths = [ + { + path = "/apple" + pathType = "Prefix" + backend.service = { + name = "app-service" + port = {number = 5678} + } + } + ] + } + ] + } + ] +} diff --git a/pkg/project/testdata/appops/http-echo/dev/ci-test/settings.yaml b/pkg/project/testdata/appops/http-echo/dev/ci-test/settings.yaml new file mode 100644 index 000000000..c3c9d4063 --- /dev/null +++ b/pkg/project/testdata/appops/http-echo/dev/ci-test/settings.yaml @@ -0,0 +1,3 @@ +kcl_options: + - key: cluster + value: default diff --git a/pkg/project/testdata/appops/http-echo/dev/kcl.yaml b/pkg/project/testdata/appops/http-echo/dev/kcl.yaml new file mode 100644 index 000000000..3c70a53f4 --- /dev/null +++ b/pkg/project/testdata/appops/http-echo/dev/kcl.yaml @@ -0,0 +1,7 @@ +# 当前文件记录编译出最终 YAML 所需要的文件,给平台侧使用,不建议修改和重命名,未来会和 ci-test 中的 settings.yaml 部分合并 +kcl_cli_configs: + file: + - ../../../base/pkg/kusion_models/kube/metadata/metadata.k + - ../base/base.k + - main.k + - ../../../base/pkg/kusion_models/kube/render/render.k diff --git a/pkg/project/testdata/appops/http-echo/dev/main.k b/pkg/project/testdata/appops/http-echo/dev/main.k new file mode 100644 index 000000000..18c1f91c8 --- /dev/null +++ b/pkg/project/testdata/appops/http-echo/dev/main.k @@ -0,0 +1,8 @@ +import base.pkg.kusion_models.kube.frontend +import base.pkg.kusion_models.kube.templates.resource as res_tpl + +# The application configuration in stack will overwrite +# the configuration with the same attribute in base. +appConfiguration: frontend.Server { + schedulingStrategy.resource = res_tpl.tiny +} diff --git a/pkg/project/testdata/appops/http-echo/dev/stack.yaml b/pkg/project/testdata/appops/http-echo/dev/stack.yaml new file mode 100644 index 000000000..1be7264fd --- /dev/null +++ b/pkg/project/testdata/appops/http-echo/dev/stack.yaml @@ -0,0 +1,2 @@ +# The stack basic info +name: dev diff --git a/pkg/project/testdata/appops/http-echo/project.yaml b/pkg/project/testdata/appops/http-echo/project.yaml new file mode 100644 index 000000000..d53a0be88 --- /dev/null +++ b/pkg/project/testdata/appops/http-echo/project.yaml @@ -0,0 +1,2 @@ +# The project basic info +name: http-echo diff --git a/pkg/project/testdata/appops/nginx-example/README.md b/pkg/project/testdata/appops/nginx-example/README.md new file mode 100644 index 000000000..eed78aaff --- /dev/null +++ b/pkg/project/testdata/appops/nginx-example/README.md @@ -0,0 +1,49 @@ +# 前言 + +> 本 README.md 包括配置代码仓库目录/文件说明及如何本地使用 Kusion+Minikube 进行测试 + +## 快速开始 + +```bash +$ cd dev +$ kusion apply +SUCCESS Compiling in stack dev... + +Stack: dev Provider Type Name Plan + * ├─ kubernetes v1:Namespace nginx-example Create + * ├─ kubernetes v1:Service nginx-example Create + * └─ kubernetes apps/v1:Deployment nginx-exampledev Create + +✔ yes +Start applying diffs...... +SUCCESS Creating Namespace/nginx-example +SUCCESS Creating Service/nginx-example +SUCCESS Creating Deployment/nginx-exampledev + +Creating Deployment/nginx-exampledev [3/3] ████████████████████████████████ 100% | 0s + +$ minikube service nginx-example -n nginx-example --url +http://192.168.99.102:30201 + +$ curl -s http://192.168.99.102:30201 | grep '' # Or visit http://192.168.99.102:30201 in browser +<title>Welcome to nginx! + +$ kusion destroy +``` + +## 目录和文件说明 + +```bash +. +├── base // 各环境通用配置 +│ ├── base.k // 应用的环境通用配置 +├── prod // 环境目录 +│ └── ci-test // ci 测试目录,放置测试脚本和数据 +│ └── settings.yaml // 测试数据和编译文件配置 +│ └── stdout.golden.yaml // 期望的 YAML,可通过 make 更新 +│ └── kcl.yaml // 当前 Stack 的多文件编译配置 +│ └── main.k // 应用在当前环境的配置清单 +│ └── stack.yaml // Stack 元信息 +└── project.yaml // Project 元信息 +└── README.md // 说明文档 +``` diff --git a/pkg/project/testdata/appops/nginx-example/base/base.k b/pkg/project/testdata/appops/nginx-example/base/base.k new file mode 100644 index 000000000..44cb0546b --- /dev/null +++ b/pkg/project/testdata/appops/nginx-example/base/base.k @@ -0,0 +1,28 @@ +import base.pkg.kusion_models.kube.frontend +import base.pkg.kusion_models.kube.frontend.service +import base.pkg.kusion_models.kube.frontend.container +import base.pkg.kusion_models.kube.templates.resource as res_tpl + +# Application Configuration +appConfiguration: frontend.Server { + # Main Container Configuration + mainContainer = container.Main { + ports = [ + {containerPort = 80} + ] + } + image = "nginx:1.7.8" + services = [ + service.Service { + name = __META_APP_NAME + type = "NodePort" + ports = [ + { + nodePort = 30201 + port = 80 + targetPort = 80 + } + ] + } + ] +} diff --git a/pkg/project/testdata/appops/nginx-example/dev/ci-test/settings.yaml b/pkg/project/testdata/appops/nginx-example/dev/ci-test/settings.yaml new file mode 100644 index 000000000..c3c9d4063 --- /dev/null +++ b/pkg/project/testdata/appops/nginx-example/dev/ci-test/settings.yaml @@ -0,0 +1,3 @@ +kcl_options: + - key: cluster + value: default diff --git a/pkg/project/testdata/appops/nginx-example/dev/kcl.yaml b/pkg/project/testdata/appops/nginx-example/dev/kcl.yaml new file mode 100644 index 000000000..4aa3062d6 --- /dev/null +++ b/pkg/project/testdata/appops/nginx-example/dev/kcl.yaml @@ -0,0 +1,7 @@ +# 当前文件记录编译出最终 YAML 所需要的文件,给平台侧使用,不建议修改和重命名,未来会和 ci-test 中的 settings.yaml 部分合并 +kcl_cli_configs: + file: + - ../../../base/pkg/kusion_models/kube/metadata/metadata.k + - ../base/base.k + - ./main.k + - ../../../base/pkg/kusion_models/kube/render/render.k diff --git a/pkg/project/testdata/appops/nginx-example/dev/main.k b/pkg/project/testdata/appops/nginx-example/dev/main.k new file mode 100644 index 000000000..18c1f91c8 --- /dev/null +++ b/pkg/project/testdata/appops/nginx-example/dev/main.k @@ -0,0 +1,8 @@ +import base.pkg.kusion_models.kube.frontend +import base.pkg.kusion_models.kube.templates.resource as res_tpl + +# The application configuration in stack will overwrite +# the configuration with the same attribute in base. +appConfiguration: frontend.Server { + schedulingStrategy.resource = res_tpl.tiny +} diff --git a/pkg/project/testdata/appops/nginx-example/dev/stack.yaml b/pkg/project/testdata/appops/nginx-example/dev/stack.yaml new file mode 100644 index 000000000..1be7264fd --- /dev/null +++ b/pkg/project/testdata/appops/nginx-example/dev/stack.yaml @@ -0,0 +1,2 @@ +# The stack basic info +name: dev diff --git a/pkg/project/testdata/appops/nginx-example/prod/ci-test/settings.yaml b/pkg/project/testdata/appops/nginx-example/prod/ci-test/settings.yaml new file mode 100644 index 000000000..c3c9d4063 --- /dev/null +++ b/pkg/project/testdata/appops/nginx-example/prod/ci-test/settings.yaml @@ -0,0 +1,3 @@ +kcl_options: + - key: cluster + value: default diff --git a/pkg/project/testdata/appops/nginx-example/prod/kcl.yaml b/pkg/project/testdata/appops/nginx-example/prod/kcl.yaml new file mode 100644 index 000000000..4aa3062d6 --- /dev/null +++ b/pkg/project/testdata/appops/nginx-example/prod/kcl.yaml @@ -0,0 +1,7 @@ +# 当前文件记录编译出最终 YAML 所需要的文件,给平台侧使用,不建议修改和重命名,未来会和 ci-test 中的 settings.yaml 部分合并 +kcl_cli_configs: + file: + - ../../../base/pkg/kusion_models/kube/metadata/metadata.k + - ../base/base.k + - ./main.k + - ../../../base/pkg/kusion_models/kube/render/render.k diff --git a/pkg/project/testdata/appops/nginx-example/prod/main.k b/pkg/project/testdata/appops/nginx-example/prod/main.k new file mode 100644 index 000000000..18c1f91c8 --- /dev/null +++ b/pkg/project/testdata/appops/nginx-example/prod/main.k @@ -0,0 +1,8 @@ +import base.pkg.kusion_models.kube.frontend +import base.pkg.kusion_models.kube.templates.resource as res_tpl + +# The application configuration in stack will overwrite +# the configuration with the same attribute in base. +appConfiguration: frontend.Server { + schedulingStrategy.resource = res_tpl.tiny +} diff --git a/pkg/project/testdata/appops/nginx-example/prod/stack.yaml b/pkg/project/testdata/appops/nginx-example/prod/stack.yaml new file mode 100644 index 000000000..556177336 --- /dev/null +++ b/pkg/project/testdata/appops/nginx-example/prod/stack.yaml @@ -0,0 +1,2 @@ +# The stack basic info +name: prod diff --git a/pkg/project/testdata/appops/nginx-example/project.yaml b/pkg/project/testdata/appops/nginx-example/project.yaml new file mode 100644 index 000000000..534895980 --- /dev/null +++ b/pkg/project/testdata/appops/nginx-example/project.yaml @@ -0,0 +1,2 @@ +# The project basic info +name: nginx-example diff --git a/pkg/project/testdata/kcl.mod b/pkg/project/testdata/kcl.mod new file mode 100644 index 000000000..e7b94bfa7 --- /dev/null +++ b/pkg/project/testdata/kcl.mod @@ -0,0 +1,6 @@ +[build] +enable_pkg_cache=true +cached_pkg_prefix="base.pkg." +[expected] +kclvm_version="v0.3.9" +kcl_plugin_version="v0.2.14"