Beispiel #1
0
Datei: job.go Projekt: utako/atc
func Job(dbJob db.SavedJob, job atc.JobConfig, groups atc.GroupConfigs, finishedBuild, nextBuild *db.Build) atc.Job {
	generator := rata.NewRequestGenerator("", routes.Routes)

	req, err := generator.CreateRequest(
		routes.GetJob,
		rata.Params{"job": job.Name, "pipeline_name": dbJob.PipelineName},
		nil,
	)
	if err != nil {
		panic("failed to generate url: " + err.Error())
	}

	var presentedNextBuild, presentedFinishedBuild *atc.Build

	if nextBuild != nil {
		presented := Build(*nextBuild)
		presentedNextBuild = &presented
	}

	if finishedBuild != nil {
		presented := Build(*finishedBuild)
		presentedFinishedBuild = &presented
	}

	groupNames := []string{}
	for _, group := range groups {
		for _, name := range group.Jobs {
			if name == job.Name {
				groupNames = append(groupNames, group.Name)
			}
		}
	}

	return atc.Job{
		Name:          job.Name,
		URL:           req.URL.String(),
		Paused:        dbJob.Paused,
		FinishedBuild: presentedFinishedBuild,
		NextBuild:     presentedNextBuild,

		Inputs:  job.Inputs(),
		Outputs: job.Outputs(),

		Groups: groupNames,
	}
}
Beispiel #2
0
	"github.com/concourse/atc/scheduler/fakes"
	"github.com/pivotal-golang/lager/lagertest"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Scheduler", func() {
	var (
		fakePipelineDB *fakes.FakePipelineDB
		fakeBuildsDB   *fakes.FakeBuildsDB
		factory        *fakes.FakeBuildFactory
		fakeEngine     *enginefakes.FakeEngine
		fakeScanner    *fakes.FakeScanner

		createdPlan atc.Plan

		job       atc.JobConfig
		resources atc.ResourceConfigs

		scheduler *Scheduler

		logger *lagertest.TestLogger
	)

	BeforeEach(func() {
		fakePipelineDB = new(fakes.FakePipelineDB)
		fakeBuildsDB = new(fakes.FakeBuildsDB)
		factory = new(fakes.FakeBuildFactory)
		fakeEngine = new(enginefakes.FakeEngine)
		fakeScanner = new(fakes.FakeScanner)
Beispiel #3
0
		Context("when two resource types have the same name", func() {
			BeforeEach(func() {
				config.ResourceTypes = append(config.ResourceTypes, config.ResourceTypes...)
			})

			It("returns an error", func() {
				Expect(validateErr).To(HaveOccurred())
				Expect(validateErr.Error()).To(ContainSubstring(
					"resource_types[0] and resource_types[1] have the same name ('some-resource-type')",
				))
			})
		})
	})

	Describe("validating a job", func() {
		var job atc.JobConfig

		BeforeEach(func() {
			job = atc.JobConfig{
				Name: "some-other-job",
			}
		})

		Context("when a job has no name", func() {
			BeforeEach(func() {
				job.Name = ""
				config.Jobs = append(config.Jobs, job)
			})

			It("returns an error", func() {
				Expect(validateErr).To(HaveOccurred())
Beispiel #4
0
package config_test

import (
	"github.com/concourse/atc"
	"github.com/concourse/atc/config"
	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Job config", func() {
	Describe("JobInputs", func() {
		var (
			jobConfig atc.JobConfig

			inputs []config.JobInput
		)

		BeforeEach(func() {
			jobConfig = atc.JobConfig{}
		})

		JustBeforeEach(func() {
			inputs = config.JobInputs(jobConfig)
		})

		Context("with a build plan", func() {
			Context("with an empty plan", func() {
				BeforeEach(func() {
					jobConfig.Plan = atc.PlanSequence{}
				})
Beispiel #5
0
package factory_test

import (
	"github.com/concourse/atc"
	. "github.com/concourse/atc/scheduler/factory"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("Factory", func() {
	var (
		factory *BuildFactory

		job       atc.JobConfig
		resources atc.ResourceConfigs

		expectedPlan atc.Plan
	)

	BeforeEach(func() {
		factory = &BuildFactory{
			PipelineName: "some-pipeline",
		}

		job = atc.JobConfig{
			Name: "some-job",
		}

		expectedPlan = atc.Plan{
			Compose: &atc.ComposePlan{
Beispiel #6
0
func (s *Scheduler) BuildLatestInputs(logger lager.Logger, job atc.JobConfig, resources atc.ResourceConfigs) error {
	logger = logger.Session("build-latest")

	inputs := job.Inputs()

	if len(inputs) == 0 {
		// no inputs; no-op
		return nil
	}

	latestInputs, err := s.PipelineDB.GetLatestInputVersions(job.Name, inputs)
	if err != nil {
		if err == db.ErrNoVersions {
			logger.Debug("no-input-versions-available")
			return nil
		}

		logger.Error("failed-to-get-latest-input-versions", err)
		return err
	}

	checkInputs := []db.BuildInput{}
	for _, input := range latestInputs {
		for _, ji := range inputs {
			if ji.Name == input.Name {
				if ji.Trigger {
					checkInputs = append(checkInputs, input)
				}

				break
			}
		}
	}

	if len(checkInputs) == 0 {
		logger.Debug("no-triggered-input-versions")
		return nil
	}

	existingBuild, err := s.PipelineDB.GetJobBuildForInputs(job.Name, checkInputs)
	if err == nil {
		logger.Debug("build-already-exists-for-inputs", lager.Data{
			"existing-build": existingBuild.ID,
		})

		return nil
	}

	build, created, err := s.PipelineDB.CreateJobBuildForCandidateInputs(job.Name)
	if err != nil {
		logger.Error("failed-to-create-build", err)
		return err
	}

	if !created {
		logger.Debug("waiting-for-existing-build-to-determine-inputs", lager.Data{
			"existing-build": build.ID,
		})
		return nil
	}

	logger.Debug("created-build", lager.Data{"build": build.ID})

	// NOTE: this is intentionally serial within a scheduler tick, so that
	// multiple ATCs don't do redundant work to determine a build's inputs.

	s.scheduleAndResumePendingBuild(logger, build, job, resources)

	return nil
}
Beispiel #7
0
func (s *Scheduler) scheduleAndResumePendingBuild(logger lager.Logger, build db.Build, job atc.JobConfig, resources atc.ResourceConfigs) engine.Build {
	logger = logger.WithData(lager.Data{"build": build.ID})

	scheduled, err := s.PipelineDB.ScheduleBuild(build.ID, job)
	if err != nil {
		logger.Error("failed-to-schedule-build", err)
		return nil
	}

	if !scheduled {
		logger.Debug("build-could-not-be-scheduled")
		return nil
	}

	buildInputs := job.Inputs()

	for _, input := range buildInputs {
		scanLog := logger.Session("scan", lager.Data{
			"input":    input.Name,
			"resource": input.Resource,
		})

		err := s.Scanner.Scan(scanLog, input.Resource)
		if err != nil {
			scanLog.Error("failed-to-scan", err)

			err := s.BuildsDB.ErrorBuild(build.ID, err)
			if err != nil {
				logger.Error("failed-to-mark-build-as-errored", err)
			}

			return nil
		}

		scanLog.Info("done")
	}

	inputs, err := s.PipelineDB.GetLatestInputVersions(job.Name, buildInputs)
	if err != nil {
		logger.Error("failed-to-get-latest-input-versions", err)
		return nil
	}

	err = s.PipelineDB.UseInputsForBuild(build.ID, inputs)
	if err != nil {
		logger.Error("failed-to-use-inputs-for-build", err)
		return nil
	}

	plan, err := s.Factory.Create(job, resources, inputs)
	if err != nil {
		logger.Error("failed-to-create-build-plan", err)
		return nil
	}

	createdBuild, err := s.Engine.CreateBuild(build, plan)
	if err != nil {
		logger.Error("failed-to-create-build", err)
		return nil
	}

	if createdBuild != nil {
		logger.Info("building")
		go createdBuild.Resume(logger)
	}

	return createdBuild
}
Beispiel #8
0
		Context("when two resources have the same name", func() {
			BeforeEach(func() {
				config.Resources = append(config.Resources, config.Resources...)
			})

			It("returns an error", func() {
				Ω(validateErr).Should(HaveOccurred())
				Ω(validateErr.Error()).Should(ContainSubstring(
					"resources[0] and resources[1] have the same name ('some-resource')",
				))
			})
		})
	})

	Describe("validating a job", func() {
		var job atc.JobConfig

		BeforeEach(func() {
			job = atc.JobConfig{
				Name:           "some-other-job",
				TaskConfigPath: "some-task-config",
			}
		})

		Context("when a job has a only a name and a build config", func() {
			BeforeEach(func() {
				config.Jobs = append(config.Jobs, job)
			})

			It("returns no error", func() {
				Ω(validateErr).ShouldNot(HaveOccurred())
Beispiel #9
0
	. "github.com/onsi/gomega"
	"github.com/onsi/gomega/gbytes"
)

var _ = Describe("Scheduler", func() {
	var (
		fakePipelineDB *fakes.FakePipelineDB
		fakeBuildsDB   *fakes.FakeBuildsDB
		factory        *fakes.FakeBuildFactory
		fakeEngine     *enginefakes.FakeEngine
		fakeScanner    *fakes.FakeScanner

		lease *dbfakes.FakeLease

		createdPlan atc.Plan

		job           atc.JobConfig
		resources     atc.ResourceConfigs
		resourceTypes atc.ResourceTypes

		scheduler *Scheduler

		someVersions *algorithm.VersionsDB

		logger *lagertest.TestLogger
	)

	BeforeEach(func() {
		fakePipelineDB = new(fakes.FakePipelineDB)
		fakeBuildsDB = new(fakes.FakeBuildsDB)
		factory = new(fakes.FakeBuildFactory)
Beispiel #10
0
func (s *Scheduler) BuildLatestInputs(logger lager.Logger, job atc.JobConfig, resources atc.ResourceConfigs) error {
	logger = logger.Session("build-latest")

	inputs := job.Inputs()

	if len(inputs) == 0 {
		// no inputs; no-op
		return nil
	}

	latestInputs, err := s.PipelineDB.GetLatestInputVersions(inputs)
	if err != nil {
		if err == db.ErrNoVersions {
			logger.Debug("no-input-versions-available")
			return nil
		}

		logger.Error("failed-to-get-latest-input-versions", err)
		return err
	}

	checkInputs := []db.BuildInput{}
	for _, input := range latestInputs {
		for _, ji := range inputs {
			if ji.Name == input.Name {
				if ji.Trigger {
					checkInputs = append(checkInputs, input)
				}

				break
			}
		}
	}

	if len(checkInputs) == 0 {
		logger.Debug("no-triggered-input-versions")
		return nil
	}

	existingBuild, err := s.PipelineDB.GetJobBuildForInputs(job.Name, checkInputs)
	if err == nil {
		logger.Debug("build-already-exists-for-inputs", lager.Data{
			"existing-build": existingBuild.ID,
		})

		return nil
	}

	build, created, err := s.PipelineDB.CreateJobBuildForCandidateInputs(job.Name)
	if err != nil {
		logger.Error("failed-to-create-build", err)
		return err
	}

	if !created {
		logger.Debug("did-not-create-build-as-it-already-is-pending")
		return nil
	}

	logger = logger.WithData(lager.Data{"build": build.ID})

	logger.Debug("created-build")

	createdBuild := s.scheduleAndResumePendingBuild(logger, build, job, resources)

	if createdBuild != nil {
		logger.Info("building")
		go createdBuild.Resume(logger)
	}

	return nil
}
Beispiel #11
0
				fakeDB.GetJobReturns(db.SavedJob{}, errors.New("disaster"))
				_, err := scheduler.NewJobService(atc.JobConfig{}, fakeDB, fakeScanner)
				Expect(err).To(HaveOccurred())
			})
		})
	})

	Describe("CanBuildBeScheduled", func() {
		var (
			service    scheduler.JobService
			dbSavedJob db.SavedJob
			jobConfig  atc.JobConfig

			logger       *lagertest.TestLogger
			dbBuild      db.Build
			buildPrep    db.BuildPreparation
			someVersions *algorithm.VersionsDB

			canBuildBeScheduled bool
			reason              string
			buildInputs         []db.BuildInput
			err                 error
		)

		BeforeEach(func() {
			fakeDB = new(fakes.FakeJobServiceDB)
			fakeScanner = new(fakes.FakeScanner)

			jobConfig = atc.JobConfig{
				Name: "some-job",