Gitlab CI评论应用程序 - 将部署脚本中的信息返回到gitlab ci环境变量中

时间:2016-12-08 09:40:24

标签: ansible gitlab ansible-playbook gitlab-ci

我使用gitlab-ci进行自动化测试。现在,我将其扩展到允许通过一个安全的剧本部署在数字海洋飞沫上的评论应用程序。

这非常有效,但是我需要从ansible到.gitlab-ci获取一个变量 - 我无法找到它的方法。

.gitlab-ci.yml

Deploy for Review:
  before_script: []
  stage: review
  script: 'cd  /home/playbooks/oewm/deployment && ansible-playbook -i inventories/review --extra-vars "do_name=$CI_PIPELINE_ID api_git_branch=$CI_BUILD_REF_NAME" digitalocean.yml'
  environment:
    name: review/$CI_BUILD_REF_NAME
    url: http://$IP_FROM_ANSIBLE
    on_stop: "Stop Review"
  only:
    - branches
  when: manual
  tags:
    - deploy

剧本中的相关部分:

- name: Create DO Droplet
  delegate_to: localhost
  local_action:
    module: digital_ocean
         state=present
         command=droplet
         name=review-{{ do_name }}
         api_token={{ do_token }}
         region_id={{ do_region }}
         image_id={{ do_image }}
         size_id={{ do_size }}
         ssh_key_ids={{ do_ssh }}
         wait_timeout=500
  register: my_droplet

- name: print info about droplet
  delegate_to: localhost
  local_action:
    module:  debug
        msg="ID is {{ my_droplet.droplet.id }} IP is {{ my_droplet.droplet.ip_address }}"

那么如何才能将gletlab-ci的Droplet ID和IP? (稍后的停止操作需要ID,要向开发人员查看IP)

2 个答案:

答案 0 :(得分:3)

Ansible是一个YAML配置的脚本工具本身,可能几乎完全自动化脚本环境本身。为什么不让它在某处写一个名为“./ip_address.sh”的文件,然后将.sh包含在你的gitlab CI中?

所有这一切的最高级别,在.gitlab-ci.yml中会有:

script:
   - ./run_ansible.sh ./out/run_file_generated_from_ansible.sh
   - . ./out/run_file_generated_from_ansible.sh
   - echo $IP_FROM_ANSIBLE
environment:
  name: review/$CI_BUILD_REF_NAME
  url: http://$IP_FROM_ANSIBLE
  on_stop: "Stop Review"

将上面的两个shell脚本编写为读者的练习。魔法发生在Ansible“playbook”里面,它实际上只是一个脚本,你用文件名“./out/run_file_generate_from_ansible.sh”“将变量导出到磁盘”。

你没有说清楚的是你需要在Gitlab-CI中使用该变量以及最终结果,以及接下来会发生什么。所以上面,我只是展示了一种可以通过临时磁盘文件(IP地址)“导出”的方法。

您可以将该导出值保存为工件并在其他阶段捕获它,因此如果将所有这些工具放在名为./out的目录中,则可以在各阶段之间传递这种“工件导出”。在gitlab-ci.yml中声明一个artifacts语句。

答案 1 :(得分:1)

我终于得到了运行的设置。我的解决方案使用AWS Route53生成动态主机名。 (我忽略了一个问题 - 我需要不同评论应用的主机名)

第1步: 动态构建主机名。为此,我使用了$CI_PIPELINE_ID我在Route53上创建了一个子域,我们将其称为review.mydomain.com。 Ansible Playbook从create_droplet获取IP,并使用Pipeline id在Route53上创建记录。 1234.review.mydomain.com

现在我的.gitlab-ci.yml知道这个主机名(因为它可以随时构建它) - 不再需要将Digitalocean Droplet IP从ansible skript中取出。

第2步: 审查后 - 用户应该能够停止/销毁液滴。为此,我需要在创建此Droplet时获得的Droplet ID。 但是破坏是一个不同的剧本,将在稍后播放 - 由开发人员调用 所以我需要一种在某处存储变量的方法 但是等等,现在我知道它是哪个主机,我可以在这个主机上创建一个事实文件,为我存储ID。当我需要摧毁主人时,ansible向我提供了事实,我知道身份证。

在剧本中它看起来像这样:

角色:digitalocean

---
- name: Create DO Droplet
  delegate_to: localhost
  local_action:
    module: digital_ocean
         state=present
         command=droplet
         name=oewm-review-{{ do_name }}
         api_token={{ do_token }}
         region_id={{ do_region }}
         image_id={{ do_image }}
         size_id={{ do_size }}
         ssh_key_ids={{ do_ssh }}
         wait_timeout=500
  register: my_droplet

- name: print info about droplet
  delegate_to: localhost
  local_action:
    module:  debug
        msg="DO-ID:{{ my_droplet.droplet.id }}"

- name: print info about droplet
  delegate_to: localhost
  local_action:
    module:  debug
        msg="DO-IP:{{ my_droplet.droplet.ip_address }}"

# DNS
- name: Get existing host information
  route53:
    command: get
    zone: "{{ r53_zone }}"
    record: "{{ do_name }}.review.mydomain.com"
    type: A
    aws_access_key: "{{ r53_access_key }}"
    aws_secret_key: "{{ r53_secret_key }}"
  register: currentip

- name: Add DNS Record for Web-Application
  route53:
    command: create
    zone: "{{ r53_zone }}"
    record: "{{ do_name }}.review.mydomain.com"
    type: A
    ttl: 600
    value: "{{ my_droplet.droplet.ip_address }}"
    aws_access_key: "{{ r53_access_key }}"
    aws_secret_key: "{{ r53_secret_key }}"
  when: currentip.set.value is not defined

- name: Add DNS Record for API
  route53:
    command: create
    zone: "{{ r53_zone }}"
    record: "api.{{ do_name }}.review.mydomain.com"
    type: A
    ttl: 600
    value: "{{ my_droplet.droplet.ip_address }}"
    aws_access_key: "{{ r53_access_key }}"
    aws_secret_key: "{{ r53_secret_key }}"
  when: currentip.set.value is not defined

- name: Add new droplet to host group
  add_host:
    hostname: "{{ my_droplet.droplet.ip_address }}"
    groupname: api,web-application
    ansible_user: root
    api_domain: "api.{{ do_name }}.review.mydomain.com"
    app_domain: "{{ do_name }}.review.mydomain.com"

- name: Wait until SSH is available on {{ my_droplet.droplet.ip_address }}
  local_action:
    module: wait_for
    host: "{{ my_droplet.droplet.ip_address }}"
    port: 22
    delay: 5
    timeout: 320
    state: started

Playbook digitalocean.yml:

---
- name: Launch DO Droplet
  hosts: all
  run_once: true
  gather_facts: false
  roles:
    - digitalocean

- name: Store Facts
  hosts: api
  tasks:
    - name: Ensure facts directory exists
      file:
        path: "/etc/ansible/facts.d"
        state: directory

    - name: store variables on host for later fact gathering
      template:
        src={{ playbook_dir }}/roles/digitalocean/templates/digitalocean.fact.js2
        dest="/etc/ansible/facts.d/digitalocean.fact"
        mode=0644

- name: Deploy 
  hosts: api
  roles:
    - deployroles

Playbook digitalocean_destroy.yml:

- name: Add Host to Inventory
  hosts: all
  vars:
    r53_zone: review.mydomain.com
    r53_access_key: "xxxx"
    r53_secret_key: "xxxx"
  tasks:
    - name: Get existing DNS host information
      route53:
        command: get
        zone: "{{ r53_zone }}"
        record: "{{ do_name }}.review.mydomain.com"
        type: A
        aws_access_key: "{{ r53_access_key }}"
        aws_secret_key: "{{ r53_secret_key }}"
      register: currentip

    - name: Remove DNS Record for Web-Application
      route53:
        command: delete
        zone: "{{ r53_zone }}"
        record: "{{ do_name }}.review.mydomain.com"
        type: A
        ttl: 600
        value: "{{ my_droplet.droplet.ip_address }}"
        aws_access_key: "{{ r53_access_key }}"
        aws_secret_key: "{{ r53_secret_key }}"
      when: currentip.set.value is defined

    - name: Remove DNS Record for API
      route53:
        command: delete
        zone: "{{ r53_zone }}"
        record: "api.{{ do_name }}.review.mydomain.com"
        type: A
        ttl: 600
        value: "{{ my_droplet.droplet.ip_address }}"
        aws_access_key: "{{ r53_access_key }}"
        aws_secret_key: "{{ r53_secret_key }}"
      when: currentip.set.value is defined

    - name: Add droplet to host group
      add_host:
        hostname: "{{ do_name }}.review.mydomain.com"
        groupname: api,web-application
        ansible_user: root

- name: Digitalocean
  hosts: api
  vars:
    do_token: xxxxx
  tasks:
    - name: Delete Droplet
      delegate_to: localhost
      local_action:
        module: digital_ocean
             state=deleted
             command=droplet
             api_token={{ do_token }}
             id="{{ ansible_local.digitalocean.DO_ID }}"

.gitlab-ci.yml的相关部分:

Deploy for Review:
  before_script: []
  stage: review
  script:
    - 'cd  /home/playbooks/myname/deployment && ansible-playbook -i inventories/review --extra-vars "do_name=$CI_PIPELINE_ID api_git_branch=$CI_BUILD_REF_NAME" digitalocean.yml'
  environment:
    name: review/$CI_BUILD_REF_NAME
    url: http://$CI_PIPELINE_ID.review.mydomain.com
    on_stop: "Stop Review"
  only:
    - branches
  when: manual
  tags:
    - deploy

Stop Review:
  before_script: []
  stage: review
  variables:
    GIT_STRATEGY: none
  script:
    - 'cd  /home/playbooks/myname/deployment && ansible-playbook -i inventories/review --extra-vars "do_name=$CI_PIPELINE_ID" digitalocean_destroy.yml'
  when: manual
  environment:
    name: review/$CI_BUILD_REF_NAME
    action: stop
  only:
    - branches
  tags:
    - deploy

# STAGING
Deploy to Staging:
  before_script: []
  stage: staging
  script:
    - 'cd  /home/playbooks/myname/deployment && ansible-playbook -i inventories/staging --extra-vars "api_git_branch=$CI_BUILD_REF_NAME" deploy.yml'
  environment:
    name: staging
    url: https://staging.mydomain.com
  when: manual
  tags:
    - deploy