GetPackages gets package information for RHEL-based systems
()
| 37 | |
| 38 | // GetPackages gets package information for RHEL-based systems |
| 39 | func (m *DNFManager) GetPackages() []models.Package { |
| 40 | // Determine package manager |
| 41 | packageManager := m.detectPackageManager() |
| 42 | |
| 43 | m.logger.WithField("manager", packageManager).Debug("Using package manager") |
| 44 | |
| 45 | // Note: We don't run 'makecache' because: |
| 46 | // 1. It causes delays on systems without internet (tries to reach remote repos) |
| 47 | // 2. It's not needed for listing installed packages |
| 48 | // 3. The 'check-update' command already refreshes metadata when needed |
| 49 | // 4. Fedora's cache issue (if any) is resolved by using proper update checks |
| 50 | |
| 51 | // Get installed packages |
| 52 | // Note: yum (CentOS 7 / legacy) uses positional argument syntax: "yum list installed" |
| 53 | // while dnf uses flag syntax: "dnf list --installed" |
| 54 | m.logger.Debug("Getting installed packages...") |
| 55 | var listCmd *exec.Cmd |
| 56 | if packageManager == "yum" { |
| 57 | listCmd = exec.Command(packageManager, "list", "installed") |
| 58 | } else { |
| 59 | listCmd = exec.Command(packageManager, "list", "--installed") |
| 60 | } |
| 61 | // OPTIMIZATION: Set minimal environment to reduce overhead |
| 62 | listCmd.Env = append(os.Environ(), "LANG=C") |
| 63 | installedOutput, err := listCmd.Output() |
| 64 | var installedPackages map[string]models.Package |
| 65 | if err != nil { |
| 66 | m.logger.WithError(err).Warn("Failed to get installed packages") |
| 67 | installedPackages = make(map[string]models.Package) |
| 68 | } else { |
| 69 | m.logger.WithField("outputSize", len(installedOutput)).Debug("Received output from list installed command") |
| 70 | m.logger.Debug("Parsing installed packages...") |
| 71 | installedPackages = m.parseInstalledPackages(string(installedOutput)) |
| 72 | m.logger.WithField("count", len(installedPackages)).Info("Found installed packages") |
| 73 | |
| 74 | if len(installedPackages) == 0 { |
| 75 | m.logger.Warn("No installed packages found - this may indicate a parsing issue") |
| 76 | } |
| 77 | } |
| 78 | |
| 79 | // Get security updates first to identify which packages are security updates |
| 80 | m.logger.Debug("Getting security updates...") |
| 81 | securityPackages := m.getSecurityPackages(packageManager) |
| 82 | m.logger.WithField("count", len(securityPackages)).Debug("Found security packages") |
| 83 | |
| 84 | // Get upgradable packages |
| 85 | m.logger.Debug("Getting upgradable packages...") |
| 86 | checkCmd := exec.Command(packageManager, "check-update") |
| 87 | checkOutput, _ := checkCmd.Output() // This command returns exit code 100 when updates are available |
| 88 | |
| 89 | var upgradablePackages []models.Package |
| 90 | if len(checkOutput) > 0 { |
| 91 | m.logger.Debug("Parsing DNF/yum check-update output...") |
| 92 | upgradablePackages = m.parseUpgradablePackages(string(checkOutput), packageManager, installedPackages, securityPackages) |
| 93 | m.logger.WithField("count", len(upgradablePackages)).Debug("Found upgradable packages") |
| 94 | } else { |
| 95 | m.logger.Debug("No updates available") |
| 96 | upgradablePackages = []models.Package{} |
nothing calls this directly
no test coverage detected