Babken Vardanyan
Babken Vardanyan

Reputation: 15090

How to create Django superuser in Ansible in idempotent way?

I am using Ansible to deploy my Django app.

I have this step in my Ansible playbook for creating a superuser:

  - name: django create superuser
    django_manage:
      virtualenv: /.../app
      app_path: /.../app
      command: "createsuperuser --noinput --username=admin --email=admin@{{ inventory_hostname }}"

But when I run my playbook a second time it fails with database constraint error since a superuser with given username already exists. I want Ansible to create the user only once.

How do I make this step idempotent?

Upvotes: 2

Views: 2267

Answers (3)

Christopher Causer
Christopher Causer

Reputation: 1494

Antonis Christofides's answer served as an inspiration for what follows, but there were a few areas that required improvement:

  1. This version is tested and works for me
  2. django_manage does not work in check_mode
  3. django_manage does not expose rc. In fact, it treats a non-zero exit as an error!

I've made my working copy more generic for SO, and obviously you'll need to supply your own variables.

- name: Check if django superuser {{ username }} exists
  django_manage:
    command: shell -c 'import sys; from django.contrib.auth.models import User; print(User.objects.filter(username="{{ username }}").count())'
    virtualenv: "{{ working_directory }}/venv"
    project_path: "{{ working_directory }}"

  register: checksuperuser
  ignore_errors: True
  changed_when: False      

- name: django create superuser {{ username }}
  django_manage:
    command: "createsuperuser --noinput --username={{ username }} --email={{ username }}@change-me.example.org"
    virtualenv: "{{ working_directory}}/venv"
    project_path: "{{ working_directory }}"
  when: checksuperuser.out|trim == "0"
  changed_when: True
  ignore_errors: True

Upvotes: 0

MartinsM
MartinsM

Reputation: 110

Another option is to tell ansible to ignore the error:

- name: django create superuser
  django_manage:
    virtualenv: /.../app
    app_path: /.../app
    command: "createsuperuser --noinput --username=admin --email=admin@{{ inventory_hostname }}"
  ignore_errors: yes

Upvotes: 2

Antonis Christofides
Antonis Christofides

Reputation: 6939

This is untested but it should work:

- name: Check if django superuser exists
  django_manage:
    virtualenv: /.../app
    app_path: /.../app
    command: shell -c 'import sys; from django.contrib.auth.models import User; sys.exit(0 if User.objects.filter(username="admiin").count() > 0 else 1)'
  register: checksuperuser
  check_mode: True
  ignore_errors: True
  changed_when: False      

- name: django create superuser
  django_manage:
    virtualenv: /.../app
    app_path: /.../app
    command: "createsuperuser --noinput --username=admin --email=admin@{{ inventory_hostname }}"
  when: checksuperuser.rc != 0

Upvotes: 3

Related Questions