diff --git a/pkg/client/client.go b/pkg/client/client.go index 348bc643..122b96c3 100644 --- a/pkg/client/client.go +++ b/pkg/client/client.go @@ -19,6 +19,7 @@ import ( "oras.land/oras-go/v2" remoteauth "oras.land/oras-go/v2/registry/remote/auth" + "kcl-lang.io/kpm/pkg/checker" "kcl-lang.io/kpm/pkg/constants" "kcl-lang.io/kpm/pkg/downloader" "kcl-lang.io/kpm/pkg/env" @@ -47,6 +48,8 @@ type KpmClient struct { homePath string // The settings of kpm loaded from the global configuration file. settings settings.Settings + // The checker to validate dependencies + DepChecker *checker.DepChecker // The flag of whether to check the checksum of the package and update kcl.mod.lock. noSumCheck bool // The flag of whether to skip the verification of TLS. @@ -66,10 +69,16 @@ func NewKpmClient() (*KpmClient, error) { return nil, err } + depChecker := checker.NewDepChecker( + checker.WithCheckers(checker.NewIdentChecker(), checker.NewVersionChecker(), checker.NewSumChecker( + checker.WithSettings(*settings))), + ) + return &KpmClient{ logWriter: os.Stdout, settings: *settings, homePath: homePath, + DepChecker: depChecker, DepDownloader: &downloader.DepDownloader{}, }, nil } @@ -897,16 +906,11 @@ func (c *KpmClient) Download(dep *pkg.Dependency, homePath, localPath string) (* } dep.FromKclPkg(dpkg) - dep.Sum, err = c.AcquireDepSum(*dep) + + dep.Sum, err = utils.HashDir(localPath) if err != nil { return nil, err } - if dep.Sum == "" { - dep.Sum, err = utils.HashDir(localPath) - if err != nil { - return nil, err - } - } if dep.LocalFullPath == "" { dep.LocalFullPath = localPath @@ -926,6 +930,9 @@ func (c *KpmClient) Download(dep *pkg.Dependency, homePath, localPath string) (* // if err != nil { // return nil, err // } + if err := c.ValidateDependency(dep); err != nil { + return nil, err + } } if dep.Source.Local != nil { @@ -939,6 +946,24 @@ func (c *KpmClient) Download(dep *pkg.Dependency, homePath, localPath string) (* return dep, nil } +func (c *KpmClient) ValidateDependency(dep *pkg.Dependency) error { + tmpKclPkg := pkg.KclPkg{ + HomePath: dep.LocalFullPath, + Dependencies: pkg.Dependencies{Deps: func() *orderedmap.OrderedMap[string, pkg.Dependency] { + m := orderedmap.NewOrderedMap[string, pkg.Dependency]() + m.Set(dep.Name, *dep) + return m + }()}, + NoSumCheck: c.GetNoSumCheck(), + } + + if err := c.DepChecker.Check(tmpKclPkg); err != nil { + return reporter.NewErrorEvent(reporter.InvalidKclPkg, err, fmt.Sprintf("%s package does not match the original kcl package", dep.FullName)) + } + + return nil +} + // DownloadFromGit will download the dependency from the git repository. func (c *KpmClient) DownloadFromGit(dep *downloader.Git, localPath string) (string, error) { var msg string @@ -1148,6 +1173,14 @@ func (c *KpmClient) PullFromOci(localPath, source, tag string) error { ) } + if err := c.ValidatePkgPullFromOci(ociOpts, storagePath); err != nil { + return reporter.NewErrorEvent( + reporter.InvalidKclPkg, + err, + fmt.Sprintf("failed to validate kclPkg at %s", storagePath), + ) + } + reporter.ReportMsgTo( fmt.Sprintf("pulled '%s' in '%s' successfully", source, storagePath), c.logWriter, @@ -1155,6 +1188,42 @@ func (c *KpmClient) PullFromOci(localPath, source, tag string) error { return nil } +func (c *KpmClient) ValidatePkgPullFromOci(ociOpts *opt.OciOptions, storagePath string) error { + kclPkg, err := c.LoadPkgFromPath(storagePath) + if err != nil { + return reporter.NewErrorEvent( + reporter.FailedGetPkg, + err, + fmt.Sprintf("failed to load kclPkg at %v", storagePath), + ) + } + + dep := &pkg.Dependency{ + Name: kclPkg.GetPkgName(), + Source: downloader.Source{ + Oci: &downloader.Oci{ + Reg: ociOpts.Reg, + Repo: ociOpts.Repo, + Tag: ociOpts.Tag, + }, + }, + } + + dep.FromKclPkg(kclPkg) + dep.Sum, err = utils.HashDir(storagePath) + if err != nil { + return reporter.NewErrorEvent( + reporter.FailedHashPkg, + err, + fmt.Sprintf("failed to hash kclPkg - %s", dep.Name), + ) + } + if err := c.ValidateDependency(dep); err != nil { + return err + } + return nil +} + // PushToOci will push a kcl package to oci registry. func (c *KpmClient) PushToOci(localPath string, ociOpts *opt.OciOptions) error { repoPath := utils.JoinPath(ociOpts.Reg, ociOpts.Repo) @@ -1525,6 +1594,8 @@ func (c *KpmClient) pullTarFromOci(localPath string, ociOpts *opt.OciOptions) er tagSelected = ociOpts.Tag } + ociOpts.Tag = tagSelected + full_repo := utils.JoinPath(ociOpts.Reg, ociOpts.Repo) reporter.ReportMsgTo( fmt.Sprintf("pulling '%s:%s' from '%s'", ociOpts.Repo, tagSelected, full_repo), diff --git a/test/e2e/test_suites/kpm/exec_outside_pkg/kpm_pull_with_oci_url/test_suite.stdout b/test/e2e/test_suites/kpm/exec_outside_pkg/kpm_pull_with_oci_url/test_suite.stdout index 2ba91f02..b6cf454b 100644 --- a/test/e2e/test_suites/kpm/exec_outside_pkg/kpm_pull_with_oci_url/test_suite.stdout +++ b/test/e2e/test_suites/kpm/exec_outside_pkg/kpm_pull_with_oci_url/test_suite.stdout @@ -1,4 +1,4 @@ start to pull 'oci://localhost:5001/test/k8s' the latest version '1.31.2' will be pulled pulling '/test/k8s:1.31.2' from 'localhost:5001/test/k8s' -pulled 'oci://localhost:5001/test/k8s' in '/localhost:5001/test/k8s' successfully \ No newline at end of file +pulled 'oci://localhost:5001/test/k8s' in '/localhost:5001/test/k8s/1.31.2' successfully \ No newline at end of file diff --git a/test/e2e/test_suites/kpm/exec_outside_pkg/kpm_pull_with_pkg_name/test_suite.stdout b/test/e2e/test_suites/kpm/exec_outside_pkg/kpm_pull_with_pkg_name/test_suite.stdout index e0d56638..b3c6f155 100644 --- a/test/e2e/test_suites/kpm/exec_outside_pkg/kpm_pull_with_pkg_name/test_suite.stdout +++ b/test/e2e/test_suites/kpm/exec_outside_pkg/kpm_pull_with_pkg_name/test_suite.stdout @@ -1,4 +1,4 @@ start to pull 'k8s' the latest version '1.31.2' will be pulled pulling 'test/k8s:1.31.2' from 'localhost:5001/test/k8s' -pulled 'k8s' in '/localhost:5001/test/k8s' successfully \ No newline at end of file +pulled 'k8s' in '/localhost:5001/test/k8s/1.31.2' successfully \ No newline at end of file diff --git a/test/e2e/test_suites/kpm/exec_outside_pkg/pull_private_pkg/test_suite.stdout b/test/e2e/test_suites/kpm/exec_outside_pkg/pull_private_pkg/test_suite.stdout index e4629312..2d980a93 100644 --- a/test/e2e/test_suites/kpm/exec_outside_pkg/pull_private_pkg/test_suite.stdout +++ b/test/e2e/test_suites/kpm/exec_outside_pkg/pull_private_pkg/test_suite.stdout @@ -1,4 +1,4 @@ start to pull 'oci://localhost:5001/test/helloworld' the latest version '0.1.2' will be pulled pulling '/test/helloworld:0.1.2' from 'localhost:5001/test/helloworld' -pulled 'oci://localhost:5001/test/helloworld' in '/localhost:5001/test/helloworld' successfully \ No newline at end of file +pulled 'oci://localhost:5001/test/helloworld' in '/localhost:5001/test/helloworld/0.1.2' successfully \ No newline at end of file