Пишем плагин для Jenkins - глобальная конфигурация

Пишем плагин для Jenkins - глобальная конфигурация

В нашей повседневной жизни мы достаточно много используем Jenkins, а значит - пишем свои и помогаем разрабатывать чужие плагины. Взявшись за разработку плагина чуть более сложного, чем туториал из документации, очень быстро понимаешь, что информации в сети очень мало.

Единственный способ почерпнуть что-то полезное - раскуривать исходники популярных плагинов, благо они общедоступны. Я планирую серию постов, посвященных разработке jenkins-плагинов и сегодня - первый из них - про глобальные настройки.

Для начала нам понадобится класс, который будет взаимодействовать с формой настроек плагина. Для этого он должен расширять абстрактный класс hudson.model.Descriptor. Самое интересное в нём - это метод configure, который нужно будет переопределить.

public class CatPluginDescriptor extends Descriptor<CatConfiguration> {
private String catName;
private String catPhotoUrl;

public CatPluginDescriptor() {
super(CatConfiguration.class);
}

public String getDisplayName() {
return "Configure your cat";
}

@Override
public boolean configure(StaplerRequest req, JSONObject formData) throws FormException {
catName = formData.getString("catName");
catPhotoUrl = formData.getString("catPhotoUrl");
save();
return super.configure(req,formData);
}

public String getTitle() {
return title;
}

public String getName() {
return name;
}
}

Как видишь, мы наследуемся не просто от класса Descriptor, а от Descriptor<CatConfiguration> - т.е. параметризуем классом CatConfiguration. Это класс, который мы описываем в нашем дескрипторе, его же передаем в конструкторе. А поскольку мы его описываем, он должен быть описываемым =), т.е. реализовывать интерфейс Describable:

public class CatConfiguration implements Describable<Configuration> {
@Extension
public static final CatPluginDescriptor DESCRIPTOR = new CatPluginDescriptor();

public CatPluginDescriptor getDescriptor() {
DESCRIPTOR.load();
return DESCRIPTOR;
}
}

Аннотация @Extension нужна для того, чтобы дженкинс мог сам найти наш плагин и провязать настройки. Интерфейс Describable требует реализации метода getDescriptor(), в котором мы возвращаем наш созданный ранее дескриптор.

Остался последний шаг - сама форма настроек. Для описания как глобальных настроек, так и настроек отдельных шагов сборки, Jenkins использут фреймворк Jelly. Совсем базовые вещи расписаны тут. Сначала создаём в папке src/main/resources/ файлик global.jelly. Он должен лежать ровно по тому же пути, что и класс, который мы описывали, только в ресурсах. Например, наш файл Configuration.java находится в пакете org.jenkinsci.plugins.myplugin, значит global.jelly должен быть в папке src/main/resources/org/jenkinsci/plugins/myplugin/Configuration/. Главное - не забывать переносить файл если меняешь название класса - я несколько раз долго не мог понять, куда же исчезли мои настройки =).

Сам jelly-файл довольно простой:

<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form">
<f:section title="${descriptor.getDisplayName()}">
<f:entry title="Cat name" field="catName">
<f:textbox default="Metrofan"/>
</f:entry>
<f:entry title="Cat photo url" field="catPhotoUrl">
<f:textbox default="http://clck.ru/9Dg2W"/>
</f:entry>
</f:section>
</j:jelly>

Ключевой момент здесь - значение аттрибута field элементов <f:entry> - именно по нему мы достаём значения в методе configure нашего дескриптора. А аттрибут title элемента <f:section> демонстрирует обратную связь - мы получаем результат метода getDisplayName() дескриптора и подставляем его в нашу форму. Аналогичным образом можно организовать и хранение дефолтных значений полей.

Фух, на сегодня хватит =).

comments powered by Disqus