Skip to content

Commit

Permalink
Read directly from prow config files instead of our own
Browse files Browse the repository at this point in the history
Prow must have jobs defined for some integrations (like Deck) to
properly show the jobs created here. The release-controller will
directly reference the prow jobs.
  • Loading branch information
smarterclayton committed Sep 19, 2018
1 parent e239cbc commit 9820044
Show file tree
Hide file tree
Showing 6 changed files with 132 additions and 72 deletions.
9 changes: 6 additions & 3 deletions cmd/release-controller/main.go
Expand Up @@ -36,7 +36,9 @@ type options struct {
ReleaseNamespace string
JobNamespace string
ProwNamespace string
ProwConfigPath string

ProwConfigPath string
JobConfigPath string
}

func main() {
Expand All @@ -56,7 +58,8 @@ func main() {
flag.StringVar(&opt.JobNamespace, "job-namespace", opt.JobNamespace, "The namespace to execute jobs and hold temporary objects.")
flag.StringVar(&opt.ReleaseNamespace, "release-namespace", opt.ReleaseNamespace, "The namespace where the releases will be published to.")
flag.StringVar(&opt.ProwNamespace, "prow-namespace", opt.ProwNamespace, "The namespace where the Prow jobs will be created (defaults to --job-namespace).")
flag.StringVar(&opt.ProwConfigPath, "prow-config", opt.ProwConfigPath, "A config file containing the jobs to run against releases.")
flag.StringVar(&opt.ProwConfigPath, "prow-config", opt.ProwConfigPath, "A config file containing the prow configuration.")
flag.StringVar(&opt.JobConfigPath, "job-config", opt.JobConfigPath, "A config file containing the jobs to run against releases.")
flag.AddGoFlag(original.Lookup("v"))

if err := cmd.Execute(); err != nil {
Expand Down Expand Up @@ -112,7 +115,7 @@ func (o *options) Run() error {

configAgent := &prowapiv1.Agent{}
if len(o.ProwConfigPath) > 0 {
if err := configAgent.Start(o.ProwConfigPath); err != nil {
if err := configAgent.Start(o.ProwConfigPath, o.JobConfigPath); err != nil {
return err
}
}
Expand Down
36 changes: 29 additions & 7 deletions cmd/release-controller/sync.go
Expand Up @@ -144,13 +144,14 @@ func (c *Controller) ensureProwJobForReleaseTag(release *Release, name, jobName
c.eventRecorder.Event(release.Source, corev1.EventTypeWarning, "ProwJobInvalid", err.Error())
return nil, terminalError{err}
}
prowSpec, ok := hasProwJob(config, jobName)
periodicConfig, ok := hasProwJob(config, jobName)
if !ok {
err := fmt.Errorf("the prow job %s is not valid: no job with that name", jobName)
c.eventRecorder.Eventf(release.Source, corev1.EventTypeWarning, "ProwJobInvalid", err.Error())
return nil, terminalError{err}
}
spec := prowSpec.DeepCopy()

spec := prowSpecForPeriodicConfig(periodicConfig, config.Plank.DefaultDecorationConfig)
mirror, _ := c.imageStreamLister.ImageStreams(c.jobNamespace).Get(releaseTag.Name)
if err := addReleaseEnvToProwJobSpec(spec, release, mirror, releaseTag); err != nil {
return nil, err
Expand Down Expand Up @@ -738,7 +739,7 @@ func addReleaseEnvToProwJobSpec(spec *prowapiv1.ProwJobSpec, release *Release, m
for j := range c.Env {
switch name := c.Env[j].Name; {
case name == "RELEASE_IMAGE_LATEST":
c.Env[j].Value = release.Target.Status.PublicDockerImageRepository + releaseTag.Name
c.Env[j].Value = release.Target.Status.PublicDockerImageRepository + ":" + releaseTag.Name
case name == "IMAGE_FORMAT":
if mirror == nil {
return fmt.Errorf("unable to determine IMAGE_FORMAT for prow job %s", spec.Job)
Expand All @@ -760,10 +761,10 @@ func addReleaseEnvToProwJobSpec(spec *prowapiv1.ProwJobSpec, release *Release, m
return nil
}

func hasProwJob(config *prowapiv1.Config, name string) (*prowapiv1.ProwJobSpec, bool) {
for i := range config.Jobs {
if config.Jobs[i].Job == name {
return &config.Jobs[i], true
func hasProwJob(config *prowapiv1.Config, name string) (*prowapiv1.PeriodicConfig, bool) {
for i := range config.Periodics {
if config.Periodics[i].Name == name {
return &config.Periodics[i], true
}
}
return nil, false
Expand Down Expand Up @@ -792,3 +793,24 @@ func toJSONString(data interface{}) string {
}
return string(out)
}

func prowSpecForPeriodicConfig(config *prowapiv1.PeriodicConfig, decorationConfig *prowapiv1.DecorationConfig) *prowapiv1.ProwJobSpec {
spec := &prowapiv1.ProwJobSpec{
Type: prowapiv1.PeriodicJob,
Job: config.Name,
Agent: prowapiv1.KubernetesAgent,

Refs: &prowapiv1.Refs{},

PodSpec: config.Spec.DeepCopy(),
}

if decorationConfig != nil {
spec.DecorationConfig = decorationConfig.DeepCopy()
} else {
spec.DecorationConfig = &prowapiv1.DecorationConfig{}
}
spec.DecorationConfig.SkipCloning = true

return spec
}
38 changes: 24 additions & 14 deletions pkg/prow/apiv1/agent.go
Expand Up @@ -28,18 +28,18 @@ import (
"github.com/golang/glog"
)

type Config struct {
Jobs []ProwJobSpec `json:"jobs"`
}

func Load(path string) (*Config, error) {
data, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
// Load reads the decoration_config from prowConfigPath and periodics from
// the provided job config, or returns an error.
func Load(prowConfigPath, jobConfigPath string) (*Config, error) {
c := &Config{}
if err := yaml.Unmarshal(data, c); err != nil {
return nil, err
for _, path := range []string{prowConfigPath, jobConfigPath} {
data, err := ioutil.ReadFile(path)
if err != nil {
return nil, err
}
if err := yaml.Unmarshal(data, c); err != nil {
return nil, err
}
}
return c, nil
}
Expand All @@ -54,8 +54,8 @@ type Agent struct {
// Start will begin polling the config file at the path. If the first load
// fails, Start with return the error and abort. Future load failures will log
// the failure message but continue attempting to load.
func (ca *Agent) Start(jobConfig string) error {
c, err := Load(jobConfig)
func (ca *Agent) Start(prowConfig, jobConfig string) error {
c, err := Load(prowConfig, jobConfig)
if err != nil {
return err
}
Expand All @@ -78,13 +78,23 @@ func (ca *Agent) Start(jobConfig string) error {

recentModTime := prowStat.ModTime()

jobConfigStat, err := os.Stat(jobConfig)
if err != nil {
glog.Errorf("Error loading job config: %v", err)
continue
}

if jobConfigStat.ModTime().After(recentModTime) {
recentModTime = jobConfigStat.ModTime()
}

if !recentModTime.After(lastModTime) {
skips++
continue // file hasn't been modified
}
lastModTime = recentModTime
}
if c, err := Load(jobConfig); err != nil {
if c, err := Load(prowConfig, jobConfig); err != nil {
glog.Errorf("Error loading config: %v", err)
} else {
skips = 0
Expand Down
31 changes: 29 additions & 2 deletions pkg/prow/apiv1/types.go
Expand Up @@ -27,6 +27,35 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

// Config loads a subset of the Prow config definition.
type Config struct {
// Plank is the default plank configuration.
Plank PlankConfig `json:"plank"`

// Periodics uses the definitions of periodic jobs to invoke
// special actions. Only a subset of fields is supported.
Periodics []PeriodicConfig `json:"periodics"`
}

type PlankConfig struct {
// DecorationConfig holds configuration options for
// decorating PodSpecs that users provide.
DefaultDecorationConfig *DecorationConfig `json:"default_decoration_config,omitempty"`
}

// PeriodicConfig is a subset of the configuration of a periodic job.
type PeriodicConfig struct {
Name string `json:"name"`
// Labels are added in prowjobs created for this job.
Labels map[string]string `json:"labels,omitempty"`
// Agent that will take care of running this job.
Agent string `json:"agent"`
// Kubernetes pod spec.
Spec *corev1.PodSpec `json:"spec,omitempty"`
// Tags for config entries
Tags []string `json:"tags,omitempty"`
}

// ProwJobType specifies how the job is triggered.
type ProwJobType string

Expand Down Expand Up @@ -131,8 +160,6 @@ type ProwJobSpec struct {
// a Kubernetes agent
PodSpec *corev1.PodSpec `json:"pod_spec,omitempty"`

Decorate bool `json:"decorate,omitempty"`

// DecorationConfig holds configuration options for
// decorating PodSpecs that users provide
DecorationConfig *DecorationConfig `json:"decoration_config,omitempty"`
Expand Down
74 changes: 28 additions & 46 deletions test/testdata/jobs.yaml
@@ -1,56 +1,38 @@
jobs:
- job: release-openshift-origin-installer-e2e-aws-master
type: periodic
periodics:
- name: release-openshift-origin-installer-e2e-aws-master
agent: kubernetes
cluster: default
refs: {}
decorate: true
decoration_config:
gcs_configuration:
bucket: origin-ci-test
default_org: openshift
default_repo: origin
path_strategy: single
gcs_credentials_secret: gcs-publisher-credentials
grace_period: 15000000000
skip_cloning: true
timeout: 14400000000000
utility_images:
clonerefs: clonerefs:latest
entrypoint: entrypoint:latest
initupload: initupload:latest
sidecar: sidecar:latest
pod_spec:
# TODO: set arbitarily high so as not to be run without our parameters,
# add a new job type to test-infra for this use case or allow periodics to
# be set to disabled.
cron: "@yearly"
spec:
containers:
- name: echo
image: centos:7
# These environment parameters are replaced by the release-controller dynamically
env:
- name: RELEASE_IMAGE_LATEST
value: registry.svc.ci.openshift.org/openshift/release:v4.0
- name: IMAGE_FORMAT
value: registry.svc.ci.openshift.org/openshift/origin-v4.0:${component}
- name: RPM_REPO
value: https://rpms.svc.ci.openshift.org/openshift-origin-v4.0/
command:
- echo
- "SUCCESS"
- job: release-openshift-origin-installer-e2e-gcp-master
type: periodic
- env
- name: release-openshift-origin-installer-e2e-gcp-master
agent: kubernetes
cluster: default
refs: {}
decorate: true
decoration_config:
gcs_configuration:
bucket: origin-ci-test
default_org: openshift
default_repo: origin
path_strategy: single
gcs_credentials_secret: gcs-publisher-credentials
grace_period: 15000000000
skip_cloning: true
timeout: 14400000000000
utility_images:
clonerefs: clonerefs:latest
entrypoint: entrypoint:latest
initupload: initupload:latest
sidecar: sidecar:latest
pod_spec:
cron: "@yearly"
spec:
containers:
- name: echo
image: centos:7
# These environment parameters are replaced by the release-controller dynamically
env:
- name: RELEASE_IMAGE_LATEST
value: registry.svc.ci.openshift.org/openshift/release:v4.0
- name: IMAGE_FORMAT
value: registry.svc.ci.openshift.org/openshift/origin-v4.0:${component}
- name: RPM_REPO
value: https://rpms.svc.ci.openshift.org/openshift-origin-v4.0/
command:
- /bin/false
- env
16 changes: 16 additions & 0 deletions test/testdata/prow.yaml
@@ -0,0 +1,16 @@
plank:
default_decoration_config:
gcs_configuration:
bucket: origin-ci-test
default_org: openshift
default_repo: origin
path_strategy: single
gcs_credentials_secret: gcs-publisher-credentials
grace_period: 15000000000
skip_cloning: true
timeout: 14400000000000
utility_images:
clonerefs: clonerefs:latest
entrypoint: entrypoint:latest
initupload: initupload:latest
sidecar: sidecar:latest

0 comments on commit 9820044

Please sign in to comment.