github.com/criteo/command-launcher@v0.0.0-20230407142452-fb616f546e98/internal/backend/package-source.go (about) 1 package backend 2 3 import ( 4 "fmt" 5 "strings" 6 "time" 7 8 "github.com/criteo/command-launcher/internal/remote" 9 "github.com/criteo/command-launcher/internal/repository" 10 "github.com/criteo/command-launcher/internal/updater" 11 "github.com/criteo/command-launcher/internal/user" 12 13 log "github.com/sirupsen/logrus" 14 ) 15 16 const ( 17 SYNC_POLICY_NEVER = "never" 18 SYNC_POLICY_ALWAYS = "always" 19 SYNC_POLICY_HOURLY = "hourly" 20 SYNC_POLICY_DAILY = "daily" 21 SYNC_POLICY_WEEKLY = "weekly" 22 SYNC_POLICY_MONTHLY = "monthly" 23 ) 24 25 type PackageSource struct { 26 Name string 27 RepoDir string 28 RemoteBaseURL string 29 RemoteRegistryURL string 30 SyncPolicy string 31 IsManaged bool 32 33 Repo repository.PackageRepository 34 Failure error 35 36 Updater *updater.CmdUpdater 37 } 38 39 func NewDropinSource(repoDir string) *PackageSource { 40 return &PackageSource{ 41 Name: "dropin", 42 RepoDir: repoDir, 43 RemoteBaseURL: "", 44 RemoteRegistryURL: "", 45 IsManaged: false, 46 SyncPolicy: SYNC_POLICY_NEVER, 47 } 48 } 49 50 func NewManagedSource(name, repoDir, remoteBaseURL string, syncPolicy string) *PackageSource { 51 return &PackageSource{ 52 Name: name, 53 RepoDir: repoDir, 54 RemoteBaseURL: remoteBaseURL, 55 RemoteRegistryURL: fmt.Sprintf("%s/index.json", remoteBaseURL), 56 IsManaged: true, 57 SyncPolicy: SYNC_POLICY_ALWAYS, 58 } 59 } 60 61 func (src *PackageSource) InitUpdater(user *user.User, timeout time.Duration, enableCI bool, lockFile string, verifyChecksum bool, verifySignature bool) *updater.CmdUpdater { 62 if src.SyncPolicy == SYNC_POLICY_NEVER { 63 return nil 64 } 65 src.Updater = &updater.CmdUpdater{ 66 LocalRepo: src.Repo, 67 CmdRepositoryBaseUrl: src.RemoteBaseURL, 68 User: *user, 69 Timeout: timeout, 70 EnableCI: enableCI, 71 PackageLockFile: lockFile, 72 VerifyChecksum: verifyChecksum, 73 VerifySignature: verifySignature, 74 } 75 return src.Updater 76 } 77 78 func (src PackageSource) IsInstalled() bool { 79 if src.Repo == nil { 80 // nothing to install 81 return true 82 } 83 return len(src.Repo.InstalledCommands()) > 0 84 } 85 86 func (src *PackageSource) InitialInstallCommands(user *user.User, enableCI bool, lockFilePath string, verifyChecksum bool, verifySignature bool) error { 87 remote := remote.CreateRemoteRepository(src.RemoteBaseURL) 88 errors := make([]string, 0) 89 90 // check locked packages if ci is enabled 91 lockedPackages := map[string]string{} 92 if enableCI { 93 pkgs, err := src.Updater.LoadLockedPackages(lockFilePath) 94 if err == nil { 95 lockedPackages = pkgs 96 } 97 } 98 99 if pkgs, err := remote.PackageNames(); err == nil { 100 for _, pkgName := range pkgs { 101 pkgVersion := "unspecified" 102 if lockedVersion, ok := lockedPackages[pkgName]; ok { 103 pkgVersion = lockedVersion 104 } else { 105 latest, err := remote.LatestPackageInfo(pkgName) 106 if err != nil { 107 log.Error(err) 108 errors = append(errors, fmt.Sprintf("cannot get the latest version of the package %s: %v", latest.Name, err)) 109 continue 110 } 111 if !user.InPartition(latest.StartPartition, latest.EndPartition) { 112 log.Infof("Skip installing package %s, user not in partition (%d %d)\n", latest.Name, latest.StartPartition, latest.EndPartition) 113 continue 114 } 115 pkgVersion = latest.Version 116 } 117 118 pkg, err := remote.Package(pkgName, pkgVersion) 119 if err != nil { 120 log.Error(err) 121 errors = append(errors, fmt.Sprintf("cannot get the package %s: %v", pkgName, err)) 122 continue 123 } 124 if ok, err := remote.Verify(pkg, 125 verifyChecksum, 126 verifySignature, 127 ); !ok || err != nil { 128 log.Error(err) 129 errors = append(errors, fmt.Sprintf("failed to verify package %s, skip it: %v", pkgName, err)) 130 continue 131 } 132 err = src.Repo.Install(pkg) 133 if err != nil { 134 errors = append(errors, fmt.Sprintf("cannot install the package %s: %v", pkgName, err)) 135 continue 136 } 137 } 138 } else { 139 errors = append(errors, fmt.Sprintf("cannot get remote packages: %v", err)) 140 } 141 142 if len(errors) > 0 { 143 return fmt.Errorf("install failed for the following reasons: [%s]", strings.Join(errors, ", ")) 144 } 145 146 return nil 147 }