Example #1
0
// 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
}
Example #2
0
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
}