// Release whatever is in the cloned configuration, without changing anything func (r *Releaser) releaseWithoutUpdate(method, msg string, inst *instance.Instance, kind flux.ReleaseKind, getServices serviceQuery, updateJob func(string, ...interface{})) (err error) { var res []ReleaseAction defer func() { if err == nil { err = r.execute(inst, res, kind, updateJob) } }() var ( base = r.metrics.StageDuration.With("method", method) stage *metrics.Timer ) defer func() { stage.ObserveDuration() }() stage = metrics.NewTimer(base.With("stage", "fetch_platform_services")) services, err := getServices(inst) if err != nil { return errors.Wrap(err, "fetching platform services") } stage.ObserveDuration() stage = metrics.NewTimer(base.With("stage", "finalize")) res = append(res, r.releaseActionPrintf(msg)) res = append(res, r.releaseActionClone()) ids := []flux.ServiceID{} for _, service := range services { res = append(res, r.releaseActionFindPodController(service.ID)) ids = append(ids, service.ID) } res = append(res, r.releaseActionRegradeServices(ids, msg)) return nil }
func (r *Releaser) releaseImages(method, msg string, inst *instance.Instance, kind flux.ReleaseKind, getServices serviceQuery, getImages imageCollect, updateJob func(string, ...interface{})) (err error) { var res []ReleaseAction defer func() { if err == nil { err = r.execute(inst, res, kind, updateJob) } }() res = append(res, r.releaseActionPrintf(msg)) var ( base = r.metrics.StageDuration.With("method", method) stage *metrics.Timer ) defer func() { stage.ObserveDuration() }() stage = metrics.NewTimer(base.With("stage", "fetch_platform_services")) services, err := getServices(inst) if err != nil { return errors.Wrap(err, "fetching platform services") } stage.ObserveDuration() stage = metrics.NewTimer(base.With("stage", "calculate_regrades")) // Each service is running multiple images. // Each image may need to be upgraded, and trigger a release. images, err := getImages(inst, services) if err != nil { return errors.Wrap(err, "collecting available images to calculate regrades") } regradeMap := map[flux.ServiceID][]containerRegrade{} for _, service := range services { containers, err := service.ContainersOrError() if err != nil { res = append(res, r.releaseActionPrintf("service %s does not have images associated: %s", service.ID, err)) continue } for _, container := range containers { currentImageID := flux.ParseImageID(container.Image) latestImage := images.LatestImage(currentImageID.Repository()) if latestImage == nil { continue } if currentImageID == latestImage.ID { res = append(res, r.releaseActionPrintf("Service %s image %s is already the latest one; skipping.", service.ID, currentImageID)) continue } regradeMap[service.ID] = append(regradeMap[service.ID], containerRegrade{ container: container.Name, current: currentImageID, target: latestImage.ID, }) } } if len(regradeMap) <= 0 { res = append(res, r.releaseActionPrintf("All selected services are running the requested images. Nothing to do.")) return nil } stage.ObserveDuration() stage = metrics.NewTimer(base.With("stage", "finalize")) // We have identified at least 1 release that needs to occur. Releasing // means cloning the repo, changing the resource file(s), committing and // pushing, and then making the release(s) to the platform. res = append(res, r.releaseActionClone()) for service, regrades := range regradeMap { res = append(res, r.releaseActionUpdatePodController(service, regrades)) } res = append(res, r.releaseActionCommitAndPush(msg)) var servicesToRegrade []flux.ServiceID for service := range regradeMap { servicesToRegrade = append(servicesToRegrade, service) } res = append(res, r.releaseActionRegradeServices(servicesToRegrade, msg)) return nil }