Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support deleted files in kusion deps cmd #96

Merged
merged 9 commits into from
Jul 18, 2022
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ require (
k8s.io/component-base v0.21.2
k8s.io/kubectl v0.21.2
kusionstack.io/kcl-plugin v0.4.1-alpha2
kusionstack.io/kclvm-go v0.4.2-alpha.9
kusionstack.io/kclvm-go v0.4.3-alpha.1
sigs.k8s.io/kustomize/api v0.8.11
sigs.k8s.io/kustomize/kustomize/v4 v4.1.2
sigs.k8s.io/kustomize/kyaml v0.11.0
Expand Down
6 changes: 2 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -205,8 +205,6 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/daviddengcn/go-colortext v0.0.0-20160507010035-511bcaf42ccd/go.mod h1:dv4zxwHi5C/8AeI+4gX4dCWOIvNi7I6JCSX0HvlKPgE=
github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4=
github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/didi/gendry v1.7.0 h1:dFR6+TVCnbjvLfNiGN53xInG/C5HqG7u0gfnkF5J/Vo=
Expand Down Expand Up @@ -1350,8 +1348,8 @@ k8s.io/utils v0.0.0-20201110183641-67b214c5f920 h1:CbnUZsM497iRC5QMVkHwyl8s2tB3g
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
kusionstack.io/kcl-plugin v0.4.1-alpha2 h1:m43JJhpJSjl/Q3FqghJf5dRIwdXsrJeKxrHhgqLJqbA=
kusionstack.io/kcl-plugin v0.4.1-alpha2/go.mod h1:VgB7qXVbDGWFOh/qb/yXf75+UrliP5EPXOQUDqBCdAQ=
kusionstack.io/kclvm-go v0.4.2-alpha.9 h1:c4mDJFlKuP3CbGTtEkFEQidxcsJpGHNCDBtv7eexlH8=
kusionstack.io/kclvm-go v0.4.2-alpha.9/go.mod h1:LKGVud6Ch0dLLACwPqZQyU4E+NkLAXzveJFQWVb5Pbk=
kusionstack.io/kclvm-go v0.4.3-alpha.1 h1:wHrTajwtT28e0gpfSk6gkmJLiUHx5vCimS5J0B+89W8=
kusionstack.io/kclvm-go v0.4.3-alpha.1/go.mod h1:cxsYIWWMiDk7mwWJMm6H9kzNNtoIpOQHgzJBZvHThzo=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
Expand Down
292 changes: 292 additions & 0 deletions pkg/kusionctl/cmd/deps/deps_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,292 @@
package deps

import (
"fmt"
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/assert"
"kusionstack.io/kusion/pkg/projectstack"
)

var workDir string

func init() {
cwd, err := os.Getwd()
if err != nil {
os.Exit(1)
}
workDir = filepath.Join(cwd, "testdata")
}

func TestNewCmdDeps(t *testing.T) {
cmd := NewCmdDeps()
if err := cmd.Execute(); err == nil {
t.Fatal(err)
}
}

func TestDepsOptions_Validate(t *testing.T) {
tCases := []struct {
name string
only string
direct string
workDir string
focus []string
ignore []string
errMsg string
}{

{
name: "invalid output filter",
errMsg: "invalid output downstream type. supported types: project, stack",
},
{
name: "invalid direct",
only: "project",
errMsg: "invalid output direction of the dependency inspection. supported directions: up, down",
},
{
name: "invalid workdir",
only: "project",
direct: "up",
errMsg: "invalid work dir: stat : no such file or directory",
},
{
name: "invalid focus",
only: "project",
direct: "up",
workDir: workDir,
errMsg: "invalid focus paths. cannot be empty",
},
{
name: "invalid ignore",
only: "project",
direct: "up",
workDir: workDir,
focus: []string{"file.k"},
ignore: []string{"invalid_path.k"},
errMsg: fmt.Sprintf("invalid ignore path. need to be valid relative path from the workdir: stat %s: no such file or directory", filepath.Join(workDir, "invalid_path.k")),
},
{
name: "valid",
only: "project",
direct: "up",
workDir: workDir,
focus: []string{"file.k"},
errMsg: "",
},
}
for _, tc := range tCases {
t.Run(tc.name, func(t *testing.T) {
opt := DepsOptions{
workDir: tc.workDir,
Direct: tc.direct,
Only: tc.only,
Focus: tc.focus,
Ignore: tc.ignore,
}
err := opt.Validate()
if err != nil && err.Error() != tc.errMsg {
t.Fatalf("wrong validate errMsg, actual: %s, expect: %s", err.Error(), tc.errMsg)
}
if err == nil && tc.errMsg != "" {
t.Fatalf("wrong validate result: actual: validate success, expect err: %s", tc.errMsg)
}
})
}
}

func TestDepsOptions_Complete(t *testing.T) {
tCases := []struct {
name string
args []string
completed string
}{
{
name: "omit workdir in args",
completed: filepath.Dir(workDir),
},
{
name: "specify workdir in args",
args: []string{"workdir path"},
completed: "workdir path",
},
}
for _, tc := range tCases {
t.Run(tc.name, func(t *testing.T) {
opt := NewDepsOptions()
opt.Complete(tc.args)
if opt.workDir != tc.completed {
t.Fatalf("wrong completed workdir, actual: %s, expect: %s", opt.workDir, tc.completed)
}
})
}
}

func TestDepsOptions_Run(t *testing.T) {
tCases := []struct {
workDir string
direct string
only string
}{
{
workDir: workDir,
direct: "up",
},
{
workDir: workDir,
direct: "down",
only: "project",
},
}
for _, tc := range tCases {
t.Run(tc.direct, func(t *testing.T) {
opt := DepsOptions{
workDir: tc.workDir,
Direct: tc.direct,
Only: tc.only,
}
if err := opt.Run(); err != nil {
t.Fatal(err)
}
})
}
}

func TestDepsOptions_Run2(t *testing.T) {
opt := DepsOptions{
workDir: workDir,
Direct: "up",
Focus: []string{
"appops/projectC/dev/main.k",
},
}
err := opt.Run()
if err != nil {
t.Fatal(err)
}
}

var downstreamTestCases = []struct {
name string
focus []string
downStreamProjects []string
ignore []string
}{
{
name: "change base and entrance files",
focus: []string{
"base/frontend/container/container_port.k",
"appops/projectA/base/base.k",
"appops/projectA/dev/main.k",
"appops/projectA/dev/datafile.sql",
},
downStreamProjects: []string{
"appops/projectA",
"appops/projectB",
"appops/projectC",
},
},
{
name: "change common base: container port",
focus: []string{"base/frontend/container/container_port.k"},
downStreamProjects: []string{
"appops/projectA",
"appops/projectB",
"appops/projectC",
},
},
{
name: "change server render base",
focus: []string{"base/render/server/server_render.k"},
downStreamProjects: []string{
"appops/projectA",
"appops/projectC",
},
},
{
name: "change job render base",
focus: []string{"base/render/job/job_render.k"},
downStreamProjects: []string{
"appops/projectB",
},
},
{
name: "ignore job render base",
focus: []string{
"base/render/server/server_render.k",
"base/render/job/job_render.k",
},
ignore: []string{
"base/render/job/job_render.k",
},
downStreamProjects: []string{
"appops/projectA",
"appops/projectC",
},
},
{
name: "only change entrance files",
focus: []string{
"appops/projectA/base/base.k",
"appops/projectA/dev/main.k",
"appops/projectB/dev/main.k",
},
downStreamProjects: []string{
"appops/projectA",
"appops/projectB",
},
},
{
name: "only change data files",
focus: []string{
"appops/projectA/dev/datafile.sql",
},
downStreamProjects: []string{
"appops/projectA",
},
},
{
name: "delete files",
focus: []string{
"appops/projectC/dev/non_exist.sql",
"base/frontend/non_exist/non_exist.k",
},
downStreamProjects: []string{
"appops/projectC",
},
},
}

func TestFindDownStreams(t *testing.T) {
projects, err := projectstack.FindAllProjectsFrom(workDir)
if err != nil {
t.Fatal(err)
}
for _, tc := range downstreamTestCases {
t.Run(tc.name, func(t *testing.T) {
result, err := findDownStreams(workDir, projects, toSet(tc.focus), toSet(tc.ignore), true)
if err != nil {
t.Fatal(err)
}
assert.ElementsMatch(t, result.toSlice(), tc.downStreamProjects, "test result mismatch")
})
}
}

func BenchmarkDownStream(b *testing.B) {
tc := downstreamTestCases[0]
for i := 0; i < b.N; i++ {
projects, err := projectstack.FindAllProjectsFrom(workDir)
if err != nil {
b.Fatal(err)
}
result, err := findDownStreams(workDir, projects, toSet(tc.focus), toSet(tc.ignore), true)
if err != nil {
b.Fatal(err)
}
assert.ElementsMatch(b, result.toSlice(), tc.downStreamProjects, "test result mismatch")
}
}
Loading