Implement custom credentials for a GitLab API token (Fixes #332)

- this custom credentials implementation provides the possibility to use labels and description text that makes it easier to configure a GitLabConnection
This commit is contained in:
Robin Müller 2016-06-25 14:51:26 +02:00
parent 783b0420a0
commit 336ffe705f
9 changed files with 75 additions and 7 deletions

View File

@ -68,7 +68,7 @@ This is not an exhaustive list of issues, but rather a place for us to note sign
Optionally, the plugin communicates with the GitLab server in order to fetch additional information. At this moment, this information is limited to fetching the source project of a Merge Request, in order to support merging from forked repositories.
To enable this functionality, a user should be set up on GitLab, with GitLab 'Developer' permissions, to access the repository. You will need to give this user access to each repo you want Jenkins to be able to clone. Log in to GitLab as that user, go to its profile, and copy its secret API key. On the Global Configuration page in Jenkins, supply the GitLab host URL, e.g. ``http://your.gitlab.server.`` Click the 'Add' button to add a credential, choose 'Secret text' as the kind of credential, and paste your GitLab user's API key into the 'Secret' field. Testing the connection should succeed.
To enable this functionality, a user should be set up on GitLab, with GitLab 'Developer' permissions, to access the repository. You will need to give this user access to each repo you want Jenkins to be able to clone. Log in to GitLab as that user, go to its profile, and copy its secret API key. On the Global Configuration page in Jenkins, supply the GitLab host URL, e.g. ``http://your.gitlab.server.`` Click the 'Add' button to add a credential, choose 'GitLab API token' as the kind of credential, and paste your GitLab user's API key into the 'API token' field. Testing the connection should succeed.
## Jenkins Job Configuration
### Git configuration for Freestyle jobs

View File

@ -180,6 +180,7 @@
<groupId>org.jenkins-ci.plugins</groupId>
<artifactId>plain-credentials</artifactId>
<version>1.1</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.eclipse.jgit</groupId>

View File

@ -0,0 +1,24 @@
package com.dabsquared.gitlabjenkins.connection;
import com.cloudbees.plugins.credentials.CredentialsNameProvider;
import com.cloudbees.plugins.credentials.NameWith;
import com.cloudbees.plugins.credentials.common.StandardCredentials;
import hudson.Util;
import hudson.util.Secret;
/**
* @author Robin Müller
*/
@NameWith(GitLabApiToken.NameProvider.class)
public interface GitLabApiToken extends StandardCredentials {
Secret getApiToken();
class NameProvider extends CredentialsNameProvider<GitLabApiToken> {
@Override
public String getName(GitLabApiToken c) {
String description = Util.fixEmptyAndTrim(c.getDescription());
return Messages.GitLabApiToken_name() + (description != null ? " (" + description + ")" : "");
}
}
}

View File

@ -0,0 +1,34 @@
package com.dabsquared.gitlabjenkins.connection;
import com.cloudbees.plugins.credentials.CredentialsScope;
import com.cloudbees.plugins.credentials.impl.BaseStandardCredentials;
import hudson.Extension;
import hudson.util.Secret;
import org.kohsuke.stapler.DataBoundConstructor;
/**
* @author Robin Müller
*/
public final class GitLabApiTokenImpl extends BaseStandardCredentials implements GitLabApiToken {
private Secret apiToken;
@DataBoundConstructor
public GitLabApiTokenImpl(CredentialsScope scope, String id, String description, Secret apiToken) {
super(scope, id, description);
this.apiToken = apiToken;
}
@Override
public Secret getApiToken() {
return apiToken;
}
@Extension
public static class DescriptorImpl extends BaseStandardCredentialsDescriptor {
@Override
public String getDisplayName() {
return Messages.GitLabApiToken_name();
}
}
}

View File

@ -5,7 +5,6 @@ import com.cloudbees.plugins.credentials.CredentialsMatcher;
import com.cloudbees.plugins.credentials.common.AbstractIdCredentialsListBoxModel;
import com.cloudbees.plugins.credentials.common.StandardCredentials;
import com.cloudbees.plugins.credentials.common.StandardListBoxModel;
import com.cloudbees.plugins.credentials.common.UsernamePasswordCredentials;
import com.cloudbees.plugins.credentials.domains.DomainRequirement;
import com.dabsquared.gitlabjenkins.gitlab.GitLabClientBuilder;
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabApi;
@ -171,7 +170,7 @@ public class GitLabConnectionConfig extends GlobalConfiguration {
private static class GitLabCredentialMatcher implements CredentialsMatcher {
@Override
public boolean matches(@NonNull Credentials credentials) {
return credentials instanceof StringCredentials || credentials instanceof UsernamePasswordCredentials;
return credentials instanceof GitLabApiToken || credentials instanceof StringCredentials;
}
}
}

View File

@ -2,8 +2,8 @@ package com.dabsquared.gitlabjenkins.gitlab;
import com.cloudbees.plugins.credentials.CredentialsMatchers;
import com.cloudbees.plugins.credentials.common.StandardCredentials;
import com.cloudbees.plugins.credentials.common.UsernamePasswordCredentials;
import com.cloudbees.plugins.credentials.domains.DomainRequirement;
import com.dabsquared.gitlabjenkins.connection.GitLabApiToken;
import com.dabsquared.gitlabjenkins.connection.GitLabConnection;
import com.dabsquared.gitlabjenkins.gitlab.api.GitLabApi;
import com.dabsquared.gitlabjenkins.util.JsonUtil;
@ -90,10 +90,11 @@ public class GitLabClientBuilder {
lookupCredentials(StandardCredentials.class, (Item) null, ACL.SYSTEM, new ArrayList<DomainRequirement>()),
CredentialsMatchers.withId(apiTokenId));
if (credentials != null) {
if (credentials instanceof GitLabApiToken) {
return ((GitLabApiToken) credentials).getApiToken().getPlainText();
}
if (credentials instanceof StringCredentials) {
return ((StringCredentials) credentials).getSecret().getPlainText();
} else if (credentials instanceof UsernamePasswordCredentials) {
return ((UsernamePasswordCredentials) credentials).getPassword().getPlainText();
}
}
throw new IllegalStateException("No credentials found for credentialsId: " + apiTokenId);

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form" xmlns:st="jelly:stapler">
<f:entry title="${%API token}" field="apiToken">
<f:password/>
</f:entry>
<st:include page="id-and-description" class="${descriptor.clazz}"/>
</j:jelly>

View File

@ -14,7 +14,7 @@
<f:entry title="${%Gitlab host URL}" field="url" description="${%The complete URL to the Gitlab server} (${%i.e. http://gitlab.org})">
<f:textbox value="${connection.url}"/>
</f:entry>
<f:entry title="${%API Token}" field="apiTokenId" description="${%API Token for accessing Gitlab}">
<f:entry title="${%Credentials}" field="apiTokenId" description="${%API Token for accessing Gitlab}">
<c:select/>
</f:entry>
<f:advanced>

View File

@ -6,3 +6,4 @@ connectionTimeout.required=Connection timeout is required
readTimeout.required=Read timeout is required
connection.success=Success
connection.error=Client error: {0}
GitLabApiToken.name=GitLab API token