ospatch/yum_update.go (94 lines of code) (raw):

// Copyright 2019 Google Inc. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package ospatch import ( "context" "fmt" "github.com/GoogleCloudPlatform/osconfig/clog" "github.com/GoogleCloudPlatform/osconfig/packages" ) const yum = "/usr/bin/yum" var ( yumUpdateArgs = []string{"update", "-y"} yumUpdateMinimalArgs = []string{"update-minimal", "-y"} ) type yumUpdateOpts struct { exclusivePackages []string excludes []*Exclude security bool minimal bool dryrun bool } // YumUpdateOption is an option for yum update. type YumUpdateOption func(*yumUpdateOpts) // YumUpdateSecurity returns a YumUpdateOption that specifies the --security flag should // be used. func YumUpdateSecurity(security bool) YumUpdateOption { return func(args *yumUpdateOpts) { args.security = security } } // YumUpdateMinimal returns a YumUpdateOption that specifies the update-minimal // command should be used. func YumUpdateMinimal(minimal bool) YumUpdateOption { return func(args *yumUpdateOpts) { args.minimal = minimal } } // YumUpdateExcludes returns a YumUpdateOption that specifies what packages to add to // the --exclude flag. func YumUpdateExcludes(excludes []*Exclude) YumUpdateOption { return func(args *yumUpdateOpts) { args.excludes = excludes } } // YumExclusivePackages includes only these packages in the upgrade. func YumExclusivePackages(exclusivePackages []string) YumUpdateOption { return func(args *yumUpdateOpts) { args.exclusivePackages = exclusivePackages } } // YumDryRun performs a dry run. func YumDryRun(dryrun bool) YumUpdateOption { return func(args *yumUpdateOpts) { args.dryrun = dryrun } } // fullPackageName returns the package name with architecture if present. func fullPackageName(pkgInfo *packages.PkgInfo) string { pkgName := pkgInfo.Name if len(pkgInfo.RawArch) > 0 { pkgName = pkgName + "." + pkgInfo.RawArch } return pkgName } // RunYumUpdate runs yum update. func RunYumUpdate(ctx context.Context, opts ...YumUpdateOption) error { yumOpts := &yumUpdateOpts{ security: false, minimal: false, dryrun: false, } for _, opt := range opts { opt(yumOpts) } pkgs, err := packages.YumUpdates(ctx, packages.YumUpdateMinimal(yumOpts.minimal), packages.YumUpdateSecurity(yumOpts.security)) if err != nil { return err } // Yum excludes are already excluded while listing yumUpdates, so we send // and empty list. fPkgs, err := filterPackages(pkgs, yumOpts.exclusivePackages, yumOpts.excludes) if err != nil { return err } if len(fPkgs) == 0 { clog.Infof(ctx, "No packages to update.") return nil } var pkgNames []string for _, pkg := range fPkgs { pkgNames = append(pkgNames, fullPackageName(pkg)) } msg := fmt.Sprintf("%d packages: %q", len(pkgNames), fPkgs) if yumOpts.dryrun { clog.Infof(ctx, "Running in dryrun mode, not updating %s", msg) return nil } ops := opsToReport{ packages: fPkgs, } logOps(ctx, ops) err = packages.InstallYumPackages(ctx, pkgNames) if err == nil { logSuccess(ctx, ops) } else { logFailure(ctx, ops, err) } return err }