diff --git a/cli/cli/go.mod b/cli/cli/go.mod index fba601c46b..162300c783 100644 --- a/cli/cli/go.mod +++ b/cli/cli/go.mod @@ -55,7 +55,6 @@ require ( github.com/mholt/archiver v3.1.1+incompatible github.com/xlab/treeprint v1.2.0 golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 - gopkg.in/segmentio/analytics-go.v3 v3.1.0 k8s.io/api v0.27.2 ) diff --git a/core/server/api_container/server/startosis_engine/startosis_packages/git_package_content_provider/git_package_content_provider.go b/core/server/api_container/server/startosis_engine/startosis_packages/git_package_content_provider/git_package_content_provider.go index 177d5cc34d..a541e4befe 100644 --- a/core/server/api_container/server/startosis_engine/startosis_packages/git_package_content_provider/git_package_content_provider.go +++ b/core/server/api_container/server/startosis_engine/startosis_packages/git_package_content_provider/git_package_content_provider.go @@ -53,7 +53,11 @@ func NewGitPackageContentProvider(moduleDir string, tmpDir string, enclaveDb *en return &GitPackageContentProvider{ packagesDir: moduleDir, packagesTmpDir: tmpDir, +<<<<<<< HEAD packageReplaceOptionsRepository: NewPackageReplaceOptionsRepository(enclaveDb), +======= + packageReplaceOptionsRepository: newPackageReplaceOptionsRepository(enclaveDb), +>>>>>>> d5e312690 (feat: local replace package dependency (#1521)) } } @@ -212,7 +216,7 @@ func (provider *GitPackageContentProvider) GetAbsoluteLocatorForRelativeLocator( ) (string, *startosis_errors.InterpretationError) { var absoluteLocator string - if isLocalAbsoluteLocator(maybeRelativeLocator, parentModuleId) { + if isSamePackageLocalAbsoluteLocator(maybeRelativeLocator, parentModuleId) { return "", startosis_errors.NewInterpretationError("The locator '%s' set in attribute is not a 'local relative locator'. Local absolute locators are not allowed you should modified it to be a valid 'local relative locator'", maybeRelativeLocator) } @@ -236,6 +240,7 @@ func (provider *GitPackageContentProvider) GetAbsoluteLocatorForRelativeLocator( func (provider *GitPackageContentProvider) CloneReplacedPackagesIfNeeded(currentPackageReplaceOptions map[string]string) *startosis_errors.InterpretationError { +<<<<<<< HEAD historicalPackageReplaceOptions, err := provider.packageReplaceOptionsRepository.Get() if err != nil { return startosis_errors.WrapWithInterpretationError(err, "An error occurred getting the historical package replace options from the repository") @@ -254,12 +259,36 @@ func (provider *GitPackageContentProvider) CloneReplacedPackagesIfNeeded(current isCurrentRemoteReplace := !isLocalDependencyReplace(currentReplace) logrus.Debugf("currentReplace '%v' isCurrentRemoteReplace? '%v', ", isCurrentRemoteReplace, currentReplace) if isCurrentRemoteReplace && isHistoricalLocalReplace { +======= + existingPackageReplaceOptions, err := provider.packageReplaceOptionsRepository.Get() + if err != nil { + return startosis_errors.WrapWithInterpretationError(err, "An error occurred getting the existing package replace options from the repository") + } + + for packageId, existingReplace := range existingPackageReplaceOptions { + + shouldClonePackage := false + + isExistingLocalReplace := isLocalLocator(existingReplace) + logrus.Debugf("existingReplace '%v' isExistingLocalReplace? '%v', ", existingReplace, isExistingLocalReplace) + + currentReplace, isCurrentReplace := currentPackageReplaceOptions[packageId] + if isCurrentReplace { + // the package will be cloned if the current replace is remote and the existing is local + isCurrentRemoteReplace := !isLocalLocator(currentReplace) + logrus.Debugf("currentReplace '%v' isCurrentRemoteReplace? '%v', ", isCurrentRemoteReplace, currentReplace) + if isCurrentRemoteReplace && isExistingLocalReplace { +>>>>>>> d5e312690 (feat: local replace package dependency (#1521)) shouldClonePackage = true } } // there is no current replace for this dependency but the version in the cache is local +<<<<<<< HEAD if !isCurrentReplace && isHistoricalLocalReplace { +======= + if !isCurrentReplace && isExistingLocalReplace { +>>>>>>> d5e312690 (feat: local replace package dependency (#1521)) shouldClonePackage = true } @@ -270,6 +299,7 @@ func (provider *GitPackageContentProvider) CloneReplacedPackagesIfNeeded(current } } +<<<<<<< HEAD // upgrade the historical-replace list with the new values for packageId, currentReplace := range currentPackageReplaceOptions { historicalPackageReplaceOptions[packageId] = currentReplace @@ -277,6 +307,15 @@ func (provider *GitPackageContentProvider) CloneReplacedPackagesIfNeeded(current if err = provider.packageReplaceOptionsRepository.Save(historicalPackageReplaceOptions); err != nil { return startosis_errors.WrapWithInterpretationError(err, "An error occurred saving the historical package replace options from the repository") +======= + // upgrade the existing-replace list with the new values + for packageId, currentReplace := range currentPackageReplaceOptions { + existingPackageReplaceOptions[packageId] = currentReplace + } + + if err = provider.packageReplaceOptionsRepository.Save(existingPackageReplaceOptions); err != nil { + return startosis_errors.WrapWithInterpretationError(err, "An error occurred saving the existing package replace options from the repository") +>>>>>>> d5e312690 (feat: local replace package dependency (#1521)) } return nil } @@ -552,6 +591,7 @@ func getKurtosisYamlPathForFileUrlInternal(absPathToFile string, packagesDir str } return filePathToKurtosisYamlNotFound, nil } +<<<<<<< HEAD func isLocalAbsoluteLocator(locator string, parentPackageId string) bool { return strings.HasPrefix(locator, parentPackageId) @@ -563,3 +603,5 @@ func isLocalDependencyReplace(replace string) bool { } return false } +======= +>>>>>>> d5e312690 (feat: local replace package dependency (#1521)) diff --git a/core/server/api_container/server/startosis_engine/startosis_packages/git_package_content_provider/locators.go b/core/server/api_container/server/startosis_engine/startosis_packages/git_package_content_provider/locators.go new file mode 100644 index 0000000000..5429424e01 --- /dev/null +++ b/core/server/api_container/server/startosis_engine/startosis_packages/git_package_content_provider/locators.go @@ -0,0 +1,71 @@ +package git_package_content_provider + +import ( + "github.com/sirupsen/logrus" + "strings" +) + +const ( + dotRelativePathIndicatorString = "." + subStrNotPresentIndicator = -1 +) + +func isLocalLocator(locator string) bool { + if strings.HasPrefix(locator, osPathSeparatorString) || strings.HasPrefix(locator, dotRelativePathIndicatorString) { + return true + } + return false +} + +func isSamePackageLocalAbsoluteLocator(locator string, parentPackageId string) bool { + return strings.HasPrefix(locator, parentPackageId) +} + +func replaceAbsoluteLocator(absoluteLocator string, packageReplaceOptions map[string]string) string { + if absoluteLocator == "" { + return absoluteLocator + } + + found, packageToBeReplaced, replaceWithPackage := findPackageReplace(absoluteLocator, packageReplaceOptions) + + if found { + // we skip if it's a local replace because we will use the same absolute locator + // due the file was already uploaded in the enclave's package cache + if isLocalLocator(replaceWithPackage) { + return absoluteLocator + } + replacedAbsoluteLocator := strings.Replace(absoluteLocator, packageToBeReplaced, replaceWithPackage, onlyOneReplace) + logrus.Debugf("absoluteLocator '%s' replaced with '%s'", absoluteLocator, replacedAbsoluteLocator) + return replacedAbsoluteLocator + } + + return absoluteLocator +} + +func findPackageReplace(absoluteLocator string, packageReplaceOptions map[string]string) (bool, string, string) { + if len(packageReplaceOptions) == 0 { + return false, "", "" + } + + pathToAnalyze := absoluteLocator + for { + numberSlashes := strings.Count(pathToAnalyze, urlPathSeparator) + + // check for the minimal path e.g.: github.com/org/package + if numberSlashes < minimumSubPathsForValidGitURL { + break + } + lastIndex := strings.LastIndex(pathToAnalyze, urlPathSeparator) + + packageToBeReplaced := pathToAnalyze[:lastIndex] + replaceWithPackage, ok := packageReplaceOptions[packageToBeReplaced] + if ok { + logrus.Debugf("dependency replace found for '%s', package '%s' will be replaced with '%s'", absoluteLocator, packageToBeReplaced, replaceWithPackage) + return true, packageToBeReplaced, replaceWithPackage + } + + pathToAnalyze = packageToBeReplaced + } + + return false, "", "" +} diff --git a/core/server/api_container/server/startosis_engine/startosis_packages/git_package_content_provider/package_replace_options_repository.go b/core/server/api_container/server/startosis_engine/startosis_packages/git_package_content_provider/package_replace_options_repository.go index 0a47d40760..7180b348af 100644 --- a/core/server/api_container/server/startosis_engine/startosis_packages/git_package_content_provider/package_replace_options_repository.go +++ b/core/server/api_container/server/startosis_engine/startosis_packages/git_package_content_provider/package_replace_options_repository.go @@ -15,7 +15,11 @@ type packageReplaceOptionsRepository struct { enclaveDb *enclave_db.EnclaveDB } +<<<<<<< HEAD func NewPackageReplaceOptionsRepository( +======= +func newPackageReplaceOptionsRepository( +>>>>>>> d5e312690 (feat: local replace package dependency (#1521)) enclaveDb *enclave_db.EnclaveDB, ) *packageReplaceOptionsRepository { return &packageReplaceOptionsRepository{ diff --git a/core/server/api_container/server/startosis_engine/startosis_packages/git_package_content_provider/package_replace_options_repository_test.go b/core/server/api_container/server/startosis_engine/startosis_packages/git_package_content_provider/package_replace_options_repository_test.go index b10aaef371..2a9fa0fe22 100644 --- a/core/server/api_container/server/startosis_engine/startosis_packages/git_package_content_provider/package_replace_options_repository_test.go +++ b/core/server/api_container/server/startosis_engine/startosis_packages/git_package_content_provider/package_replace_options_repository_test.go @@ -24,15 +24,49 @@ func TestSaveAnGet_Success(t *testing.T) { require.Equal(t, allPackageReplaceOptionsForTest, historicalReplacePackageOptions) } +<<<<<<< HEAD +======= +func TestSaveAnGet_OverwriteSuccess(t *testing.T) { + repository := getPackageReplaceOptionsRepositoryForTest(t) + + err := repository.Save(allPackageReplaceOptionsForTest) + require.NoError(t, err) + + randomReplaceOptionsForTest := map[string]string{ + "github.com/kurtosis-tech/sample-dependency-package": "github.com/kurtosis-tech/random-package", + "github.com/kurtosis-tech/avalanche-package": "github.com/another-org/avalanche-package", + } + + err = repository.Save(randomReplaceOptionsForTest) + require.NoError(t, err) + + expectedReplacePackageOptions := map[string]string{ + "github.com/kurtosis-tech/sample-dependency-package": "github.com/kurtosis-tech/random-package", + "github.com/kurtosis-tech/avalanche-package": "github.com/another-org/avalanche-package", + "github.com/kurtosis-tech/ethereum-package": "github.com/another-org/ethereum-package", + } + + existingReplacePackageOptions, err := repository.Get() + require.NoError(t, err) + require.Equal(t, expectedReplacePackageOptions, existingReplacePackageOptions) +} + +>>>>>>> d5e312690 (feat: local replace package dependency (#1521)) func TestSaveAnGet_SuccessForNoReplacePackageOptions(t *testing.T) { repository := getPackageReplaceOptionsRepositoryForTest(t) err := repository.Save(noPackageReplaceOptions) require.NoError(t, err) +<<<<<<< HEAD historicalReplacePackageOptions, err := repository.Get() require.NoError(t, err) require.Equal(t, noPackageReplaceOptions, historicalReplacePackageOptions) +======= + existingReplacePackageOptions, err := repository.Get() + require.NoError(t, err) + require.Equal(t, noPackageReplaceOptions, existingReplacePackageOptions) +>>>>>>> d5e312690 (feat: local replace package dependency (#1521)) } func TestSave_ErrorWhenSavingNil(t *testing.T) { @@ -45,9 +79,15 @@ func TestSave_ErrorWhenSavingNil(t *testing.T) { func TestGet_SuccessEmptyRepository(t *testing.T) { repository := getPackageReplaceOptionsRepositoryForTest(t) +<<<<<<< HEAD historicalReplacePackageOptions, err := repository.Get() require.NoError(t, err) require.Equal(t, noPackageReplaceOptions, historicalReplacePackageOptions) +======= + existingReplacePackageOptions, err := repository.Get() + require.NoError(t, err) + require.Equal(t, noPackageReplaceOptions, existingReplacePackageOptions) +>>>>>>> d5e312690 (feat: local replace package dependency (#1521)) } func getPackageReplaceOptionsRepositoryForTest(t *testing.T) *packageReplaceOptionsRepository { @@ -63,7 +103,11 @@ func getPackageReplaceOptionsRepositoryForTest(t *testing.T) *packageReplaceOpti enclaveDb := &enclave_db.EnclaveDB{ DB: db, } +<<<<<<< HEAD repository := NewPackageReplaceOptionsRepository(enclaveDb) +======= + repository := newPackageReplaceOptionsRepository(enclaveDb) +>>>>>>> d5e312690 (feat: local replace package dependency (#1521)) return repository } diff --git a/core/server/api_container/server/startosis_engine/startosis_packages/package_content_provider.go b/core/server/api_container/server/startosis_engine/startosis_packages/package_content_provider.go index 48812e2461..e78c63a862 100644 --- a/core/server/api_container/server/startosis_engine/startosis_packages/package_content_provider.go +++ b/core/server/api_container/server/startosis_engine/startosis_packages/package_content_provider.go @@ -29,8 +29,13 @@ type PackageContentProvider interface { // ClonePackage clones the package with the given id and returns the absolute path on disk ClonePackage(packageId string) (string, *startosis_errors.InterpretationError) +<<<<<<< HEAD // GetAbsoluteLocatorForRelativeLocator returns the absolute package path for a relative module path and replace the package path if // there is a valid option in the noPackageReplaceOptions map +======= + // GetAbsoluteLocatorForRelativeLocator returns the absolute package path for a relative file path and replace the package path if + // there is a valid option in the packageReplaceOptions map +>>>>>>> d5e312690 (feat: local replace package dependency (#1521)) GetAbsoluteLocatorForRelativeLocator(packageId string, relativeOrAbsoluteLocator string, packageReplaceOptions map[string]string) (string, *startosis_errors.InterpretationError) // GetKurtosisYaml returns the package kurtosis.yml file content diff --git a/internal_testsuites/starlark/packages-with-replace/replace-with-local/main.star b/internal_testsuites/starlark/packages-with-replace/replace-with-local/main.star index f9c88c2406..cd5d1e1be4 100644 --- a/internal_testsuites/starlark/packages-with-replace/replace-with-local/main.star +++ b/internal_testsuites/starlark/packages-with-replace/replace-with-local/main.star @@ -6,7 +6,10 @@ EXPECTED_MSG_FROM_LOCAL_PACKAGE_MAIN = "msg-loaded-from-local-dependency" MSG_ORIGIN_MAIN = "main" MSG_ORIGIN_LOCAL_DEPENDENCY = "local" +<<<<<<< HEAD # TODO remove https://github.com/kurtosis-tech/sample-startosis-load/tree/main/sample-package if it's not used +======= +>>>>>>> d5e312690 (feat: local replace package dependency (#1521)) def run(plan, message_origin=MSG_ORIGIN_MAIN): plan.print("Replace with local package loaded.")