Search code examples
apiansiblerepositoryartifactory

Ansible: How to check if an Artifactory Repository exist or not, if it exists update the Repository configuration, if not create the Repository


How we can use when condition in an Ansible playbook to check if an Artifactory Repository exist or not, if it exists update the Repository configuration, if not create the Repository. For all, create and update I am using the REST API.

Here I am using the REST API from JFrog Artifactory, I don't want to write any Python or Shell script. I need to do all with Ansible by using Conditionals.

I have tried:

 - name: Update Repository Configuration
    uri:
      url: (url)/api/repositories/docker-remote
      method: POST
      headers:
        Content-Type: application/json
      body_format: json
      body: "{{ lookup('file','/docker-remote.json') }}"
      follow_redirects: all
      url_username: "user"
      url_password: "pass"
      force_basic_auth: yes
      status_code: 200
      return_content: yes
    delegate_to: localhost
    when: status_code == 200
    register: result

  - name: Create Repository
    uri:
      url: (url)/api/repositories/docker-remote
      method: PUT
      headers:
        Content-Type: application/json
      body_format: json
      body: "{{ lookup('file','docker-remote.json') }}"
      follow_redirects: all
      url_username: "user"
      url_password: "pass"
      force_basic_auth: yes
      status_code: 200
      return_content: yes
    delegate_to: localhost
    register: result
    when: status_code == 400

Solution

  • You've almost achieved your goal. Since Ansible is a tool for Configuration Management, one need only to make sure that there is a Desired State configured.

    ... check if an Artifactory Repository exist or not, if it exists update the Repository configuration, if not create the Repository ...

    In other words, there is no need to check before or to do something like IF THEN ELSE. It is only necessary to declare how the final state should look like. Based on your already given example you could proceed further with the following ...

    A sample repository configuration set in JSON representation, TEST.json

    {
      "key" : "TEST",
      "rclass" : "local",
      "repoLayoutRef": "simple-default",
      "description" : "Local generic test repository",
      "url" : "https://<yourRepositoryURL>/artifactory/TEST",
      "packageType": "Generic"
    }
    

    and a sample test playbook create_repository.yml

    ---
    - hosts: localhost
      become: no
      gather_facts: no
    
      vars:
    
        API_URL: "<yourRepositoryURL>/artifactory/api"
        REST_API_ENDPOINT: "repositories" # since there are also access and security ...
        RKEY: "TEST" # aka REPOSITORY_KEY
    
      tasks:
    
      - name: Read in repository configuration
        include_vars:
          file: "{{ RKEY }}.json"
          name: CONFIG
        when: not ansible_check_mode
    
      - name: Make sure repository is created
        local_action:
          module: uri
          url: "https://{{ API_URL }}/{{ REST_API_ENDPOINT }}/{{ RKEY }}"
          method: PUT
          url_username: "{{ ansible_user }}"
          url_password: "{{ ansible_password }}"
          validate_certs: yes
          body_format: json
          body: "{{ CONFIG }}"
          status_code: 200,400
        register: PUT
        failed_when: false
        when: not ansible_check_mode
    
      - name: Make sure repository is in desired state
        local_action:
          module: uri
          url: "https://{{ API_URL }}/{{ REST_API_ENDPOINT }}/{{ RKEY }}"
          method: POST
          url_username: "{{ ansible_user }}"
          url_password: "{{ ansible_password }}"
          validate_certs: yes
          body_format: json
          body: "{{ CONFIG }}"
          status_code: 200
        when: not ansible_check_mode and PUT.status == 400
    
      - name: Gather current repository configuration, if there is one
        local_action:
          module: uri
          url: "https://{{ API_URL }}/{{ REST_API_ENDPOINT }}/{{ RKEY }}"
          method: GET
          url_username: "{{ ansible_user }}"
          url_password: "{{ ansible_password }}"
          validate_certs: yes
          return_content: yes
          status_code: 200,400
          body_format: json
        register: GET
        check_mode: false
    
      - name: Show repository configuration, if there is one
        debug:
          msg: "{{ GET.json }}"
        check_mode: false
    

    to call via

    sshpass -p ${PASSWORD} ansible-playbook --user ${ACCOUNT} --ask-pass create_repository.yml --check
    sshpass -p ${PASSWORD} ansible-playbook --user ${ACCOUNT} --ask-pass create_repository.yml
    

    If the given repository configuration is not available within Artifactory, the first REST API call will result into the creation of it and an status code of 200. After that there would be no need for an update. Therefore, when: PUT.status == 400.

    If the given repository configuration is already available within Artifactory, the first REST API call result into an status code of 400, which is then considered not as an error. After that another REST API call makes sure that the configuration is in the desired state.