Доступ к учетным данным Jenkins из плагинов

#jenkins #jenkins-plugins

#Дженкинс #дженкинс-плагины

Вопрос:

Я следую документации здесь https://github.com/jenkinsci/credentials-plugin/blob/master/docs/consumer.adoc

В частности, этот пример:

 public ListBoxModel doFillCredentialsIdItems(
        @AncestorInPath Item item,
        @QueryParameter String credentialsId,
        ... (1)
        ) {
  StandardListBoxModel result = new StandardListBoxModel();
  if (item == null) {
    if (!Jenkins.getActiveInstance().hasPermission(Jenkins.ADMINISTER)) {
      return result.includeCurrentValue(credentialsId); (2)
    }
  } else {
    if (!item.hasPermission(Item.EXTENDED_READ)
        amp;amp; !item.hasPermission(CredentialsProvider.USE_ITEM)) {
      return result.includeCurrentValue(credentialsId); (2)
    }
  }
  return result
    .includeEmptySelection() (3)
    .includeMatchingAs(...) (4)
    .includeCurrentValue(credentialsId); (5)
}
  
  1. Включите любые дополнительные контекстные параметры, которые вам нужны для уточнения списка учетных данных. Например, если учетные данные будут использоваться для подключения к удаленному серверу, вы могли бы включить элемент формы URL сервера в качестве параметра @QueryParameter, чтобы требования к домену могли быть сформированы на основе этого URL.

  2. Мы защищаем от полного заполнения выпадающего списка пользователей, у которых нет возможности фактически сделать выбор. Это также полезно для предотвращения нежелательных запросов к внешнему хранилищу учетных данных.

  3. Если для пользователя допустимо выбрать никаких учетных данных, затем включите пустой выбор.

  4. Нам нужно включить соответствующие учетные данные. В некоторых случаях у вас могут быть непересекающиеся объединения учетных данных, и в этом случае вы можете вызывать этот метод несколько раз, выигрывает первое удостоверение, добавленное для любого заданного идентификатора.

  5. Если вы включите текущее значение, то конфигурация формы останется неизменной в случае удаления резервных учетных данных. Альтернативный вариант — позволить форме «волшебным» образом выбрать новые учетные данные, но обычно это будут неправильные учетные данные. Рекомендуется просто добавить «несуществующие» учетные данные и попросить проверку формы сообщить об ошибке

Однако я застрял на шаге 4 в примере, что мне здесь делать? Я пытался просмотреть другие плагины, чтобы увидеть, как они это реализуют, но я быстро теряюсь. Есть ли простая демонстрация, которая показывает, как это работает?

Вот мой код, основанный на примере Jenkins «Hello World».

 package io.jenkins.plugins.sample;

import com.cloudbees.plugins.credentials.common.*;
import hudson.Launcher;
import hudson.Extension;
import hudson.FilePath;
import hudson.model.*;
import hudson.util.FormValidation;
import hudson.tasks.Builder;
import hudson.tasks.BuildStepDescriptor;
import hudson.util.ListBoxModel;
import jenkins.model.Jenkins;
import org.apache.commons.httpclient.auth.CredentialsProvider;
import org.kohsuke.stapler.*;
import javax.servlet.ServletException;
import java.io.IOException;
import jenkins.tasks.SimpleBuildStep;
import org.jenkinsci.Symbol;

public class HelloWorldBuilder extends Builder implements SimpleBuildStep {

    private final String name;
    private final String credentials;
    private boolean useFrench;
    private final String tppurl;

    @DataBoundConstructor
    public HelloWorldBuilder(String name, String tppurl, String credentials) {
        this.name = name;
        this.tppurl = tppurl;
        this.credentials = credentials;
    }

    @DataBoundSetter
    public void setUseFrench(boolean useFrench) {
        this.useFrench = useFrench;
    }

    public String getName() {
        return name;
    }

    public String getTppurl() {
        return tppurl;
    }

    public String getCredentials() {
        return credentials;
    }

    public boolean isUseFrench() {
        return useFrench;
    }

    @Override
    public void perform(Run<?, ?> run, FilePath workspace, Launcher launcher, TaskListener listener) throws InterruptedException, IOException {
        if (useFrench) {
            listener.getLogger().println("Bonjour, "   name   "!");
        } else {
            listener.getLogger().println("Hello, "   name   tppurl   "! " );
        }
    }

    @Symbol("greet")
    @Extension
    public static final class DescriptorImpl extends BuildStepDescriptor<Builder> {

        public FormValidation doCheckName(@QueryParameter String value, @QueryParameter boolean useFrench)
                throws IOException, ServletException {
            if (value.length() == 0)
                return FormValidation.error(Messages.HelloWorldBuilder_DescriptorImpl_errors_missingName());
            if (value.length() < 4)
                return FormValidation.warning(Messages.HelloWorldBuilder_DescriptorImpl_warnings_tooShort());
            if (!useFrench amp;amp; value.matches(".*[éáàç].*")) {
                return FormValidation.warning(Messages.HelloWorldBuilder_DescriptorImpl_warnings_reallyFrench());
            }
            return FormValidation.ok();
        }

        @Override
        public boolean isApplicable(Class<? extends AbstractProject> aClass) {
            return true;
        }

        @Override
        public String getDisplayName() {
            return Messages.HelloWorldBuilder_DescriptorImpl_DisplayName();
        }

    }

//This is the credentials bit

    public ListBoxModel doFillCredentialsIdItems(
            @AncestorInPath Item item,
            @QueryParameter String credentialsId,
        ) {
        StandardListBoxModel result = new StandardListBoxModel();
        if (item == null) {
            if (!Jenkins.getActiveInstance().hasPermission(Jenkins.ADMINISTER)) {
                return result.includeCurrentValue(credentialsId); 
            }
        } else {
            if (!item.hasPermission(Item.EXTENDED_READ)
                    amp;amp; !item.hasPermission(CredentialsProvider.USE_ITEM)) {
                return result.includeCurrentValue(credentialsId); 
            }
        }
        return result
                .includeEmptySelection() 
                .includeMatchingAs(STUCK HERE!!!!!) 
                .includeCurrentValue(credentialsId); 
    }


// end credentials


}

  

Ответ №1:

На странице есть обновленная информация, которая предлагает более подробную информацию о том, как ее следует использовать

В com.cloudbees.плагины.учетные данные.общие.Класс AbstractIdCredentialsListBoxModel, метод объявлен как:

     /**
 * Adds the ids of the specified credential type that are available to the specified context as the specified
 * authentication with the specified domain requirements and match the specified filter.
 *
 * @param authentication     the authentication to search with
 * @param context            the context to add credentials from.
 * @param type               the base class of the credentials to add.
 * @param domainRequirements the domain requirements.
 * @param matcher            the filter to apply to the credentials.
 * @return {@code this} for method chaining.
 * @see CredentialsProvider#listCredentials(Class, Item, Authentication, List, CredentialsMatcher)
 * @since 2.1.0
 */
public AbstractIdCredentialsListBoxModel<T, C> includeMatchingAs(@NonNull Authentication authentication,
                                                                 @NonNull Item context,
                                                                 @NonNull Class<? extends C> type,
                                                                 @NonNull
                                                                         List<DomainRequirement> domainRequirements,
                                                                 @NonNull CredentialsMatcher matcher) {
    addMissing(CredentialsProvider.listCredentials(type, context, authentication, domainRequirements, matcher));
    return this;
}

/**
 * Adds the ids of the specified credential type that are available to the specified context as the specified
 * authentication with the specified domain requirements and match the specified filter.
 *
 * @param authentication     the authentication to search with
 * @param context            the context to add credentials from.
 * @param type               the base class of the credentials to add.
 * @param domainRequirements the domain requirements.
 * @param matcher            the filter to apply to the credentials.
 * @return {@code this} for method chaining.
 * @see CredentialsProvider#listCredentials(Class, ItemGroup, Authentication, List, CredentialsMatcher)
 * @since 2.1.0
 */
public AbstractIdCredentialsListBoxModel<T, C> includeMatchingAs(@NonNull Authentication authentication,
                                                                 @NonNull ItemGroup context,
                                                                 @NonNull Class<? extends C> type,
                                                                 @NonNull
                                                                         List<DomainRequirement> domainRequirements,
                                                                 @NonNull CredentialsMatcher matcher) {
    addMissing(CredentialsProvider.listCredentials(type, context, authentication, domainRequirements, matcher));
    return this;
}