post image :date_long | 4 min Read

How to create resource in Bitbucket via curl and Ansible

There are some situation when one can have credentials to some web page that does not have API properly exposed and TOKEN can not be used. However, when trying to do certain action e.g. import Bitbucket repo from already existing repo - this is doable by clicking in a web browser using username and password. In this particular situation the reference/sample code can be found in variable SAMPLE_PROJECT_URL.

In this case one can take an advantage of cookies and trying to simulate a browser.

export PASSWORD='...'
export USERNAME='...'
export BB_PROJECT_NAME="PROJECT-NAME"
export BITBUCKET_REPO_NAME="REPO-NAME"
export SAMPLE_PROJECT_URL="https://example.net/scm/example-solutions/sample-valid.git"

# repo level
export WRITERS="<username1> <username2> ..."
export ADMINS="<username4> <username5> ..."

echo -e "\n\nCreting a project\n"

curl -u "${USERNAME}:${PASSWORD}" -k --url "https://bitbucket.url.example/rest/api/latest/projects" \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{
  "key": "'"${BB_PROJECT_NAME}"'"
}'

echo -e "\n\nGET a project\n"

curl -u "${USERNAME}:${PASSWORD}" -k --url 'https://bitbucket.url.example/rest/api/latest/projects/'"${BB_PROJECT_NAME}"'' \
--header 'Accept: application/json' \
--header 'Content-Type: application/json'

echo -e "\n\nGrant permissions to ed pas horizon\n"

curl -u "${USERNAME}:${PASSWORD}" -k --request PUT \
  --url 'https://bitbucket.url.example/rest/api/latest/projects/'"${BB_PROJECT_NAME}"'/permissions/groups' \
  --header 'Accept: application/json' \
  --url-query "name=<group-name>" \
  --url-query "permission=PROJECT_ADMIN"

# ............................................
# Import/crate new repo with sample code
# ............................................

rm /tmp/cookies.txt
curl -G -k -c - 'https://bitbucket.url.example/j_atl_security_check' \
  -H "Content-Type: application/x-www-form-urlencoded; Charset=utf-8" \
  --data-urlencode "j_username=${USERNAME}" \
  --data-urlencode "j_password=${PASSWORD}" \
  --data-urlencode "queryString=native_login=" \
  --data-urlencode "submit=Log in" > /tmp/cookies.txt

curl -k  -b /tmp/cookies.txt 'https://bitbucket.url.example/rest/importer/latest/projects/'"${BB_PROJECT_NAME}"'/import/repos' \
  --header 'Content-Type: application/json' \
  --data '{
    "externalRepositories":[{
      "cloneUrl":"'"${SAMPLE_PROJECT_URL}"'",
      "name":"'"${BITBUCKET_REPO_NAME}"'",
      "scmId":"git"
    }]
  }'


# echo -e "\n\nCreate repository\n"

# curl -u "${USERNAME}:${PASSWORD}" -k --url 'https://bitbucket.url.example/rest/api/1.0/projects/'"${BB_PROJECT_NAME}"'/repos' \
# --header 'Accept: application/json' \
# --header 'Content-Type: application/json' \
# --data '{
#   "name": "'"${BITBUCKET_REPO_NAME}"'",
#   "project": {
#     "key": "'"${BB_PROJECT_NAME}"'"
#   },
#   "slug": "'"${BITBUCKET_REPO_NAME}"'",
#   "scmId": "git"
# }'

echo -e "\n\nGrant users WRITE permissions\n"

curl  -k -X PUT \
-u "${USERNAME}:${PASSWORD}" \
--url 'https://bitbucket.url.example/rest/api/latest/projects/'"${BB_PROJECT_NAME}"'/repos/'"${BITBUCKET_REPO_NAME}"'/permissions/users' \
--header 'Accept: application/json' --header 'Content-Type: application/json' $(for i in $(echo $WRITERS); do echo -n --url-query name=$i" " ; done) \
--url-query "permission=REPO_WRITE"

echo -e "\n\nGrant users ADMIN permissions\n"

curl  -k -X PUT \
-u "${USERNAME}:${PASSWORD}" \
--url 'https://bitbucket.url.example/rest/api/latest/projects/'"${BB_PROJECT_NAME}"'/repos/'"${BITBUCKET_REPO_NAME}"'/permissions/users' \
--header 'Accept: application/json' --header 'Content-Type: application/json' $(for i in $(echo $ADMINS); do echo -n --url-query name=$i" " ; done) \
--url-query "permission=REPO_ADMIN"

Ansible version

---
# .........................................................................
# 1. Creating Bitbucket project
# .........................................................................
- name: Read input yaml file
  ansible.builtin.shell: "cat {{ DEFINITION_FILE }}"
  register: result

- name: Load input data into data variable
  set_fact:
    data: "{{ result.stdout | from_yaml }}"


- name: creating Bitbucket project
  uri:
    url: "{{ BITBUCKET_URL }}/rest/api/latest/projects"
    user: "{{ BITBUCKET_USER }}"
    password: "{{ BITBUCKET_PASS }}"
    force_basic_auth: yes
    headers:
      Content-Type: "application/json"
      Accept: "application/json"
    method: POST
    body: |
      {
        "key": "{{ data | json_query('bb_project') }}"
      }
    validate_certs: False
    body_format: json
    status_code: [200, 201, 409]
  register: _response

# .........................................................................
# 2. Granting PROJECT_ADMIN to BB_GROUP_NAME group at Bitbucket project level
# .........................................................................
- name: Grant permissions to group BB_GROUP_NAME
  uri:
    url: "{{ BITBUCKET_URL }}/rest/api/latest/projects/{{ data | json_query('bb_project') }}/permissions/groups?name={{ BB_GROUP_NAME | urlencode}}&permission=PROJECT_ADMIN"
    user: "{{ BITBUCKET_USER }}"
    password: "{{ BITBUCKET_PASS }}"
    force_basic_auth: yes
    headers:
      Accept: "application/json"
    method: PUT
    validate_certs: False
    status_code: [200, 201, 204]
  register: _response

# .........................................................................
# 3. Import/create new repo with sample code
# .........................................................................
- name: import/create new repo with sample code
  uri:
    url: "{{ BITBUCKET_URL }}/rest/importer/latest/projects/{{ data | json_query('bb_project') }}/import/repos"
    user: "{{ BITBUCKET_USER }}"
    password: "{{ BITBUCKET_PASS }}"
    force_basic_auth: yes
    headers:
      Content-Type: "application/json"
      Accept: "application/json"
    method: POST
    body: |
      {
      "externalRepositories":[{
        "cloneUrl":"{{ SAMPLE_PROJECT_URL }}",
        "name":"{{ data | json_query('bb_repo') }}",
        "scmId":"git"
      }]
      }
    validate_certs: False
    body_format: json
    status_code: [200, 201, 409]
  register: _response

# .........................................................................
# 4. Grant neceassary permissions to Bitbucket repo
# .........................................................................

- name: grant neceassary permissions to Bitbucket repo REPO_ADMIN
  uri:
    url: "{{ BITBUCKET_URL }}/rest/api/latest/projects/{{ data | json_query('bb_project') }}/repos/{{ data | json_query('bb_repo') }}/permissions/users?permission=REPO_ADMIN{% for item in data | json_query('bb_repo_admins') %}&name={{ item }}{% endfor %}"
    user: "{{ BITBUCKET_USER }}"
    password: "{{ BITBUCKET_PASS }}"
    force_basic_auth: yes
    headers:
      Content-Type: "application/json"
      Accept: "application/json"
    method: PUT
    body_format: form-urlencoded
    validate_certs: False
    status_code: [200, 201, 204]
  register: _response

202407250907

author image

Jan Toth

I have been in DevOps related jobs for past 6 years dealing mainly with Kubernetes in AWS and on-premise as well. I spent quite a lot …

comments powered by Disqus