Develop/devops

Jenkins API를 이용하여 Item build하기

에디개발자 2021. 3. 10. 07:00
반응형

재직중인 회사에서 자동화를 위해서 Spring-batch와 Jenkins를 이용하여 무언가를 체크하는 로직을 만들었고 요청이 들어올때마다 실행해주고 있었습니다. 하지만 이것도 불편하다!! 웹에서 버튼을 눌렀을 때 Jenkins의 Item을 실행해보자!

나를 닮았다고 한다...

Jenkins Token 발급

먼저 Jenkins에서 Token을 발급받아야만 Jenkins API를 사용할 수 있습니다. Token을 발급받아보겠습니다. 먼저 People에 들어가 발급받는 유저를 선택하고 Configure로 진입합니다.

People 선택 후 화면
사용자 선택 후 화면

 

구성화면에 진입한 후 Add New Token 버튼을 클릭합니다.

 

토큰 명을 입력하고 Generate 버튼을 클릭합니다.

생성된 토큰을 저장합니다.

Code 작성

Jenkins와 통실할 클래스를 생성합니다. 

application.yaml

jenkins:
  url: localhost:8080
  user: limyongtae 
  token: 148ca24cccc51e1dddde3affffafaad9e5

jenkins의 정보를 입력합니다.

  • url : jenkins의 url
  • user : 이전 단락에서 토큰을 발급받은 user
  • token : 이전 단락에서 저장한 토큰

JenkinsProperties

application.yaml에서 설정한 jenkins properties 클래스입니다.

@Configuration
@ConfigurationProperties(prefix = "jenkins")
@Getter @Setter
public class JenkinsProperties {
    private String url;
    private String user;
    private String token;
}

JenkinsUrl

먼저 상수 열거형(enum)에 Jenkins로 배포할 url 정보를 선언합니다.

@Getter
public enum JenkinsUrl {
    BUILD("/build"),
    BUILD_WITH_PARAMS("/buildWithParameters"),
    JENKINS_URL_PATTERN("http://%s/job/%s/%s");

    private String url;

    JenkinsUrl(String url) {
        this.url = url;
    }
}

JenkinsParamCollection

Jenkins 배포 시 parameter를 설정할 경우 사용되는 일급 컬렉션입니다.

public class JenkinsParamCollection {
    private final MultiValueMap<String, String> postParams;

    public JenkinsParamCollection(MultiValueMap<String, String> postParams) {
        this.postParams = postParams;
    }

    public void put(String key, String value) {
        postParams.set(key, value);
    }

    public void put(String key, List<String> values) {
        postParams.put(key, values);
    }

    public List<String> get(String key) {
        return postParams.get(key);
    }
}

여기서 주의깊게 살펴보실 내용은 일반 Map을 쓰지않고 MultiValueMap을 사용하였습니다. 이유는 파라미터로 동일한 Key에 다른 Value값을 주입할 수 있도록 하기 위해서입니다.

RestClient

API 통신 Client입니다.

@Component
@RequiredArgsConstructor
public class RestClient {
    private final RestTemplate restTemplate;

    private final String HEADER_BASIC = "Basic ";
    private final String AUTHORIZATION = "Authorization";

    public <T> ResponseEntity<T> get(final String url, final Class<T> responseType) {
        return restTemplate.getForEntity(url, responseType);
    }

    public <T> ResponseEntity<T> post(final String url, Object request, final Class<T> responseType) {
        return restTemplate.postForEntity(url, request, responseType);
    }

    public void put(final String url, final Object request) {
        restTemplate.put(url, request);
    }

    public void delete(final String url) {
        restTemplate.delete(url);
    }

    public void addHeader(String username, String token) {
        String authHeaderValue = HEADER_BASIC + Base64.getEncoder().encodeToString((username + ":" + token).getBytes(StandardCharsets.UTF_8));

        restTemplate.getInterceptors().add((request, body, execution) -> {
            HttpHeaders headers = request.getHeaders();
            headers.set(AUTHORIZATION, authHeaderValue);
            return execution.execute(request, body);
        });
    }
}

JenkinsClient

Jenkins와 실제로 통신하는 Client입니다.

public class JenkinsClient {
    private final JenkinsProperties properties;
    private final RestClient restClient;

    private String endpoint;
    private JenkinsParamCollection jenkinsParamCollection;

    public JenkinsClient(JenkinsProperties properties, RestClient restClient) {
        this.properties = properties;
        this.restClient = restClient;
        this.endpoint = JenkinsUrl.BUILD.getUrl();
        this.jenkinsParamCollection = new JenkinsParamCollection(new LinkedMultiValueMap<>());

        setJenkinsConfig();
    }

    public void build(String jobName) {
        String url = generateUrl(jobName);
        this.restClient.post(url, this.jenkinsParamCollection, String.class);
    }

    public void setParameters(Map<String, String> jobParameters) {
        if (jobParameters != null) {
            jobParameters.forEach(this.jenkinsParamCollection::put);
        }

        this.endpoint = JenkinsUrl.BUILD_WITH_PARAMS.getUrl();
    }

    private void setJenkinsConfig() {
        addHeader();
    }

    private void addHeader() {
        this.restClient.addHeader(this.properties.getUser(), this.properties.getToken());
    }

    private String generateUrl(String jobName) {
        return String.format(JenkinsUrl.JENKINS_URL_PATTERN.getUrl(), this.properties.getUrl(), jobName, this.endpoint);
    }
}

Header에 인증 정보를 넣고 요청하는 JenkinsClient입니다. 

반응형