В нашей повседневной жизни мы достаточно много используем 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