| // Copyright 2018 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 agentendpoint |
| |
| import ( |
| "context" |
| "errors" |
| "regexp" |
| "strings" |
| "time" |
| |
| "github.com/GoogleCloudPlatform/osconfig/clog" |
| "github.com/GoogleCloudPlatform/osconfig/ospatch" |
| "github.com/GoogleCloudPlatform/osconfig/packages" |
| "github.com/GoogleCloudPlatform/osconfig/retryutil" |
| |
| "cloud.google.com/go/osconfig/agentendpoint/apiv1/agentendpointpb" |
| ) |
| |
| func (r *patchTask) runUpdates(ctx context.Context) error { |
| var errs []string |
| const retryPeriod = 3 * time.Minute |
| // Check for both apt-get and dpkg-query to give us a clean signal. |
| if packages.AptExists && packages.DpkgQueryExists { |
| excludes, err := convertInputToExcludes(r.Task.GetPatchConfig().GetApt().GetExcludes()) |
| if err != nil { |
| return err |
| } |
| opts := []ospatch.AptGetUpgradeOption{ |
| ospatch.AptGetDryRun(r.Task.GetDryRun()), |
| ospatch.AptGetExcludes(excludes), |
| ospatch.AptGetExclusivePackages(r.Task.GetPatchConfig().GetApt().GetExclusivePackages()), |
| } |
| switch r.Task.GetPatchConfig().GetApt().GetType() { |
| case agentendpointpb.AptSettings_DIST: |
| opts = append(opts, ospatch.AptGetUpgradeType(packages.AptGetDistUpgrade)) |
| } |
| clog.Debugf(ctx, "Installing APT package updates.") |
| if err := retryutil.RetryFunc(ctx, retryPeriod, "installing APT package updates", func() error { return ospatch.RunAptGetUpgrade(ctx, opts...) }); err != nil { |
| errs = append(errs, err.Error()) |
| } |
| } |
| if packages.YumExists && packages.RPMQueryExists { |
| excludes, err := convertInputToExcludes(r.Task.GetPatchConfig().GetYum().GetExcludes()) |
| if err != nil { |
| return err |
| } |
| opts := []ospatch.YumUpdateOption{ |
| ospatch.YumUpdateSecurity(r.Task.GetPatchConfig().GetYum().GetSecurity()), |
| ospatch.YumUpdateMinimal(r.Task.GetPatchConfig().GetYum().GetMinimal()), |
| ospatch.YumUpdateExcludes(excludes), |
| ospatch.YumExclusivePackages(r.Task.GetPatchConfig().GetYum().GetExclusivePackages()), |
| ospatch.YumDryRun(r.Task.GetDryRun()), |
| } |
| clog.Debugf(ctx, "Installing YUM package updates.") |
| if err := retryutil.RetryFunc(ctx, retryPeriod, "installing YUM package updates", func() error { return ospatch.RunYumUpdate(ctx, opts...) }); err != nil { |
| errs = append(errs, err.Error()) |
| } |
| } |
| if packages.ZypperExists && packages.RPMQueryExists { |
| excludes, err := convertInputToExcludes(r.Task.GetPatchConfig().GetZypper().GetExcludes()) |
| if err != nil { |
| return err |
| } |
| opts := []ospatch.ZypperPatchOption{ |
| ospatch.ZypperPatchCategories(r.Task.GetPatchConfig().GetZypper().GetCategories()), |
| ospatch.ZypperPatchSeverities(r.Task.GetPatchConfig().GetZypper().GetSeverities()), |
| ospatch.ZypperUpdateWithUpdate(r.Task.GetPatchConfig().GetZypper().GetWithUpdate()), |
| ospatch.ZypperUpdateWithOptional(r.Task.GetPatchConfig().GetZypper().GetWithOptional()), |
| ospatch.ZypperUpdateWithExcludes(excludes), |
| ospatch.ZypperUpdateWithExclusivePatches(r.Task.GetPatchConfig().GetZypper().GetExclusivePatches()), |
| ospatch.ZypperUpdateDryrun(r.Task.GetDryRun()), |
| } |
| clog.Debugf(ctx, "Installing Zypper updates.") |
| if err := retryutil.RetryFunc(ctx, retryPeriod, "installing Zypper updates", func() error { return ospatch.RunZypperPatch(ctx, opts...) }); err != nil { |
| errs = append(errs, err.Error()) |
| } |
| } |
| if errs == nil { |
| return nil |
| } |
| return errors.New(strings.Join(errs, ",\n")) |
| } |
| |
| func convertInputToExcludes(input []string) ([]*ospatch.Exclude, error) { |
| var output []*ospatch.Exclude |
| for _, s := range input { |
| if len(s) >= 2 && (s)[0] == '/' && s[len(s)-1] == '/' { |
| exclude, err := regexExcludeFromString(s[1 : len(s)-1]) |
| if err != nil { |
| return nil, err |
| } |
| output = append(output, exclude) |
| } else { |
| output = append(output, ospatch.CreateStringExclude(&s)) |
| } |
| } |
| return output, nil |
| } |
| |
| func regexExcludeFromString(s string) (*ospatch.Exclude, error) { |
| compile, err := regexp.Compile(s) |
| if err != nil { |
| return nil, err |
| } |
| return ospatch.CreateRegexExclude(compile), nil |
| } |