text:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >

    <item
        android:id="@+id/menu_zoom_toggle"
        android:title="@string/menu_zoom_disable"/>
    <item
        android:id="@+id/menu_scale_fit_center"
        android:showAsAction="never"
        android:title="@string/menu_scale_fit_center"/>
    <item
        android:id="@+id/menu_scale_fit_start"
        android:showAsAction="never"
        android:title="@string/menu_scale_fit_start"/>
    <item
        android:id="@+id/menu_scale_fit_end"
        android:showAsAction="never"
        android:title="@string/menu_scale_fit_end"/>
    <item
        android:id="@+id/menu_scale_fit_xy"
        android:showAsAction="never"
        android:title="@string/menu_scale_fit_xy"/>
    <item
        android:id="@+id/menu_scale_scale_center"
        android:showAsAction="never"
        android:title="@string/menu_scale_center"/>
    <item
        android:id="@+id/menu_scale_scale_center_crop"
        android:showAsAction="never"
        android:title="@string/menu_scale_center_crop"/>
    <item
        android:id="@+id/menu_scale_scale_center_inside"
        android:showAsAction="never"
        android:title="@string/menu_scale_center_inside"/>
    <item
        android:id="@+id/menu_scale_random_animate"
        android:showAsAction="never"
        android:title="@string/menu_zoom_random_animate"/>
    <item
        android:id="@+id/menu_scale_random"
        android:showAsAction="never"
        android:title="@string/menu_zoom_random"/>
    <item
        android:id="@+id/menu_matrix_restore"
        android:title="@string/menu_matrix_restore"/>
    <item
        android:id="@+id/menu_matrix_capture"
        android:title="@string/menu_matrix_capture"/>
    <item
        android:id="@+id/extract_visible_bitmap"
        android:title="@string/extract_visible_bitmap"/>

</menu>


text:
require 'handlebars_assets'
Sprockets.append_path HandlebarsAssets.path
require "jekyll-assets"

redpajama_set_name: RedPajamaGithub


text:
package uk.nhs.hdn.common.serialisers.separatedValues.fieldEscapers;

import org.jetbrains.annotations.NotNull;
import uk.nhs.hdn.common.serialisers.CouldNotEncodeDataException;
import uk.nhs.hdn.common.serialisers.CouldNotWriteDataException;

import java.io.Writer;

public interface FieldEscaper
{
	void escape(@NotNull final String field, @NotNull final Writer writer) throws CouldNotWriteDataException, CouldNotEncodeDataException;

	void writeLineEnding(@NotNull final Writer writer) throws CouldNotWriteDataException;

	void writeFieldSeparator(@NotNull final Writer writer) throws CouldNotWriteDataException;
}


text:
<atlassian-plugin key="${project.groupId}.${project.artifactId}-tests" name="${project.name}" plugins-version="2">
    <plugin-info>
        <description>${project.description}</description>
        <version>${project.version}</version>
        <vendor name="${project.organization.name}" url="${project.organization.url}" />
    </plugin-info>

    <!-- from our base plugin -->
    <component-import key="myComponent" interface="io.chef.bamboo.api.MyPluginComponent"/>

    <!-- from the product container -->
    <component-import key="applicationProperties" interface="com.atlassian.sal.api.ApplicationProperties" />

</atlassian-plugin>


text:
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="text/xsl" href="#xslt"?>
<!DOCTYPE xsl:stylesheet [<!ATTLIST xsl:stylesheet id ID #IMPLIED>]>
<xsl:stylesheet id="xslt" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="xsl:stylesheet">
<xsl:variable name="current" select="current()"/>
<xsl:if test="name($current) = 'xsl:stylesheet'"><result><xsl:value-of select="'PASS'"/></result></xsl:if>
</xsl:template>
</xsl:stylesheet>


text:
<?php

namespace Crm\EquipoBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;

class LicenciaEquipoType extends AbstractType
{
    /**
     * @param FormBuilderInterface $builder
     * @param array $options
     */
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('fechaInicio','date',array('widget'=>'single_text'))
            ->add('fechaFinal','date',array('widget'=>'single_text'))
            ->add('equipo','entity', array(
                'class' => 'EquipoBundle:Equipo',
                'property' => 'serieWarriors',
                'query_builder' => function (\Crm\EquipoBundle\Entity\EquipoRepository $repository){
                    return $repository->createQueryBuilder('equipo')
                    ->orderBy('equipo.checkLicencia', 'ASC')
                    ->where('equipo.checkLicencia = :check')
                    ->setParameter('check', 'f');}
                ))
        ;
    }

    /**
     * @param OptionsResolverInterface $resolver
     */
    public function setDefaultOptions(OptionsResolverInterface $resolver)
    {
        $resolver->setDefaults(array(
            'data_class' => 'Crm\EquipoBundle\Entity\LicenciaEquipo'
        ));
    }

    /**
     * @return string
     */
    public function getName()
    {
        return 'crm_equipobundle_licenciaequipo';
    }
}


text:
class AddPolymorphicAssociationToComments < ActiveRecord::Migration
  def change
    change_table :messages do |t|
      t.references :messageable, :polymorphic => true
    end
  end
end


text:
class COptionsDlg;
class COptionsGeneralPage : public COptionsPage
{
// Konstruktion
public:
	COptionsGeneralPage(COptionsDlg *pOptionsDlg, CWnd* pParent = NULL);   // Standardkonstruktor

	virtual BOOL IsDataValid();
	virtual void SaveData();
	virtual void LoadData();

	// Dialogfelddaten
	//{{AFX_DATA(COptionsGeneralPage)
	enum { IDD = IDD_OPTIONS_GENERAL };
	CString	m_MaxUsers;
	CString	m_Port;
	CString	m_Threadnum;
	CString	m_Timeout;
	CString	m_NoTransferTimeout;
	CString	m_LoginTimeout;
	//}}AFX_DATA

// Überschreibungen
	// Vom Klassen-Assistenten generierte virtuelle Funktionsüberschreibungen
	//{{AFX_VIRTUAL(COptionsGeneralPage)
	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV-Unterstützung
	//}}AFX_VIRTUAL

// Implementierung
protected:

	// Generierte Nachrichtenzuordnungsfunktionen
	//{{AFX_MSG(COptionsGeneralPage)
		// HINWEIS: Der Klassen-Assistent fügt hier Member-Funktionen ein
	//}}AFX_MSG
	DECLARE_MESSAGE_MAP()
};

//{{AFX_INSERT_LOCATION}}
// Microsoft Visual C++ fügt unmittelbar vor der vorhergehenden Zeile zusätzliche Deklarationen ein.

#endif // AFX_OPTIONSGENERALPAGE_H__2198594C_33A4_4A87_A753_76FE8507A8F8__INCLUDED_


text:
const React = require("react");

class Footer extends React.Component {
  docUrl(doc, language) {
    const baseUrl = this.props.config.baseUrl;
    const docsUrl = this.props.config.docsUrl;
    const docsPart = `${docsUrl ? `${docsUrl}/` : ""}`;
    const langPart = "";
    return `${baseUrl}${docsPart}${langPart}${doc}`;
  }

  pageUrl(doc, language) {
    const baseUrl = this.props.config.baseUrl;
    return baseUrl + doc;
  }

  render() {
    return (

            {this.props.config.footerIcon && (

            )}

Documentation

              Guides

              Javadocs

Legal

              Disclaimer

            Policies

{this.props.config.copyright}

    );
  }
}

module.exports = Footer;


text:
package org.apache.jena.sparql.procedure.library;

import org.apache.jena.sparql.engine.ExecutionContext ;
import org.apache.jena.sparql.engine.QueryIterator ;
import org.apache.jena.sparql.engine.binding.Binding ;
import org.apache.jena.sparql.expr.ExprList ;
import org.apache.jena.sparql.procedure.ProcedureEval ;
import org.apache.jena.sparql.util.IterLib ;

public class debug extends ProcedureEval
{

    @Override
    public QueryIterator execEval(Binding binding, ExprList args, ExecutionContext execCxt)
    {
        System.out.println("Debug: "+args.toString()) ;
        return IterLib.result(binding, execCxt) ;
    }
}


text:
title: Overview
page_title: Server-side Programming Overview - RadStepper
description: Check our Web Forms article about Overview.
slug: stepper/server-side-programming/overview
tags: overview
published: True
position: 0
---

# Server-side Programming Overview

You can configure the settings of RadStepper and create its Steps in the code-behind via the Server-Side API of the control.

## RadStepper Public Properties and Methods

For a list with the server-side properties and methods of the control, see the [Server-Side API of the RadStepper class](https://docs.telerik.com/devtools/aspnet-ajax/api/server/Telerik.Web.UI/RadStepper). You can also find it in the IntelliSense in Visual Studio.

## Create a RadStepper in the Code-behind:

````ASP.NET
<asp:PlaceHolder ID="PlaceHolder1" runat="server"></asp:PlaceHolder>
````

````C#
protected void Page_Init(object sender, EventArgs e)
{
    var stepper = new RadStepper();
    stepper.ID = "RadStepper1";
    stepper.Skin = "Silk";
    stepper.Linear = false;
    stepper.Orientation = StepperOrientation.Vertical;
    stepper.DataBinding += new EventHandler(RadStepper1_DataBinding);
    stepper.Load += new EventHandler(RadStepper1_Load);

    PlaceHolder1.Controls.Add(stepper);
}

protected void RadStepper1_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        (sender as RadStepper).DataBind();
    }
}

protected void RadStepper1_DataBinding(object sender, EventArgs e)
{
    var stepper = (sender as RadStepper);
    stepper.Steps.AddRange(GetStepperSteps(null));
}

private IEnumerable<StepperStep> GetStepperSteps(object dataSource)
{
    var result = new List<StepperStep>();

    result.Add(new StepperStep() { Label = "Home", Icon = "home", Error = true });
    result.Add(new StepperStep() { Label = "Settings", Icon = "gear", Enabled = false });
    result.Add(new StepperStep() { Label = "Attachments", Icon = "attachment", Selected = true });
    result.Add(new StepperStep() { Label = "Save", Icon = "save" });

    return result;
}
````
````VB
Protected Sub Page_Init(ByVal sender As Object, ByVal e As EventArgs) Handles Me.Init
    Dim stepper = New RadStepper()
    stepper.ID = "RadStepper1"
    stepper.Skin = "Silk"
    stepper.Linear = False
    stepper.Orientation = StepperOrientation.Vertical
    AddHandler stepper.Load, AddressOf RadStepper1_Load
    AddHandler stepper.DataBinding, AddressOf RadStepper1_DataBinding
    PlaceHolder1.Controls.Add(stepper)
End Sub

Protected Sub RadStepper1_Load(ByVal sender As Object, ByVal e As EventArgs)
    If Not IsPostBack Then
        TryCast(sender, RadStepper).DataBind()
    End If
End Sub

Protected Sub RadStepper1_DataBinding(ByVal sender As Object, ByVal e As EventArgs)
    Dim stepper = TryCast(sender, RadStepper)
    stepper.Steps.AddRange(GetStepperSteps(Nothing))
End Sub

Private Function GetStepperSteps(ByVal dataSource As Object) As IEnumerable(Of StepperStep)
    Dim result = New List(Of StepperStep)()
    result.Add(New StepperStep() With {
        .Label = "Home",
        .Icon = "home",
        .[Error] = True
    })
    result.Add(New StepperStep() With {
        .Label = "Settings",
        .Icon = "gear",
        .Enabled = False
    })
    result.Add(New StepperStep() With {
        .Label = "Attachments",
        .Icon = "attachment",
        .Selected = True
    })
    result.Add(New StepperStep() With {
        .Label = "Save",
        .Icon = "save"
    })
    Return result
End Function
````

# See Also

 * [Server-Side API of the RadStepper class](https://docs.telerik.com/devtools/aspnet-ajax/api/server/Telerik.Web.UI/RadStepper)


text:
package com.aep.domain;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Email {

	private String Id;
	private String address;
	private boolean isValid;

	public Email() {
		super();
	}

	public Email(String id, String address, boolean isValid) {
		this();
		Id = id;
		this.address = address;
		this.isValid = isValid;
	}

	public String getId() {
		return Id;
	}

	public void setId(String id) {
		Id = id;
	}

	public String getAddress() {
		return address;
	}

	public void setAddress(String address) {
		this.address = address;
	}

	public boolean isValid() {
		return isValid;
	}

	public void setValid(boolean isValid) {
		this.isValid = isValid;
	}
}


text:
#ifndef _GAMMA_TRIS_H
#define _GAMMA_TRIS_H

extern void gammaDDTrifuncInit(void);
extern void gammaDDChooseTriRenderState(GLcontext *);

#endif /* !(_GAMMA_TRIS_H) */


text:
package org.apache.camel.component.timer;

import java.util.Date;
import java.util.Timer;

import org.apache.camel.Component;
import org.apache.camel.Consumer;
import org.apache.camel.MultipleConsumersSupport;
import org.apache.camel.Processor;
import org.apache.camel.Producer;
import org.apache.camel.RuntimeCamelException;
import org.apache.camel.api.management.ManagedAttribute;
import org.apache.camel.api.management.ManagedResource;
import org.apache.camel.impl.DefaultEndpoint;
import org.apache.camel.spi.Metadata;
import org.apache.camel.spi.UriEndpoint;
import org.apache.camel.spi.UriParam;
import org.apache.camel.spi.UriPath;

/**
 * Represents a timer endpoint that can generate periodic inbound exchanges triggered by a timer.
 *
 * @version
 */
@ManagedResource(description = "Managed TimerEndpoint")
@UriEndpoint(scheme = "timer", syntax = "timer:timerName", consumerOnly = true, consumerClass = TimerConsumer.class, label = "core,scheduling")
public class TimerEndpoint extends DefaultEndpoint implements MultipleConsumersSupport {
    @UriPath @Metadata(required = "true")
    private String timerName;
    @UriParam
    private Date time;
    @UriParam(defaultValue = "1000")
    private long period = 1000;
    @UriParam(defaultValue = "1000")
    private long delay = 1000;
    @UriParam
    private boolean fixedRate;
    @UriParam(defaultValue = "true")
    private boolean daemon = true;
    @UriParam(defaultValue = "0")
    private long repeatCount;
    @UriParam
    private Timer timer;

    public TimerEndpoint() {
    }

    public TimerEndpoint(String uri, Component component, String timerName) {
        super(uri, component);
        this.timerName = timerName;
    }

    protected TimerEndpoint(String endpointUri, Component component) {
        super(endpointUri, component);
    }

    @Override
    public TimerComponent getComponent() {
        return (TimerComponent) super.getComponent();
    }

    public Producer createProducer() throws Exception {
        throw new RuntimeCamelException("Cannot produce to a TimerEndpoint: " + getEndpointUri());
    }

    public Consumer createConsumer(Processor processor) throws Exception {
        Consumer answer = new TimerConsumer(this, processor);
        configureConsumer(answer);
        return answer;
    }

    @Override
    protected void doStart() throws Exception {
        super.doStart();
        // do nothing, the timer will be set when the first consumer will request it
    }

    @Override
    protected void doStop() throws Exception {
        setTimer(null);
        super.doStop();
    }

    @ManagedAttribute
    public boolean isMultipleConsumersSupported() {
        return true;
    }

    @ManagedAttribute(description = "Timer Name")
    public String getTimerName() {
        if (timerName == null) {
            timerName = getEndpointUri();
        }
        return timerName;
    }

    /**
     * The name of the timer
     */
    @ManagedAttribute(description = "Timer Name")
    public void setTimerName(String timerName) {
        this.timerName = timerName;
    }

    @ManagedAttribute(description = "Timer Daemon")
    public boolean isDaemon() {
        return daemon;
    }

    /**
     * Specifies whether or not the thread associated with the timer endpoint runs as a daemon.
     *

     * The default value is true.
     */
    @ManagedAttribute(description = "Timer Daemon")
    public void setDaemon(boolean daemon) {
        this.daemon = daemon;
    }

    @ManagedAttribute(description = "Timer Delay")
    public long getDelay() {
        return delay;
    }

    /**
     * The number of milliseconds to wait before the first event is generated. Should not be used in conjunction with the time option.
     *

     * The default value is 1000.
     */
    @ManagedAttribute(description = "Timer Delay")
    public void setDelay(long delay) {
        this.delay = delay;
    }

    @ManagedAttribute(description = "Timer FixedRate")
    public boolean isFixedRate() {
        return fixedRate;
    }

    /**
     * Events take place at approximately regular intervals, separated by the specified period.
     */
    @ManagedAttribute(description = "Timer FixedRate")
    public void setFixedRate(boolean fixedRate) {
        this.fixedRate = fixedRate;
    }

    @ManagedAttribute(description = "Timer Period")
    public long getPeriod() {
        return period;
    }

    /**
     * If greater than 0, generate periodic events every period milliseconds.
     *

     * The default value is 1000.
     */
    @ManagedAttribute(description = "Timer Period")
    public void setPeriod(long period) {
        this.period = period;
    }

    @ManagedAttribute(description = "Repeat Count")
    public long getRepeatCount() {
        return repeatCount;
    }

    /**
     * Specifies a maximum limit of number of fires.
     * So if you set it to 1, the timer will only fire once.
     * If you set it to 5, it will only fire five times.
     * A value of zero or negative means fire forever.
     */
    @ManagedAttribute(description = "Repeat Count")
    public void setRepeatCount(long repeatCount) {
        this.repeatCount = repeatCount;
    }

    public Date getTime() {
        return time;
    }

    /**
     * A java.util.Date the first event should be generated. If using the URI, the pattern expected is: yyyy-MM-dd HH:mm:ss or yyyy-MM-dd'T'HH:mm:ss.
     */
    public void setTime(Date time) {
        this.time = time;
    }

    @ManagedAttribute(description = "Singleton")
    public boolean isSingleton() {
        return true;
    }

    @ManagedAttribute(description = "Camel id")
    public String getCamelId() {
        return this.getCamelContext().getName();
    }

    @ManagedAttribute(description = "Camel ManagementName")
    public String getCamelManagementName() {
        return this.getCamelContext().getManagementName();
    }

    @ManagedAttribute(description = "Endpoint Uri")
    public String getEndpointUri() {
        return super.getEndpointUri();
    }

    @ManagedAttribute(description = "Endpoint State")
    public String getState() {
        return getStatus().name();
    }

    public Timer getTimer(TimerConsumer consumer) {
        if (timer != null) {
            // use custom timer
            return timer;
        }
        return getComponent().getTimer(consumer);
    }

    /**
     * To use a custom {@link Timer}
     */
    public void setTimer(Timer timer) {
        this.timer = timer;
    }

    public void removeTimer(TimerConsumer consumer) {
        if (timer == null) {
            // only remove timer if we are not using a custom timer
            getComponent().removeTimer(consumer);
        }
    }

}


text:
import { Type } from '@angular/core';
import { TagComponent } from './tag.component';
import { TagDetailComponent } from './tag-detail.component';

export * from './tag.component';
export * from './tag-detail.component';

export const TAG_DIRECTIVES: Type<any>[] = [
  TagComponent,
  TagDetailComponent
];


text:
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class AddUserColumnToBookmarksTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('bookmarks', function (Blueprint $table) {
            $table->unsignedInteger('user_id');
            $table->foreign('user_id')->references('id')->on('users');
            $table->dropIndex('bookmarks_parent_id_index');
            $table->dropUnique('bookmarks_page_id_unique');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('bookmarks', function (Blueprint $table) {

            $table->dropForeign('bookmarks_user_id_foreign');

            $table->dropColumn('user_id');

            $table->index('parent_id');
            $table->unique('page_id');
        });
    }
}


text:
package org.slc.sli.sif.domain.converter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import openadk.library.common.GradeLevel;
import openadk.library.common.GradeLevelCode;
import openadk.library.common.GradeLevels;

import org.springframework.stereotype.Component;

/**
 * A customized converter to convert SIF GradeLevels to SLI gradesOffered.
 *
 * SLI values:
 * Adult Education
 * Early Education
 * Eighth grade
 * Eleventh grade
 * Fifth grade
 * First grade
 * Fourth grade
 * Grade 13
 * Infant/toddler
 * Kindergarten
 * Ninth grade
 * Other
 * Postsecondary
 * Preschool/Prekindergarten
 * Second grade
 * Seventh grade
 * Sixth grade
 * Tenth grade
 * Third grade
 * Transitional Kindergarten
 * Twelfth grade
 * Ungraded
 * Not Available
 *
 * @author slee
 *
 */
@Component
public class GradeLevelsConverter {

    private static final Map<GradeLevelCode, String> GRADE_LEVEL_CODE_MAP = new HashMap<GradeLevelCode, String>();
    static {
        GRADE_LEVEL_CODE_MAP.put(GradeLevelCode._01, "First grade");
        GRADE_LEVEL_CODE_MAP.put(GradeLevelCode._02, "Second grade");
        GRADE_LEVEL_CODE_MAP.put(GradeLevelCode._03, "Third grade");
        GRADE_LEVEL_CODE_MAP.put(GradeLevelCode._04, "Fourth grade");
        GRADE_LEVEL_CODE_MAP.put(GradeLevelCode._05, "Fifth grade");
        GRADE_LEVEL_CODE_MAP.put(GradeLevelCode._06, "Sixth grade");
        GRADE_LEVEL_CODE_MAP.put(GradeLevelCode._07, "Seventh grade");
        GRADE_LEVEL_CODE_MAP.put(GradeLevelCode._08, "Eighth grade");
        GRADE_LEVEL_CODE_MAP.put(GradeLevelCode._09, "Ninth grade");
        GRADE_LEVEL_CODE_MAP.put(GradeLevelCode._10, "Tenth grade");
        GRADE_LEVEL_CODE_MAP.put(GradeLevelCode._11, "Eleventh grade");
        GRADE_LEVEL_CODE_MAP.put(GradeLevelCode._12, "Twelfth grade");
        GRADE_LEVEL_CODE_MAP.put(GradeLevelCode.KG, "Kindergarten");
        GRADE_LEVEL_CODE_MAP.put(GradeLevelCode.OTHER, "Other");
        // SIF defines PG as Postgraduate/Adult, could be SLI Postsecondary or Adult Education
        GRADE_LEVEL_CODE_MAP.put(GradeLevelCode.PG, "Postsecondary");
        GRADE_LEVEL_CODE_MAP.put(GradeLevelCode.PK, "Preschool/Prekindergarten");
        GRADE_LEVEL_CODE_MAP.put(GradeLevelCode.UN, "Ungraded");
        GRADE_LEVEL_CODE_MAP.put(GradeLevelCode.UNKNOWN, "Not Available");
    }

    public List<String> convert(GradeLevels source) {
        if (source == null) {
            return null;
        }

        return toSliGradeList(source.getGradeLevels());
    }

    public String convert(GradeLevel source) {
        if (source == null) {
            return null;
        }
        return toSliGrade(GradeLevelCode.wrap(source.getCode()));
    }

    private List<String> toSliGradeList(GradeLevel[] gradeLevels) {
        List<String> list = new ArrayList<String>(gradeLevels.length);
        for (GradeLevel gradeLevel : gradeLevels) {
            list.add(convert(gradeLevel));
        }
        return list;
    }

    private String toSliGrade(GradeLevelCode gradeCode) {
        String mapping = GRADE_LEVEL_CODE_MAP.get(gradeCode);
        return mapping == null ? "Not Available" : mapping;
    }
}


text:
<?xml version="1.0" encoding="ascii"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
          "DTD/xhtml1-transitional.dtd">

  <title>lxml.etree.XSLTAccessControl</title>
  <link rel="stylesheet" href="epydoc.css" type="text/css" />

         Home

         Trees

         Indices

         Help

lxml API

        Package lxml ::
        Module etree ::
        Class XSLTAccessControl

[hide private]

[frames] | no frames]

Class XSLTAccessControl

object --+
         |
        XSLTAccessControl

XSLTAccessControl(self, read_file=True, write_file=True, create_dir=True, read_network=True, write_network=True)

Access control for XSLT: reading/writing files, directories and
network I/O.  Access to a type of resource is granted or denied by
passing any of the following boolean keyword arguments.  All of
them default to True to allow access.

read_file

write_file

create_dir

read_network

write_network

For convenience, there is also a class member DENY_ALL that
provides an XSLTAccessControl instance that is readily configured
to deny everything, and a DENY_WRITE member that denies all
write access but allows read access.

See XSLT.

        Instance Methods
        [hide private]

      a new object with type S, a subtype of T

          __new__(T,
        S,
        ...)

          __repr__(x)

      repr(x)

Inherited from object:
      __delattr__,
      __format__,
      __getattribute__,
      __hash__,
      __init__,
      __reduce__,
      __reduce_ex__,
      __setattr__,
      __sizeof__,
      __str__,
      __subclasshook__

        Class Variables
        [hide private]

        DENY_ALL = XSLTAccessControl(create_dir=False, read_file=False...

        DENY_WRITE = XSLTAccessControl(create_dir=False, read_file=Tru...

        Properties
        [hide private]

        options

      The access control configuration as a map of options.

Inherited from object:
      __class__

        Method Details
        [hide private]

__new__(T,
        S,
        ...)

Returns: a new object with type S, a subtype of T

Overrides:
        object.__new__

__repr__(x)

(Representation operator)

  repr(x)

Overrides:
        object.__repr__

        Class Variable Details
        [hide private]

DENY_ALL

Value:

XSLTAccessControl(create_dir=False, read_file=False, read_network=Fals
e, write_file=False, write_network=False)

DENY_WRITE

Value:

XSLTAccessControl(create_dir=False, read_file=True, read_network=True,
 write_file=False, write_network=False)

         Home

         Trees

         Indices

         Help

lxml API

    Generated by Epydoc 3.0.1 on Mon Mar 26 15:26:08 2012

      http://epydoc.sourceforge.net


text:
// Package config knows how to read and parse config.yaml.
package config

import (
	"bytes"
	"compress/gzip"
	"errors"
	"fmt"
	"io/ioutil"
	"net/url"
	"os"
	"path/filepath"
	"regexp"
	"strings"
	"text/template"
	"time"

	"github.com/sirupsen/logrus"
	cron "gopkg.in/robfig/cron.v2"
	v1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/labels"
	"k8s.io/apimachinery/pkg/util/sets"
	"k8s.io/apimachinery/pkg/util/validation"
	"sigs.k8s.io/yaml"

	buildapi "github.com/knative/build/pkg/apis/build/v1alpha1"
	prowapi "k8s.io/test-infra/prow/apis/prowjobs/v1"
	"k8s.io/test-infra/prow/config/org"
	"k8s.io/test-infra/prow/github"
	"k8s.io/test-infra/prow/kube"
	"k8s.io/test-infra/prow/pod-utils/decorate"
	"k8s.io/test-infra/prow/pod-utils/downwardapi"
)

const (
	// DefaultJobTimeout represents the default deadline for a prow job.
	DefaultJobTimeout = 24 * time.Hour
)

// Config is a read-only snapshot of the config.
type Config struct {
	JobConfig
	ProwConfig
}

// JobConfig is config for all prow jobs
type JobConfig struct {
	// Presets apply to all job types.
	Presets []Preset `json:"presets,omitempty"`
	// Full repo name (such as "kubernetes/kubernetes") -> list of jobs.
	Presubmits  map[string][]Presubmit  `json:"presubmits,omitempty"`
	Postsubmits map[string][]Postsubmit `json:"postsubmits,omitempty"`

	// Periodics are not associated with any repo.
	Periodics []Periodic `json:"periodics,omitempty"`
}

// ProwConfig is config for all prow controllers
type ProwConfig struct {
	Tide             Tide                  `json:"tide,omitempty"`
	Plank            Plank                 `json:"plank,omitempty"`
	Sinker           Sinker                `json:"sinker,omitempty"`
	Deck             Deck                  `json:"deck,omitempty"`
	BranchProtection BranchProtection      `json:"branch-protection,omitempty"`
	Orgs             map[string]org.Config `json:"orgs,omitempty"`
	Gerrit           Gerrit                `json:"gerrit,omitempty"`
	GitHubReporter   GitHubReporter        `json:"github_reporter,omitempty"`

	// TODO: Move this out of the main config.
	JenkinsOperators []JenkinsOperator `json:"jenkins_operators,omitempty"`

	// ProwJobNamespace is the namespace in the cluster that prow
	// components will use for looking up ProwJobs. The namespace
	// needs to exist and will not be created by prow.
	// Defaults to "default".
	ProwJobNamespace string `json:"prowjob_namespace,omitempty"`
	// PodNamespace is the namespace in the cluster that prow
	// components will use for looking up Pods owned by ProwJobs.
	// The namespace needs to exist and will not be created by prow.
	// Defaults to "default".
	PodNamespace string `json:"pod_namespace,omitempty"`

	// LogLevel enables dynamically updating the log level of the
	// standard logger that is used by all prow components.
	//
	// Valid values:
	//
	// "debug", "info", "warn", "warning", "error", "fatal", "panic"
	//
	// Defaults to "info".
	LogLevel string `json:"log_level,omitempty"`

	// PushGateway is a prometheus push gateway.
	PushGateway PushGateway `json:"push_gateway,omitempty"`

	// OwnersDirBlacklist is used to configure which directories to ignore when
	// searching for OWNERS{,_ALIAS} files in a repo.
	OwnersDirBlacklist OwnersDirBlacklist `json:"owners_dir_blacklist,omitempty"`

	// Pub/Sub Subscriptions that we want to listen to
	PubSubSubscriptions PubsubSubscriptions `json:"pubsub_subscriptions,omitempty"`

	// GitHubOptions allows users to control how prow applications display GitHub website links.
	GitHubOptions GitHubOptions `json:"github,omitempty"`

	// StatusErrorLink is the url that will be used for jenkins prowJobs that can't be
	// found, or have another generic issue. The default that will be used if this is not set
	// is: https://github.com/kubernetes/test-infra/issues
	StatusErrorLink string `json:"status_error_link,omitempty"`

	// DefaultJobTimeout this is default deadline for prow jobs. This value is used when
	// no timeout is configured at the job level. This value is set to 24 hours.
	DefaultJobTimeout time.Duration `json:"default_job_timeout,omitempty"`
}

// OwnersDirBlacklist is used to configure which directories to ignore when
// searching for OWNERS{,_ALIAS} files in a repo.
type OwnersDirBlacklist struct {
	// Repos configures a directory blacklist per repo (or org)
	Repos map[string][]string `json:"repos"`
	// Default configures a default blacklist for repos (or orgs) not
	// specifically configured
	Default []string `json:"default"`
}

// DirBlacklist returns directories which are used to ignore when
// searching for OWNERS{,_ALIAS} files in a repo.
func (ownersDirBlacklist OwnersDirBlacklist) DirBlacklist(org, repo string) (blacklist []string) {
	blacklist = append(blacklist, ownersDirBlacklist.Default...)
	if bl, ok := ownersDirBlacklist.Repos[org]; ok {
		blacklist = append(blacklist, bl...)
	}
	if bl, ok := ownersDirBlacklist.Repos[org+"/"+repo]; ok {
		blacklist = append(blacklist, bl...)
	}
	return
}

// PushGateway is a prometheus push gateway.
type PushGateway struct {
	// Endpoint is the location of the prometheus pushgateway
	// where prow will push metrics to.
	Endpoint string `json:"endpoint,omitempty"`
	// IntervalString compiles into Interval at load time.
	IntervalString string `json:"interval,omitempty"`
	// Interval specifies how often prow will push metrics
	// to the pushgateway. Defaults to 1m.
	Interval time.Duration `json:"-"`
}

// Controller holds configuration applicable to all agent-specific
// prow controllers.
type Controller struct {
	// JobURLTemplateString compiles into JobURLTemplate at load time.
	JobURLTemplateString string `json:"job_url_template,omitempty"`
	// JobURLTemplate is compiled at load time from JobURLTemplateString. It
	// will be passed a prowapi.ProwJob and is used to set the URL for the
	// "Details" link on GitHub as well as the link from deck.
	JobURLTemplate *template.Template `json:"-"`

	// ReportTemplateString compiles into ReportTemplate at load time.
	ReportTemplateString string `json:"report_template,omitempty"`
	// ReportTemplate is compiled at load time from ReportTemplateString. It
	// will be passed a prowapi.ProwJob and can provide an optional blurb below
	// the test failures comment.
	ReportTemplate *template.Template `json:"-"`

	// MaxConcurrency is the maximum number of tests running concurrently that
	// will be allowed by the controller. 0 implies no limit.
	MaxConcurrency int `json:"max_concurrency,omitempty"`

	// MaxGoroutines is the maximum number of goroutines spawned inside the
	// controller to handle tests. Defaults to 20. Needs to be a positive
	// number.
	MaxGoroutines int `json:"max_goroutines,omitempty"`

	// AllowCancellations enables aborting presubmit jobs for commits that
	// have been superseded by newer commits in GitHub pull requests.
	AllowCancellations bool `json:"allow_cancellations,omitempty"`
}

// Plank is config for the plank controller.
type Plank struct {
	Controller `json:",inline"`
	// PodPendingTimeoutString compiles into PodPendingTimeout at load time.
	PodPendingTimeoutString string `json:"pod_pending_timeout,omitempty"`
	// PodPendingTimeout is after how long the controller will perform a garbage
	// collection on pending pods. Defaults to one day.
	PodPendingTimeout time.Duration `json:"-"`
	// DefaultDecorationConfig are defaults for shared fields for ProwJobs
	// that request to have their PodSpecs decorated
	DefaultDecorationConfig *prowapi.DecorationConfig `json:"default_decoration_config,omitempty"`
	// Deprecated, use JobURLPrefixConfig instead
	// JobURLPrefix is the host and path prefix under
	// which job details will be viewable
	// TODO @alvaroaleman: Remove in September 2019
	JobURLPrefix string `json:"job_url_prefix,omitempty"`
	// JobURLPrefixConfig is the host and path prefix under which job details
	// will be viewable. Use `org/repo`, `org` or `*`as key and an url as value
	JobURLPrefixConfig map[string]string `json:"job_url_prefix_config,omitempty"`
}

func (p Plank) GetJobURLPrefix(refs *prowapi.Refs) string {
	if refs == nil {
		return p.JobURLPrefixConfig["*"]
	}
	if p.JobURLPrefixConfig[fmt.Sprintf("%s/%s", refs.Org, refs.Repo)] != "" {
		return p.JobURLPrefixConfig[fmt.Sprintf("%s/%s", refs.Org, refs.Repo)]
	}
	if p.JobURLPrefixConfig[refs.Org] != "" {
		return p.JobURLPrefixConfig[refs.Org]
	}
	return p.JobURLPrefixConfig["*"]
}

// Gerrit is config for the gerrit controller.
type Gerrit struct {
	// TickInterval is how often we do a sync with binded gerrit instance
	TickIntervalString string        `json:"tick_interval,omitempty"`
	TickInterval       time.Duration `json:"-"`
	// RateLimit defines how many changes to query per gerrit API call
	// default is 5
	RateLimit int `json:"ratelimit,omitempty"`
}

// JenkinsOperator is config for the jenkins-operator controller.
type JenkinsOperator struct {
	Controller `json:",inline"`
	// LabelSelectorString compiles into LabelSelector at load time.
	// If set, this option needs to match --label-selector used by
	// the desired jenkins-operator. This option is considered
	// invalid when provided with a single jenkins-operator config.
	//
	// For label selector syntax, see below:
	// https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors
	LabelSelectorString string `json:"label_selector,omitempty"`
	// LabelSelector is used so different jenkins-operator replicas
	// can use their own configuration.
	LabelSelector labels.Selector `json:"-"`
}

// GitHubReporter holds the config for report behavior in github
type GitHubReporter struct {
	// JobTypesToReport is used to determine which type of prowjob
	// should be reported to github
	//
	// defaults to presubmit job only.
	// Will default to both presubmit and postsubmit jobs by April.1st.2019
	JobTypesToReport []prowapi.ProwJobType `json:"job_types_to_report,omitempty"`
}

// Sinker is config for the sinker controller.
type Sinker struct {
	// ResyncPeriodString compiles into ResyncPeriod at load time.
	ResyncPeriodString string `json:"resync_period,omitempty"`
	// ResyncPeriod is how often the controller will perform a garbage
	// collection. Defaults to one hour.
	ResyncPeriod time.Duration `json:"-"`
	// MaxProwJobAgeString compiles into MaxProwJobAge at load time.
	MaxProwJobAgeString string `json:"max_prowjob_age,omitempty"`
	// MaxProwJobAge is how old a ProwJob can be before it is garbage-collected.
	// Defaults to one week.
	MaxProwJobAge time.Duration `json:"-"`
	// MaxPodAgeString compiles into MaxPodAge at load time.
	MaxPodAgeString string `json:"max_pod_age,omitempty"`
	// MaxPodAge is how old a Pod can be before it is garbage-collected.
	// Defaults to one day.
	MaxPodAge time.Duration `json:"-"`
}

// Spyglass holds config for Spyglass
type Spyglass struct {
	// Viewers is a map of Regexp strings to viewer names that defines which sets
	// of artifacts need to be consumed by which viewers. The keys are compiled
	// and stored in RegexCache at load time.
	Viewers map[string][]string `json:"viewers,omitempty"`
	// RegexCache is a map of viewer regexp strings to their compiled equivalents.
	RegexCache map[string]*regexp.Regexp `json:"-"`
	// SizeLimit is the max size artifact in bytes that Spyglass will attempt to
	// read in entirety. This will only affect viewers attempting to use
	// artifact.ReadAll(). To exclude outlier artifacts, set this limit to
	// expected file size + variance. To include all artifacts with high
	// probability, use 2*maximum observed artifact size.
	SizeLimit int64 `json:"size_limit,omitempty"`
	// GCSBrowserPrefix is used to generate a link to a human-usable GCS browser.
	// If left empty, the link will be not be shown. Otherwise, a GCS path (with no
	// prefix or scheme) will be appended to GCSBrowserPrefix and shown to the user.
	GCSBrowserPrefix string `json:"gcs_browser_prefix,omitempty"`
	// If set, Announcement is used as a Go HTML template string to be displayed at the top of
	// each spyglass page. Using HTML in the template is acceptable.
	// Currently the only variable available is .ArtifactPath, which contains the GCS path for the job artifacts.
	Announcement string `json:"announcement,omitempty"`
	// TestGridConfig is the path to the TestGrid config proto. If the path begins with
	// "gs://" it is assumed to be a GCS reference, otherwise it is read from the local filesystem.
	// If left blank, TestGrid links will not appear.
	TestGridConfig string `json:"testgrid_config,omitempty"`
	// TestGridRoot is the root URL to the TestGrid frontend, e.g. "https://testgrid.k8s.io/".
	// If left blank, TestGrid links will not appear.
	TestGridRoot string `json:"testgrid_root,omitempty"`
}

// Deck holds config for deck.
type Deck struct {
	// Spyglass specifies which viewers will be used for which artifacts when viewing a job in Deck
	Spyglass Spyglass `json:"spyglass,omitempty"`
	// TideUpdatePeriodString compiles into TideUpdatePeriod at load time.
	TideUpdatePeriodString string `json:"tide_update_period,omitempty"`
	// TideUpdatePeriod specifies how often Deck will fetch status from Tide. Defaults to 10s.
	TideUpdatePeriod time.Duration `json:"-"`
	// HiddenRepos is a list of orgs and/or repos that should not be displayed by Deck.
	HiddenRepos []string `json:"hidden_repos,omitempty"`
	// ExternalAgentLogs ensures external agents can expose
	// their logs in prow.
	ExternalAgentLogs []ExternalAgentLog `json:"external_agent_logs,omitempty"`
	// Branding of the frontend
	Branding *Branding `json:"branding,omitempty"`
	// GoogleAnalytics, if specified, include a Google Analytics tracking code on each page.
	GoogleAnalytics string `json:"google_analytics,omitempty"`
}

// ExternalAgentLog ensures an external agent like Jenkins can expose
// its logs in prow.
type ExternalAgentLog struct {
	// Agent is an external prow agent that supports exposing
	// logs via deck.
	Agent string `json:"agent,omitempty"`
	// SelectorString compiles into Selector at load time.
	SelectorString string `json:"selector,omitempty"`
	// Selector can be used in prow deployments where the workload has
	// been sharded between controllers of the same agent. For more info
	// see https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#label-selectors
	Selector labels.Selector `json:"-"`
	// URLTemplateString compiles into URLTemplate at load time.
	URLTemplateString string `json:"url_template,omitempty"`
	// URLTemplate is compiled at load time from URLTemplateString. It
	// will be passed a prowapi.ProwJob and the generated URL should provide
	// logs for the ProwJob.
	URLTemplate *template.Template `json:"-"`
}

// Branding holds branding configuration for deck.
type Branding struct {
	// Logo is the location of the logo that will be loaded in deck.
	Logo string `json:"logo,omitempty"`
	// Favicon is the location of the favicon that will be loaded in deck.
	Favicon string `json:"favicon,omitempty"`
	// BackgroundColor is the color of the background.
	BackgroundColor string `json:"background_color,omitempty"`
	// HeaderColor is the color of the header.
	HeaderColor string `json:"header_color,omitempty"`
}

// PubSubSubscriptions maps GCP projects to a list of Topics.
type PubsubSubscriptions map[string][]string

// GitHubOptions allows users to control how prow applications display GitHub website links.
type GitHubOptions struct {
	// LinkURLFromConfig is the string representation of the link_url config parameter.
	// This config parameter allows users to override the default GitHub link url for all plugins.
	// If this option is not set, we assume "https://github.com".
	LinkURLFromConfig string `json:"link_url,omitempty"`

	// LinkURL is the url representation of LinkURLFromConfig. This variable should be used
	// in all places internally.
	LinkURL *url.URL
}

// Load loads and parses the config at path.
func Load(prowConfig, jobConfig string) (c *Config, err error) {
	// we never want config loading to take down the prow components
	defer func() {
		if r := recover(); r != nil {
			c, err = nil, fmt.Errorf("panic loading config: %v", r)
		}
	}()
	c, err = loadConfig(prowConfig, jobConfig)
	if err != nil {
		return nil, err
	}
	if err := c.finalizeJobConfig(); err != nil {
		return nil, err
	}
	if err := c.validateComponentConfig(); err != nil {
		return nil, err
	}
	if err := c.validateJobConfig(); err != nil {
		return nil, err
	}
	return c, nil
}

// loadConfig loads one or multiple config files and returns a config object.
func loadConfig(prowConfig, jobConfig string) (*Config, error) {
	stat, err := os.Stat(prowConfig)
	if err != nil {
		return nil, err
	}

	if stat.IsDir() {
		return nil, fmt.Errorf("prowConfig cannot be a dir - %s", prowConfig)
	}

	var nc Config
	if err := yamlToConfig(prowConfig, &nc); err != nil {
		return nil, err
	}
	if err := parseProwConfig(&nc); err != nil {
		return nil, err
	}

	// TODO(krzyzacy): temporary allow empty jobconfig
	//                 also temporary allow job config in prow config
	if jobConfig == "" {
		return &nc, nil
	}

	stat, err = os.Stat(jobConfig)
	if err != nil {
		return nil, err
	}

	if !stat.IsDir() {
		// still support a single file
		var jc JobConfig
		if err := yamlToConfig(jobConfig, &jc); err != nil {
			return nil, err
		}
		if err := nc.mergeJobConfig(jc); err != nil {
			return nil, err
		}
		return &nc, nil
	}

	// we need to ensure all config files have unique basenames,
	// since updateconfig plugin will use basename as a key in the configmap
	uniqueBasenames := sets.String{}

	err = filepath.Walk(jobConfig, func(path string, info os.FileInfo, err error) error {
		if err != nil {
			logrus.WithError(err).Errorf("walking path %q.", path)
			// bad file should not stop us from parsing the directory
			return nil
		}

		if strings.HasPrefix(info.Name(), "..") {
			// kubernetes volumes also include files we
			// should not look be looking into for keys
			if info.IsDir() {
				return filepath.SkipDir
			}
			return nil
		}

		if filepath.Ext(path) != ".yaml" && filepath.Ext(path) != ".yml" {
			return nil
		}

		if info.IsDir() {
			return nil
		}

		base := filepath.Base(path)
		if uniqueBasenames.Has(base) {
			return fmt.Errorf("duplicated basename is not allowed: %s", base)
		}
		uniqueBasenames.Insert(base)

		var subConfig JobConfig
		if err := yamlToConfig(path, &subConfig); err != nil {
			return err
		}
		return nc.mergeJobConfig(subConfig)
	})

	if err != nil {
		return nil, err
	}

	return &nc, nil
}

// yamlToConfig converts a yaml file into a Config object
func yamlToConfig(path string, nc interface{}) error {
	b, err := ReadFileMaybeGZIP(path)
	if err != nil {
		return fmt.Errorf("error reading %s: %v", path, err)
	}
	if err := yaml.Unmarshal(b, nc); err != nil {
		return fmt.Errorf("error unmarshaling %s: %v", path, err)
	}
	var jc *JobConfig
	switch v := nc.(type) {
	case *JobConfig:
		jc = v
	case *Config:
		jc = &v.JobConfig
	}
	for rep := range jc.Presubmits {
		var fix func(*Presubmit)
		fix = func(job *Presubmit) {
			job.SourcePath = path
		}
		for i := range jc.Presubmits[rep] {
			fix(&jc.Presubmits[rep][i])
		}
	}
	for rep := range jc.Postsubmits {
		var fix func(*Postsubmit)
		fix = func(job *Postsubmit) {
			job.SourcePath = path
		}
		for i := range jc.Postsubmits[rep] {
			fix(&jc.Postsubmits[rep][i])
		}
	}

	var fix func(*Periodic)
	fix = func(job *Periodic) {
		job.SourcePath = path
	}
	for i := range jc.Periodics {
		fix(&jc.Periodics[i])
	}
	return nil
}

// ReadFileMaybeGZIP wraps ioutil.ReadFile, returning the decompressed contents
// if the file is gzipped, or otherwise the raw contents
func ReadFileMaybeGZIP(path string) ([]byte, error) {
	b, err := ioutil.ReadFile(path)
	if err != nil {
		return nil, err
	}
	// check if file contains gzip header: http://www.zlib.org/rfc-gzip.html
	if !bytes.HasPrefix(b, []byte("\x1F\x8B")) {
		// go ahead and return the contents if not gzipped
		return b, nil
	}
	// otherwise decode
	gzipReader, err := gzip.NewReader(bytes.NewBuffer(b))
	if err != nil {
		return nil, err
	}
	return ioutil.ReadAll(gzipReader)
}

// mergeConfig merges two JobConfig together
// It will try to merge:
//	- Presubmits
//	- Postsubmits
// 	- Periodics
//	- PodPresets
func (c *Config) mergeJobConfig(jc JobConfig) error {
	// Merge everything
	// *** Presets ***
	c.Presets = append(c.Presets, jc.Presets...)

	// validate no duplicated preset key-value pairs
	validLabels := map[string]bool{}
	for _, preset := range c.Presets {
		for label, val := range preset.Labels {
			pair := label + ":" + val
			if _, ok := validLabels[pair]; ok {
				return fmt.Errorf("duplicated preset 'label:value' pair : %s", pair)
			}
			validLabels[pair] = true
		}
	}

	// *** Periodics ***
	c.Periodics = append(c.Periodics, jc.Periodics...)

	// *** Presubmits ***
	if c.Presubmits == nil {
		c.Presubmits = make(map[string][]Presubmit)
	}
	for repo, jobs := range jc.Presubmits {
		c.Presubmits[repo] = append(c.Presubmits[repo], jobs...)
	}

	// *** Postsubmits ***
	if c.Postsubmits == nil {
		c.Postsubmits = make(map[string][]Postsubmit)
	}
	for repo, jobs := range jc.Postsubmits {
		c.Postsubmits[repo] = append(c.Postsubmits[repo], jobs...)
	}

	return nil
}

func setPresubmitDecorationDefaults(c *Config, ps *Presubmit) {
	if ps.Decorate {
		ps.DecorationConfig = ps.DecorationConfig.ApplyDefault(c.Plank.DefaultDecorationConfig)
	}
}

func setPostsubmitDecorationDefaults(c *Config, ps *Postsubmit) {
	if ps.Decorate {
		ps.DecorationConfig = ps.DecorationConfig.ApplyDefault(c.Plank.DefaultDecorationConfig)
	}
}

func setPeriodicDecorationDefaults(c *Config, ps *Periodic) {
	if ps.Decorate {
		ps.DecorationConfig = ps.DecorationConfig.ApplyDefault(c.Plank.DefaultDecorationConfig)
	}
}

// finalizeJobConfig mutates and fixes entries for jobspecs
func (c *Config) finalizeJobConfig() error {
	if c.decorationRequested() {
		if c.Plank.DefaultDecorationConfig == nil {
			return errors.New("no default decoration config provided for plank")
		}
		if c.Plank.DefaultDecorationConfig.UtilityImages == nil {
			return errors.New("no default decoration image pull specs provided for plank")
		}
		if c.Plank.DefaultDecorationConfig.GCSConfiguration == nil {
			return errors.New("no default GCS decoration config provided for plank")
		}
		if c.Plank.DefaultDecorationConfig.GCSCredentialsSecret == "" {
			return errors.New("no default GCS credentials secret provided for plank")
		}

		for _, vs := range c.Presubmits {
			for i := range vs {
				setPresubmitDecorationDefaults(c, &vs[i])
			}
		}

		for _, js := range c.Postsubmits {
			for i := range js {
				setPostsubmitDecorationDefaults(c, &js[i])
			}
		}

		for i := range c.Periodics {
			setPeriodicDecorationDefaults(c, &c.Periodics[i])
		}
	}

	// Ensure that regexes are valid and set defaults.
	for _, vs := range c.Presubmits {
		c.defaultPresubmitFields(vs)
		if err := SetPresubmitRegexes(vs); err != nil {
			return fmt.Errorf("could not set regex: %v", err)
		}
	}
	for _, js := range c.Postsubmits {
		c.defaultPostsubmitFields(js)
		if err := SetPostsubmitRegexes(js); err != nil {
			return fmt.Errorf("could not set regex: %v", err)
		}
	}

	c.defaultPeriodicFields(c.Periodics)

	for _, v := range c.AllPresubmits(nil) {
		if err := resolvePresets(v.Name, v.Labels, v.Spec, v.BuildSpec, c.Presets); err != nil {
			return err
		}
	}

	for _, v := range c.AllPostsubmits(nil) {
		if err := resolvePresets(v.Name, v.Labels, v.Spec, v.BuildSpec, c.Presets); err != nil {
			return err
		}
	}

	for _, v := range c.AllPeriodics() {
		if err := resolvePresets(v.Name, v.Labels, v.Spec, v.BuildSpec, c.Presets); err != nil {
			return err
		}
	}

	return nil
}

// validateComponentConfig validates the infrastructure component configuration
func (c *Config) validateComponentConfig() error {
	if c.Plank.JobURLPrefix != "" && c.Plank.JobURLPrefixConfig["*"] != "" {
		return errors.New(`Planks job_url_prefix must be unset when job_url_prefix_config["*"] is set. The former is deprecated, use the latter`)
	}
	for k, v := range c.Plank.JobURLPrefixConfig {
		if _, err := url.Parse(v); err != nil {
			return fmt.Errorf(`Invalid value for Planks job_url_prefix_config["%s"]: %v`, k, err)
		}
	}
	return nil
}

var jobNameRegex = regexp.MustCompile(`^[A-Za-z0-9-._]+$`)

func validateJobBase(v JobBase, jobType prowapi.ProwJobType, podNamespace string) error {
	if !jobNameRegex.MatchString(v.Name) {
		return fmt.Errorf("name: must match regex %q", jobNameRegex.String())
	}
	// Ensure max_concurrency is non-negative.
	if v.MaxConcurrency < 0 {
		return fmt.Errorf("max_concurrency: %d must be a non-negative number", v.MaxConcurrency)
	}
	if err := validateAgent(v, podNamespace); err != nil {
		return err
	}
	if err := validatePodSpec(jobType, v.Spec); err != nil {
		return err
	}
	if err := validateLabels(v.Labels); err != nil {
		return err
	}
	if v.Spec == nil || len(v.Spec.Containers) == 0 {
		return nil // knative-build and jenkins jobs have no spec
	}
	return validateDecoration(v.Spec.Containers[0], v.DecorationConfig)
}

// validateJobConfig validates if all the jobspecs/presets are valid
// if you are mutating the jobs, please add it to finalizeJobConfig above
func (c *Config) validateJobConfig() error {
	type orgRepoJobName struct {
		orgRepo, jobName string
	}

	// Validate presubmits.
	// Checking that no duplicate job in prow config exists on the same org / repo / branch.
	validPresubmits := map[orgRepoJobName][]Presubmit{}
	for repo, jobs := range c.Presubmits {
		for _, job := range jobs {
			repoJobName := orgRepoJobName{repo, job.Name}
			for _, existingJob := range validPresubmits[repoJobName] {
				if existingJob.Brancher.Intersects(job.Brancher) {
					return fmt.Errorf("duplicated presubmit job: %s", job.Name)
				}
			}
			validPresubmits[repoJobName] = append(validPresubmits[repoJobName], job)
		}
	}

	for _, v := range c.AllPresubmits(nil) {
		if err := validateJobBase(v.JobBase, prowapi.PresubmitJob, c.PodNamespace); err != nil {
			return fmt.Errorf("invalid presubmit job %s: %v", v.Name, err)
		}
		if err := validateTriggering(v); err != nil {
			return err
		}
	}

	// Validate postsubmits.
	// Checking that no duplicate job in prow config exists on the same org / repo / branch.
	validPostsubmits := map[orgRepoJobName][]Postsubmit{}
	for repo, jobs := range c.Postsubmits {
		for _, job := range jobs {
			repoJobName := orgRepoJobName{repo, job.Name}
			for _, existingJob := range validPostsubmits[repoJobName] {
				if existingJob.Brancher.Intersects(job.Brancher) {
					return fmt.Errorf("duplicated postsubmit job: %s", job.Name)
				}
			}
			validPostsubmits[repoJobName] = append(validPostsubmits[repoJobName], job)
		}
	}

	for _, j := range c.AllPostsubmits(nil) {
		if err := validateJobBase(j.JobBase, prowapi.PostsubmitJob, c.PodNamespace); err != nil {
			return fmt.Errorf("invalid postsubmit job %s: %v", j.Name, err)
		}
	}

	// validate no duplicated periodics
	validPeriodics := sets.NewString()
	// Ensure that the periodic durations are valid and specs exist.
	for _, p := range c.AllPeriodics() {
		if validPeriodics.Has(p.Name) {
			return fmt.Errorf("duplicated periodic job : %s", p.Name)
		}
		validPeriodics.Insert(p.Name)
		if err := validateJobBase(p.JobBase, prowapi.PeriodicJob, c.PodNamespace); err != nil {
			return fmt.Errorf("invalid periodic job %s: %v", p.Name, err)
		}
	}
	// Set the interval on the periodic jobs. It doesn't make sense to do this
	// for child jobs.
	for j, p := range c.Periodics {
		if p.Cron != "" && p.Interval != "" {
			return fmt.Errorf("cron and interval cannot be both set in periodic %s", p.Name)
		} else if p.Cron == "" && p.Interval == "" {
			return fmt.Errorf("cron and interval cannot be both empty in periodic %s", p.Name)
		} else if p.Cron != "" {
			if _, err := cron.Parse(p.Cron); err != nil {
				return fmt.Errorf("invalid cron string %s in periodic %s: %v", p.Cron, p.Name, err)
			}
		} else {
			d, err := time.ParseDuration(c.Periodics[j].Interval)
			if err != nil {
				return fmt.Errorf("cannot parse duration for %s: %v", c.Periodics[j].Name, err)
			}
			c.Periodics[j].interval = d
		}
	}

	return nil
}

// DefaultConfigPath will be used if a --config-path is unset
const DefaultConfigPath = "/etc/config/config.yaml"

// ConfigPath returns the value for the component's configPath if provided
// explicityly or default otherwise.
func ConfigPath(value string) string {

	if value != "" {
		return value
	}
	logrus.Warningf("defaulting to %s until 15 July 2019, please migrate", DefaultConfigPath)
	return DefaultConfigPath
}

func parseProwConfig(c *Config) error {
	if err := ValidateController(&c.Plank.Controller); err != nil {
		return fmt.Errorf("validating plank config: %v", err)
	}

	if c.Plank.PodPendingTimeoutString == "" {
		c.Plank.PodPendingTimeout = 24 * time.Hour
	} else {
		podPendingTimeout, err := time.ParseDuration(c.Plank.PodPendingTimeoutString)
		if err != nil {
			return fmt.Errorf("cannot parse duration for plank.pod_pending_timeout: %v", err)
		}
		c.Plank.PodPendingTimeout = podPendingTimeout
	}

	if c.Gerrit.TickIntervalString == "" {
		c.Gerrit.TickInterval = time.Minute
	} else {
		tickInterval, err := time.ParseDuration(c.Gerrit.TickIntervalString)
		if err != nil {
			return fmt.Errorf("cannot parse duration for c.gerrit.tick_interval: %v", err)
		}
		c.Gerrit.TickInterval = tickInterval
	}

	if c.Gerrit.RateLimit == 0 {
		c.Gerrit.RateLimit = 5
	}

	if len(c.GitHubReporter.JobTypesToReport) == 0 {
		// TODO(krzyzacy): The default will be changed to presubmit + postsubmit by April.
		c.GitHubReporter.JobTypesToReport = append(c.GitHubReporter.JobTypesToReport, prowapi.PresubmitJob)
	}

	// validate entries are valid job types
	// Currently only presubmit and postsubmit can be reported to github
	for _, t := range c.GitHubReporter.JobTypesToReport {
		if t != prowapi.PresubmitJob && t != prowapi.PostsubmitJob {
			return fmt.Errorf("invalid job_types_to_report: %v", t)
		}
	}

	for i := range c.JenkinsOperators {
		if err := ValidateController(&c.JenkinsOperators[i].Controller); err != nil {
			return fmt.Errorf("validating jenkins_operators config: %v", err)
		}
		sel, err := labels.Parse(c.JenkinsOperators[i].LabelSelectorString)
		if err != nil {
			return fmt.Errorf("invalid jenkins_operators.label_selector option: %v", err)
		}
		c.JenkinsOperators[i].LabelSelector = sel
		// TODO: Invalidate overlapping selectors more
		if len(c.JenkinsOperators) > 1 && c.JenkinsOperators[i].LabelSelectorString == "" {
			return errors.New("selector overlap: cannot use an empty label_selector with multiple selectors")
		}
		if len(c.JenkinsOperators) == 1 && c.JenkinsOperators[0].LabelSelectorString != "" {
			return errors.New("label_selector is invalid when used for a single jenkins-operator")
		}
	}

	for i, agentToTmpl := range c.Deck.ExternalAgentLogs {
		urlTemplate, err := template.New(agentToTmpl.Agent).Parse(agentToTmpl.URLTemplateString)
		if err != nil {
			return fmt.Errorf("parsing template for agent %q: %v", agentToTmpl.Agent, err)
		}
		c.Deck.ExternalAgentLogs[i].URLTemplate = urlTemplate
		// we need to validate selectors used by deck since these are not
		// sent to the api server.
		s, err := labels.Parse(c.Deck.ExternalAgentLogs[i].SelectorString)
		if err != nil {
			return fmt.Errorf("error parsing selector %q: %v", c.Deck.ExternalAgentLogs[i].SelectorString, err)
		}
		c.Deck.ExternalAgentLogs[i].Selector = s
	}

	if c.Deck.TideUpdatePeriodString == "" {
		c.Deck.TideUpdatePeriod = time.Second * 10
	} else {
		period, err := time.ParseDuration(c.Deck.TideUpdatePeriodString)
		if err != nil {
			return fmt.Errorf("cannot parse duration for deck.tide_update_period: %v", err)
		}
		c.Deck.TideUpdatePeriod = period
	}

	if c.Deck.Spyglass.SizeLimit == 0 {
		c.Deck.Spyglass.SizeLimit = 100e6
	} else if c.Deck.Spyglass.SizeLimit <= 0 {
		return fmt.Errorf("invalid value for deck.spyglass.size_limit, must be >=0")
	}

	c.Deck.Spyglass.RegexCache = make(map[string]*regexp.Regexp)
	for k := range c.Deck.Spyglass.Viewers {
		r, err := regexp.Compile(k)
		if err != nil {
			return fmt.Errorf("cannot compile regexp %s, err: %v", k, err)
		}
		c.Deck.Spyglass.RegexCache[k] = r
	}

	// Map old viewer names to the new ones for backwards compatibility.
	// TODO(Katharine, #10274): remove this, eventually.
	oldViewers := map[string]string{
		"build-log-viewer": "buildlog",
		"metadata-viewer":  "metadata",
		"junit-viewer":     "junit",
	}

	for re, viewers := range c.Deck.Spyglass.Viewers {
		for i, v := range viewers {
			if rename, ok := oldViewers[v]; ok {
				c.Deck.Spyglass.Viewers[re][i] = rename
			}
		}
	}

	if c.PushGateway.IntervalString == "" {
		c.PushGateway.Interval = time.Minute
	} else {
		interval, err := time.ParseDuration(c.PushGateway.IntervalString)
		if err != nil {
			return fmt.Errorf("cannot parse duration for push_gateway.interval: %v", err)
		}
		c.PushGateway.Interval = interval
	}

	if c.Sinker.ResyncPeriodString == "" {
		c.Sinker.ResyncPeriod = time.Hour
	} else {
		resyncPeriod, err := time.ParseDuration(c.Sinker.ResyncPeriodString)
		if err != nil {
			return fmt.Errorf("cannot parse duration for sinker.resync_period: %v", err)
		}
		c.Sinker.ResyncPeriod = resyncPeriod
	}

	if c.Sinker.MaxProwJobAgeString == "" {
		c.Sinker.MaxProwJobAge = 7 * 24 * time.Hour
	} else {
		maxProwJobAge, err := time.ParseDuration(c.Sinker.MaxProwJobAgeString)
		if err != nil {
			return fmt.Errorf("cannot parse duration for max_prowjob_age: %v", err)
		}
		c.Sinker.MaxProwJobAge = maxProwJobAge
	}

	if c.Sinker.MaxPodAgeString == "" {
		c.Sinker.MaxPodAge = 24 * time.Hour
	} else {
		maxPodAge, err := time.ParseDuration(c.Sinker.MaxPodAgeString)
		if err != nil {
			return fmt.Errorf("cannot parse duration for max_pod_age: %v", err)
		}
		c.Sinker.MaxPodAge = maxPodAge
	}

	if c.Tide.SyncPeriodString == "" {
		c.Tide.SyncPeriod = time.Minute
	} else {
		period, err := time.ParseDuration(c.Tide.SyncPeriodString)
		if err != nil {
			return fmt.Errorf("cannot parse duration for tide.sync_period: %v", err)
		}
		c.Tide.SyncPeriod = period
	}
	if c.Tide.StatusUpdatePeriodString == "" {
		c.Tide.StatusUpdatePeriod = c.Tide.SyncPeriod
	} else {
		period, err := time.ParseDuration(c.Tide.StatusUpdatePeriodString)
		if err != nil {
			return fmt.Errorf("cannot parse duration for tide.status_update_period: %v", err)
		}
		c.Tide.StatusUpdatePeriod = period
	}

	if c.Tide.MaxGoroutines == 0 {
		c.Tide.MaxGoroutines = 20
	}
	if c.Tide.MaxGoroutines <= 0 {
		return fmt.Errorf("tide has invalid max_goroutines (%d), it needs to be a positive number", c.Tide.MaxGoroutines)
	}

	for name, method := range c.Tide.MergeType {
		if method != github.MergeMerge &&
			method != github.MergeRebase &&
			method != github.MergeSquash {
			return fmt.Errorf("merge type %q for %s is not a valid type", method, name)
		}
	}

	for i, tq := range c.Tide.Queries {
		if err := tq.Validate(); err != nil {
			return fmt.Errorf("tide query (index %d) is invalid: %v", i, err)
		}
	}

	if c.ProwJobNamespace == "" {
		c.ProwJobNamespace = "default"
	}
	if c.PodNamespace == "" {
		c.PodNamespace = "default"
	}

	if c.Plank.JobURLPrefixConfig == nil {
		c.Plank.JobURLPrefixConfig = map[string]string{}
	}
	if c.Plank.JobURLPrefix != "" && c.Plank.JobURLPrefixConfig["*"] == "" {
		c.Plank.JobURLPrefixConfig["*"] = c.Plank.JobURLPrefix
		// Set JobURLPrefix to an empty string to indicate we've moved
		// it to JobURLPrefixConfig["*"] without overwriting the latter
		// so validation succeeds
		c.Plank.JobURLPrefix = ""
	}

	if c.GitHubOptions.LinkURLFromConfig == "" {
		c.GitHubOptions.LinkURLFromConfig = "https://github.com"
	}
	linkURL, err := url.Parse(c.GitHubOptions.LinkURLFromConfig)
	if err != nil {
		return fmt.Errorf("unable to parse github.link_url, might not be a valid url: %v", err)
	}
	c.GitHubOptions.LinkURL = linkURL

	if c.StatusErrorLink == "" {
		c.StatusErrorLink = "https://github.com/kubernetes/test-infra/issues"
	}

	if c.LogLevel == "" {
		c.LogLevel = "info"
	}
	lvl, err := logrus.ParseLevel(c.LogLevel)
	if err != nil {
		return err
	}
	logrus.SetLevel(lvl)

	// Avoid using a job timeout of infinity by setting the default value to 24 hours
	if c.DefaultJobTimeout == 0 {
		c.DefaultJobTimeout = DefaultJobTimeout
	}

	return nil
}

func (c *JobConfig) decorationRequested() bool {
	for _, vs := range c.Presubmits {
		for i := range vs {
			if vs[i].Decorate {
				return true
			}
		}
	}

	for _, js := range c.Postsubmits {
		for i := range js {
			if js[i].Decorate {
				return true
			}
		}
	}

	for i := range c.Periodics {
		if c.Periodics[i].Decorate {
			return true
		}
	}

	return false
}

func validateLabels(labels map[string]string) error {
	for label, value := range labels {
		for _, prowLabel := range decorate.Labels() {
			if label == prowLabel {
				return fmt.Errorf("label %s is reserved for decoration", label)
			}
		}
		if errs := validation.IsQualifiedName(label); len(errs) != 0 {
			return fmt.Errorf("invalid label %s: %v", label, errs)
		}
		if errs := validation.IsValidLabelValue(labels[label]); len(errs) != 0 {
			return fmt.Errorf("label %s has invalid value %s: %v", label, value, errs)
		}
	}
	return nil
}

func validateAgent(v JobBase, podNamespace string) error {
	k := string(prowapi.KubernetesAgent)
	b := string(prowapi.KnativeBuildAgent)
	j := string(prowapi.JenkinsAgent)
	agents := sets.NewString(k, b, j)
	agent := v.Agent
	switch {
	case !agents.Has(agent):
		return fmt.Errorf("agent must be one of %s (found %q)", strings.Join(agents.List(), ", "), agent)
	case v.Spec != nil && agent != k:
		return fmt.Errorf("job specs require agent: %s (found %q)", k, agent)
	case agent == k && v.Spec == nil:
		return errors.New("kubernetes jobs require a spec")
	case v.BuildSpec != nil && agent != b:
		return fmt.Errorf("job build_specs require agent: %s (found %q)", b, agent)
	case agent == b && v.BuildSpec == nil:
		return errors.New("knative-build jobs require a build_spec")
	case v.DecorationConfig != nil && agent != k && agent != b:
		// TODO(fejta): only source decoration supported...
		return fmt.Errorf("decoration requires agent: %s or %s (found %q)", k, b, agent)
	case v.ErrorOnEviction && agent != k:
		return fmt.Errorf("error_on_eviction only applies to agent: %s (found %q)", k, agent)
	case v.Namespace == nil || *v.Namespace == "":
		return fmt.Errorf("failed to default namespace")
	case *v.Namespace != podNamespace && agent != b:
		// TODO(fejta): update plank to allow this (depends on client change)
		return fmt.Errorf("namespace customization requires agent: %s (found %q)", b, agent)
	}
	return nil
}

func validateDecoration(container v1.Container, config *prowapi.DecorationConfig) error {
	if config == nil {
		return nil
	}

	if err := config.Validate(); err != nil {
		return fmt.Errorf("invalid decoration config: %v", err)
	}
	var args []string
	args = append(append(args, container.Command...), container.Args...)
	if len(args) == 0 || args[0] == "" {
		return errors.New("decorated job containers must specify command and/or args")
	}
	return nil
}

func resolvePresets(name string, labels map[string]string, spec *v1.PodSpec, buildSpec *buildapi.BuildSpec, presets []Preset) error {
	for _, preset := range presets {
		if spec != nil {
			if err := mergePreset(preset, labels, spec.Containers, &spec.Volumes); err != nil {
				return fmt.Errorf("job %s failed to merge presets for podspec: %v", name, err)
			}
		}

		if buildSpec != nil {
			if err := mergePreset(preset, labels, buildSpec.Steps, &buildSpec.Volumes); err != nil {
				return fmt.Errorf("job %s failed to merge presets for buildspec: %v", name, err)
			}
		}
	}

	return nil
}

func validatePodSpec(jobType prowapi.ProwJobType, spec *v1.PodSpec) error {
	if spec == nil {
		return nil
	}

	if len(spec.InitContainers) != 0 {
		return errors.New("pod spec may not use init containers")
	}

	if n := len(spec.Containers); n != 1 {
		return fmt.Errorf("pod spec must specify exactly 1 container, found: %d", n)
	}

	for _, env := range spec.Containers[0].Env {
		for _, prowEnv := range downwardapi.EnvForType(jobType) {
			if env.Name == prowEnv {
				// TODO(fejta): consider allowing this
				return fmt.Errorf("env %s is reserved", env.Name)
			}
		}
	}

	for _, mount := range spec.Containers[0].VolumeMounts {
		for _, prowMount := range decorate.VolumeMounts() {
			if mount.Name == prowMount {
				return fmt.Errorf("volumeMount name %s is reserved for decoration", prowMount)
			}
		}
		for _, prowMountPath := range decorate.VolumeMountPaths() {
			if strings.HasPrefix(mount.MountPath, prowMountPath) || strings.HasPrefix(prowMountPath, mount.MountPath) {
				return fmt.Errorf("mount %s at %s conflicts with decoration mount at %s", mount.Name, mount.MountPath, prowMountPath)
			}
		}
	}

	for _, volume := range spec.Volumes {
		for _, prowVolume := range decorate.VolumeMounts() {
			if volume.Name == prowVolume {
				return fmt.Errorf("volume %s is a reserved for decoration", volume.Name)
			}
		}
	}

	return nil
}

func validateTriggering(job Presubmit) error {
	if job.AlwaysRun && job.RunIfChanged != "" {
		return fmt.Errorf("job %s is set to always run but also declares run_if_changed targets, which are mutually exclusive", job.Name)
	}

	if !job.SkipReport && job.Context == "" {
		return fmt.Errorf("job %s is set to report but has no context configured", job.Name)
	}

	return nil
}

// ValidateController validates the provided controller config.
func ValidateController(c *Controller) error {
	urlTmpl, err := template.New("JobURL").Parse(c.JobURLTemplateString)
	if err != nil {
		return fmt.Errorf("parsing template: %v", err)
	}
	c.JobURLTemplate = urlTmpl

	reportTmpl, err := template.New("Report").Parse(c.ReportTemplateString)
	if err != nil {
		return fmt.Errorf("parsing template: %v", err)
	}
	c.ReportTemplate = reportTmpl
	if c.MaxConcurrency < 0 {
		return fmt.Errorf("controller has invalid max_concurrency (%d), it needs to be a non-negative number", c.MaxConcurrency)
	}
	if c.MaxGoroutines == 0 {
		c.MaxGoroutines = 20
	}
	if c.MaxGoroutines <= 0 {
		return fmt.Errorf("controller has invalid max_goroutines (%d), it needs to be a positive number", c.MaxGoroutines)
	}
	return nil
}

// DefaultTriggerFor returns the default regexp string used to match comments
// that should trigger the job with this name.
func DefaultTriggerFor(name string) string {
	return fmt.Sprintf(`(?m)^/test( | .* )%s,?($|\s.*)`, name)
}

// DefaultRerunCommandFor returns the default rerun command for the job with
// this name.
func DefaultRerunCommandFor(name string) string {
	return fmt.Sprintf("/test %s", name)
}

// defaultJobBase configures common parameters, currently Agent and Namespace.
func (c *ProwConfig) defaultJobBase(base *JobBase) {
	if base.Agent == "" { // Use kubernetes by default
		base.Agent = string(prowapi.KubernetesAgent)
	}
	if base.Namespace == nil || *base.Namespace == "" {
		s := c.PodNamespace
		base.Namespace = &s
	}
	if base.Cluster == "" {
		base.Cluster = kube.DefaultClusterAlias
	}
}

func (c *ProwConfig) defaultPresubmitFields(js []Presubmit) {
	for i := range js {
		c.defaultJobBase(&js[i].JobBase)
		if js[i].Context == "" {
			js[i].Context = js[i].Name
		}
		// Default the values of Trigger and RerunCommand if both fields are
		// specified. Otherwise let validation fail as both or neither should have
		// been specified.
		if js[i].Trigger == "" && js[i].RerunCommand == "" {
			js[i].Trigger = DefaultTriggerFor(js[i].Name)
			js[i].RerunCommand = DefaultRerunCommandFor(js[i].Name)
		}
	}
}

func (c *ProwConfig) defaultPostsubmitFields(js []Postsubmit) {
	for i := range js {
		c.defaultJobBase(&js[i].JobBase)
		if js[i].Context == "" {
			js[i].Context = js[i].Name
		}
	}
}

func (c *ProwConfig) defaultPeriodicFields(js []Periodic) {
	for i := range js {
		c.defaultJobBase(&js[i].JobBase)
	}
}

// SetPresubmitRegexes compiles and validates all the regular expressions for
// the provided presubmits.
func SetPresubmitRegexes(js []Presubmit) error {
	for i, j := range js {
		if re, err := regexp.Compile(j.Trigger); err == nil {
			js[i].re = re
		} else {
			return fmt.Errorf("could not compile trigger regex for %s: %v", j.Name, err)
		}
		if !js[i].re.MatchString(j.RerunCommand) {
			return fmt.Errorf("for job %s, rerun command \"%s\" does not match trigger \"%s\"", j.Name, j.RerunCommand, j.Trigger)
		}
		b, err := setBrancherRegexes(j.Brancher)
		if err != nil {
			return fmt.Errorf("could not set branch regexes for %s: %v", j.Name, err)
		}
		js[i].Brancher = b

		c, err := setChangeRegexes(j.RegexpChangeMatcher)
		if err != nil {
			return fmt.Errorf("could not set change regexes for %s: %v", j.Name, err)
		}
		js[i].RegexpChangeMatcher = c
	}
	return nil
}

// setBrancherRegexes compiles and validates all the regular expressions for
// the provided branch specifiers.
func setBrancherRegexes(br Brancher) (Brancher, error) {
	if len(br.Branches) > 0 {
		if re, err := regexp.Compile(strings.Join(br.Branches, `|`)); err == nil {
			br.re = re
		} else {
			return br, fmt.Errorf("could not compile positive branch regex: %v", err)
		}
	}
	if len(br.SkipBranches) > 0 {
		if re, err := regexp.Compile(strings.Join(br.SkipBranches, `|`)); err == nil {
			br.reSkip = re
		} else {
			return br, fmt.Errorf("could not compile negative branch regex: %v", err)
		}
	}
	return br, nil
}

func setChangeRegexes(cm RegexpChangeMatcher) (RegexpChangeMatcher, error) {
	if cm.RunIfChanged != "" {
		re, err := regexp.Compile(cm.RunIfChanged)
		if err != nil {
			return cm, fmt.Errorf("could not compile run_if_changed regex: %v", err)
		}
		cm.reChanges = re
	}
	return cm, nil
}

// SetPostsubmitRegexes compiles and validates all the regular expressions for
// the provided postsubmits.
func SetPostsubmitRegexes(ps []Postsubmit) error {
	for i, j := range ps {
		b, err := setBrancherRegexes(j.Brancher)
		if err != nil {
			return fmt.Errorf("could not set branch regexes for %s: %v", j.Name, err)
		}
		ps[i].Brancher = b
		c, err := setChangeRegexes(j.RegexpChangeMatcher)
		if err != nil {
			return fmt.Errorf("could not set change regexes for %s: %v", j.Name, err)
		}
		ps[i].RegexpChangeMatcher = c
	}
	return nil
}


text:
import rospy

from nav_msgs.msg import OccupancyGrid
from geometry_msgs.msg import Pose, Point
import copy

from dst import GridMassFunction

import matplotlib.pyplot as plt
plt.ion()

from particle_filter import ParticleFilter, ParticleFilterParams
from occupancy_grid import LocalOccupancyGrid, LocalOccupancyGridParams
from tf import transformations
from tf.listener import xyz_to_mat44, xyzw_to_mat44

from common import *

from plot import ParticleFilterPlot

from mdet.msg import GridDST

import cProfile, pstats, StringIO

profiler = None

# uncomment to enable particle filter profiling

# profiler = cProfile.Profile()

transformer = None
"""
:type: tf.Transformer
"""

grid_publisher = None
dynamic_publisher = None
static_publisher = None

dynamics_plot = None
dynamics_image = None

params = ParticleFilterParams(rospy)

particle_filter = ParticleFilter(params)

particle_publisher = None
loader_publisher = None

map = None

class MyTransformer(tf.TransformListener):

    def transformPose(self, target_frame, ps, header=None):

        if hasattr(ps, "header"):
            return super(MyTransformer, self).transformPose(target_frame, ps)

        self.waitForTransform(header.frame_id, target_frame, header.stamp, rospy.Duration(4.0))

        translation, rotation = self.lookupTransformFull(target_frame=target_frame, source_frame=header.frame_id, source_time=header.stamp, target_time=header.stamp, fixed_frame='world')
        mat44 = self.fromTranslationRotation(translation, rotation)

        print("Pose: ", ps.position.x, ps.position.y, ps.position.z)

        # pose44 is the given pose as a 4x4
        pose44 = np.dot(xyz_to_mat44(ps.position), xyzw_to_mat44(ps.orientation))

        # txpose is the new pose in target_frame as a 4x4
        txpose = np.dot(mat44, pose44)

        # xyz and quat are txpose's position and orientation
        xyz = tuple(transformations.translation_from_matrix(txpose))[:3]
        quat = tuple(transformations.quaternion_from_matrix(txpose))

        # assemble return value PoseStamped
        return Pose(Point(*xyz), Quaternion(*quat))

scan_cnt = 0

def grid_callback(input_grid):
    """
    :param OccupancyGrid input_grid:
    """
    global grid_publisher
    global transformer
    global particle_publisher
    global loader_publisher
    global grid_publisher
    global dynamic_publisher
    global static_publisher
    global scan_cnt
    global tfbr
    global plot
    global map

    global hist_plot
    global local_environment_publisher
    cur_scan_cnt = scan_cnt
    scan_cnt += 1
    cur_scan_cnt +=1

    print("Got scan request {0}".format(cur_scan_cnt))

    try:
        # transform grid pose to world tf

        target_frame = "world"

        target_time = input_grid.header.stamp

        #translation, rotation = transformer.lookupTransformFull(target_frame=target_frame, source_frame=input_grid.header.frame_id, source_time=target_time, target_time=target_time, fixed_frame='world')

        input_grid.info.origin = transformer.transformPose(target_frame, input_grid.info.origin, input_grid.header)
        input_grid.header.frame_id = target_frame

        print("tx pose:", input_grid.info.origin.position.x, input_grid.info.origin.position.y, input_grid.info.origin.position.z)

        params = LocalOccupancyGridParams(rospy, '~grid_')

        grid = LocalOccupancyGrid(input_grid, params)

        # inline profiling, limited to particle filter
        if profiler:
            profiler.enable()
        particle_filter.update_grid(grid)
        if profiler:
            profiler.disable()

        distance = (particle_filter.distance_gauss_occupied() * 255).astype(np.int8)
        input_grid.header.frame_id = "odom"
        publish_grid(grid_publisher, distance, input_grid.header, input_grid.info.resolution)

        if profiler:
            profiler.enable()
        particle_filter.step_model()
        if profiler:
            profiler.disable()

        mass_static, mass_dynamic = particle_filter.get_masses()

        universe = ['F', 'D', 'S']

        m_grid = GridMassFunction(universe, grid.info)
        m_grid[['S', 'D']] = grid.get_grid()
        m_grid['F'] = 1.0 - m_grid[['S', 'D']]

        m_pfilter = GridMassFunction(universe, grid.info)
        m_pfilter['S'] = mass_static
        m_pfilter['D'] = mass_dynamic

        m_pfilter.normalize_universe()

        # m_pfilter[universe] is automatically set to the remainder

        m, conflict = m_grid.conj_dempster(m_pfilter)

        m['F'] += conflict

        mass_static = m['S']

        mass_dynamic = m['D']

        #  publishing of dynamic and static masses

        print("Publishing state")

        static_scaled = ((1.0 - mass_static) * 255).astype(np.int8)

        publish_grid(static_publisher, static_scaled, input_grid.header, input_grid.info.resolution)

        dynamic_scaled = ((1.0 - mass_dynamic) * 255).astype(np.int8)

        publish_grid(dynamic_publisher, dynamic_scaled, input_grid.header, input_grid.info.resolution)

        local_environment_publisher.publish(m.asMessage(input_grid.header))

        orientation = particle_filter.get_orientation_means()

        plot.update_plot(mass_static, mass_dynamic, orientation, grid.get_rotation_angle())

        if profiler:
            profiler.enable()
        particle_filter.resample()
        if profiler:
            profiler.disable()

        if profiler:
            s = StringIO.StringIO()
            sortby = 'cumulative'
            ps = pstats.Stats(profiler, stream=s).sort_stats(sortby)
            ps.print_stats()

            file = "/home/viktor/Sync/School/DP/profile.txt"

            with open(file, "w") as f:
                f.write(s.getvalue())

        publish_point_cloud(particle_publisher, particle_filter.get_particles_xyza(), target_frame, input_grid.header.stamp)

    finally:
        #time.sleep(1.6)
        # print("Publishing scan request {0}".format(cur_scan_cnt))
        # loader_publisher.publish(Empty())
        pass

def mapping():

    # get mass function after fusion of grid and particle filter

    # get 2d rotation matrix from grid pose
    # get translation from grid pose

    # for all non-zero masses in mass function, use opencv warpAffine to rotate grid to correct position
    # calculate affected region fo the map
    # enlarge map if necessary
    # create new MassFunction with only affected region of map
    # join rotated mass function to region of map using Josang cumulative operator

    # http://stackoverflow.com/questions/22041699/rotate-an-image-without-cropping-in-opencv-in-c

    pass

def main():
    global grid_publisher
    global dynamic_publisher
    global static_publisher
    global particle_filter
    global transformer
    global particle_publisher
    global loader_publisher
    global dynamics_plot
    global plot
    global local_environment_publisher
    rospy.init_node('particle_filter')

    transformer = MyTransformer(False)

    rospy.Subscriber("local_grid", OccupancyGrid, grid_callback)

    grid_publisher = rospy.Publisher('distance_transform', OccupancyGrid, queue_size=1)

    dynamic_publisher = rospy.Publisher('dynamic', OccupancyGrid, queue_size=1)

    static_publisher = rospy.Publisher('static', OccupancyGrid, queue_size=1)

    particle_publisher = rospy.Publisher('particles', PointCloud2, queue_size=1)

    local_environment_publisher = rospy.Publisher('local_environment', GridDST, queue_size=1)

    plot = ParticleFilterPlot()

    rospy.spin()

if __name__ == '__main__':
    try:
        print("Particle filter starting")
        main()
    except rospy.ROSInterruptException:
        print("Interrupted by ROS")
        pass


text:
package org.apache.camel.test.infra.xmpp.services;

import org.apache.camel.test.infra.common.services.SimpleTestServiceBuilder;

public final class XmppServiceFactory {
    private XmppServiceFactory() {

    }

    public static SimpleTestServiceBuilder<XmppService> builder() {
        return new SimpleTestServiceBuilder<>("xmpp");
    }

    public static XmppService createService() {
        return builder()
                .addLocalMapping(XmppLocalContainerService::new)
                .addRemoteMapping(XmppRemoteService::new)
                .build();
    }
}


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<title>Account</title>
<meta name="date" content="2014-05-21">
<link rel="stylesheet" type="text/css" href="../stylesheet.css" title="Style">

JavaScript is disabled on your browser.

Overview

Package

Class

Tree

Deprecated

Index

Help

Prev Class

Next Class

Frames

No Frames

All Classes

Summary:

Nested |

Field |

Constr |

Method

Detail:

Field |

Constr |

Method

nxt

Class Account

java.lang.Object

nxt.Account

public final class Account
extends java.lang.Object

Nested Class Summary

Nested Classes

Modifier and Type
Class and Description

static class
Account.AccountAsset

static class
Account.AccountLease

static class
Account.Event

Method Summary

Methods

Modifier and Type
Method and Description

static boolean
addAssetListener(Listener<Account.AccountAsset> listener,
                Account.Event eventType)

static boolean
addLeaseListener(Listener<Account.AccountLease> listener,
                Account.Event eventType)

static boolean
addListener(Listener<Account> listener,
           Account.Event eventType)

static Account
getAccount(byte[] publicKey)

static Account
getAccount(java.lang.Long id)

static java.util.Collection<Account>
getAllAccounts()

java.util.Map<java.lang.Long,java.lang.Long>
getAssetBalancesQNT()

long
getBalanceNQT()

int
getCurrentLeasingHeightFrom()

int
getCurrentLeasingHeightTo()

java.lang.Long
getCurrentLesseeId()

java.lang.String
getDescription()

long
getEffectiveBalanceNXT()

long
getForgedBalanceNQT()

long
getGuaranteedBalanceNQT(int numberOfConfirmations)

java.lang.Long
getId()

static java.lang.Long
getId(byte[] publicKey)

java.util.Set<java.lang.Long>
getLessorIds()

java.lang.String
getName()

int
getNextLeasingHeightFrom()

int
getNextLeasingHeightTo()

java.lang.Long
getNextLesseeId()

byte[]
getPublicKey()

java.lang.Long
getUnconfirmedAssetBalanceQNT(java.lang.Long assetId)

java.util.Map<java.lang.Long,java.lang.Long>
getUnconfirmedAssetBalancesQNT()

long
getUnconfirmedBalanceNQT()

static boolean
removeAssetListener(Listener<Account.AccountAsset> listener,
                   Account.Event eventType)

static boolean
removeLeaseListener(Listener<Account.AccountLease> listener,
                   Account.Event eventType)

static boolean
removeListener(Listener<Account> listener,
              Account.Event eventType)

Methods inherited from class java.lang.Object

clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

Method Detail

addListener

public static boolean addListener(Listener<Account> listener,
                  Account.Event eventType)

removeListener

public static boolean removeListener(Listener<Account> listener,
                     Account.Event eventType)

addAssetListener

public static boolean addAssetListener(Listener<Account.AccountAsset> listener,
                       Account.Event eventType)

removeAssetListener

public static boolean removeAssetListener(Listener<Account.AccountAsset> listener,
                          Account.Event eventType)

addLeaseListener

public static boolean addLeaseListener(Listener<Account.AccountLease> listener,
                       Account.Event eventType)

removeLeaseListener

public static boolean removeLeaseListener(Listener<Account.AccountLease> listener,
                          Account.Event eventType)

getAllAccounts

public static java.util.Collection<Account> getAllAccounts()

getAccount

public static Account getAccount(java.lang.Long id)

getAccount

public static Account getAccount(byte[] publicKey)

getId

public static java.lang.Long getId(byte[] publicKey)

getId

public java.lang.Long getId()

getName

public java.lang.String getName()

getDescription

public java.lang.String getDescription()

getPublicKey

public byte[] getPublicKey()

getBalanceNQT

public long getBalanceNQT()

getUnconfirmedBalanceNQT

public long getUnconfirmedBalanceNQT()

getForgedBalanceNQT

public long getForgedBalanceNQT()

getEffectiveBalanceNXT

public long getEffectiveBalanceNXT()

getGuaranteedBalanceNQT

public long getGuaranteedBalanceNQT(int numberOfConfirmations)

getUnconfirmedAssetBalanceQNT

public java.lang.Long getUnconfirmedAssetBalanceQNT(java.lang.Long assetId)

getAssetBalancesQNT

public java.util.Map<java.lang.Long,java.lang.Long> getAssetBalancesQNT()

getUnconfirmedAssetBalancesQNT

public java.util.Map<java.lang.Long,java.lang.Long> getUnconfirmedAssetBalancesQNT()

getCurrentLesseeId

public java.lang.Long getCurrentLesseeId()

getNextLesseeId

public java.lang.Long getNextLesseeId()

getCurrentLeasingHeightFrom

public int getCurrentLeasingHeightFrom()

getCurrentLeasingHeightTo

public int getCurrentLeasingHeightTo()

getNextLeasingHeightFrom

public int getNextLeasingHeightFrom()

getNextLeasingHeightTo

public int getNextLeasingHeightTo()

getLessorIds

public java.util.Set<java.lang.Long> getLessorIds()

Overview

Package

Class

Tree

Deprecated

Index

Help

Prev Class

Next Class

Frames

No Frames

All Classes

Summary:

Nested |

Field |

Constr |

Method

Detail:

Field |

Constr |

Method


text:
package integration

import (
	"reflect"
	"testing"

	"github.com/coreos/etcd/Godeps/_workspace/src/golang.org/x/net/context"
	"github.com/coreos/etcd/clientv3"
	"github.com/coreos/etcd/integration"
	"github.com/coreos/etcd/pkg/testutil"
	"github.com/coreos/etcd/pkg/types"
)

func TestMemberList(t *testing.T) {
	defer testutil.AfterTest(t)

	clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3})
	defer clus.Terminate(t)

	capi := clientv3.NewCluster(clus.RandClient())

	resp, err := capi.MemberList(context.Background())
	if err != nil {
		t.Fatalf("failed to list member %v", err)
	}

	if len(resp.Members) != 3 {
		t.Errorf("number of members = %d, want %d", len(resp.Members), 3)
	}
}

func TestMemberAdd(t *testing.T) {
	defer testutil.AfterTest(t)

	clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3})
	defer clus.Terminate(t)

	capi := clientv3.NewCluster(clus.RandClient())

	urls := []string{"http://127.0.0.1:1234"}
	resp, err := capi.MemberAdd(context.Background(), urls)
	if err != nil {
		t.Fatalf("failed to add member %v", err)
	}

	if !reflect.DeepEqual(resp.Member.PeerURLs, urls) {
		t.Errorf("urls = %v, want %v", urls, resp.Member.PeerURLs)
	}
}

func TestMemberRemove(t *testing.T) {
	defer testutil.AfterTest(t)

	clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3})
	defer clus.Terminate(t)

	capi := clientv3.NewCluster(clus.Client(1))
	resp, err := capi.MemberList(context.Background())
	if err != nil {
		t.Fatalf("failed to list member %v", err)
	}

	rmvID := resp.Members[0].ID
	// indexes in capi member list don't necessarily match cluster member list;
	// find member that is not the client to remove
	for _, m := range resp.Members {
		mURLs, _ := types.NewURLs(m.PeerURLs)
		if !reflect.DeepEqual(mURLs, clus.Members[1].ServerConfig.PeerURLs) {
			rmvID = m.ID
			break
		}
	}

	_, err = capi.MemberRemove(context.Background(), rmvID)
	if err != nil {
		t.Fatalf("failed to remove member %v", err)
	}

	resp, err = capi.MemberList(context.Background())
	if err != nil {
		t.Fatalf("failed to list member %v", err)
	}

	if len(resp.Members) != 2 {
		t.Errorf("number of members = %d, want %d", len(resp.Members), 2)
	}
}

func TestMemberUpdate(t *testing.T) {
	defer testutil.AfterTest(t)

	clus := integration.NewClusterV3(t, &integration.ClusterConfig{Size: 3})
	defer clus.Terminate(t)

	capi := clientv3.NewCluster(clus.RandClient())
	resp, err := capi.MemberList(context.Background())
	if err != nil {
		t.Fatalf("failed to list member %v", err)
	}

	urls := []string{"http://127.0.0.1:1234"}
	_, err = capi.MemberUpdate(context.Background(), resp.Members[0].ID, urls)
	if err != nil {
		t.Fatalf("failed to update member %v", err)
	}

	resp, err = capi.MemberList(context.Background())
	if err != nil {
		t.Fatalf("failed to list member %v", err)
	}

	if !reflect.DeepEqual(resp.Members[0].PeerURLs, urls) {
		t.Errorf("urls = %v, want %v", urls, resp.Members[0].PeerURLs)
	}
}