Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OpenShift Resources Role #6

Merged
merged 4 commits into from
Aug 26, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions create-openshift-resources.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
- name: "Create OpenShift Resources"
hosts: localhost

roles:
- openshift-defaults
- create-openshift-resources
99 changes: 99 additions & 0 deletions files/default-vars-tower.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this file for? I don't see it used anywhere in here ... could it be eliminated?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

"docker": {
"common": {
"client_binary": "docker"
},
"registry": {
"host": "registry.apps.env2-1.innovation.labs.redhat.com"
},
"user": {
"email": "Rhc-open-innovation-labs@redhat.com"
}
},
"openshift": {
"common": {
"client_binary": "oc"
}
},
"openshift_host_env": "master1.env2-1.innovation.labs.redhat.com",
"openshift_resources_to_create": {
"projects": [
{
"apps": [
{
"base_image": "openshift/php",
"context_dir": "website",
"git_url": "https://github.com/sherl0cks/infographic.git",
"name": "web"
},
{
"base_image": "openshift/nodejs",
"git_url": "https://github.com/sherl0cks/infographic-node-app.git",
"name": "node-app"
}
],
"display_name": "Infographic - Holmes",
"name": "infographic-holmes"
},
{
"apps": [
{
"base_image": "openshift/nodejs",
"git_url": "https://github.com/mcanoy/infographic-node-app.git",
"name": "node-app"
}
],
"display_name": "Infographic - McAnoy",
"name": "infographic-mcanoy"
},
{
"apps": [
{
"base_image": "openshift/php",
"context_dir": "website",
"git_url": "https://github.com/rht-labs/infographic.git",
"name": "web"
},
{
"base_image": "openshift/nodejs",
"git_url": "https://github.com/rht-labs/infographic-node-app.git",
"name": "node-app"
}
],
"build_environment": true,
"display_name": "Infographic - Dev",
"name": "infographic-dev"
},
{
"apps": [
{
"base_image": "web",
"name": "web"
},
{
"base_image": "node-app",
"name": "node-app"
}
],
"display_name": "Infographic - Stage",
"name": "infographic-stage",
"promotion_environment": true
},
{
"apps": [
{
"base_image": "web",
"name": "web"
},
{
"base_image": "node-app",
"name": "node-app"
}
],
"display_name": "Infographic - Prod",
"name": "infographic-prod",
"promotion_environment": true
}
]
}
}
96 changes: 96 additions & 0 deletions roles/create-openshift-resources/tasks/create_app.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
- name: Fail for Missing git url and base image
fail: msg="This role requires app.git_url or app.base_image to be set and non empty"
when: app.git_url is not defined and app.base_image is not defined

- name: Fail for Missing app name
fail: msg="This role requires app.name to be set and non empty"
when: app.name is not defined and app.name == ''

- name: Fail for Missing project name
fail: msg="This role requires project.name to be set and non empty"
when: project.name is not defined and project.name == ''

- name: "Set App Basic Facts"
set_fact:
app_options: ''
app_source: ''

- name: "Set App Source with Git Url and Base Image"
set_fact:
app_source: "{{ app.base_image }}~{{ app.git_url }}"
when: app.git_url is defined and app.git_url != '' and app.base_image is defined and app.base_image != ''

- name: "Set App Source with only Base Image"
set_fact:
app_options: "{{ app_options }} --image-stream={{ app.base_image }}"
when: (app.base_image is defined and app.base_image != '') and (app.git_url is not defined or app.git_url == '')

- name: "Set App Source with only Git Url"
set_fact:
app_source: "{{ app.git_url }}"
when: (app.git_url is defined and app.git_url != '') and (app.base_image is not defined or app.base_image == '')

- name: "Add context-dir Option"
set_fact:
app_options: "{{ app_options }} --context-dir={{ app.context_dir }}"
when: app.context_dir is defined and app.context_dir != ''

- name: "Add name Option"
set_fact:
app_options: "{{ app_options }} --name={{ app.name }}"
when: app.name is defined and app.name != ''

- name: "Determine if {{ app.name }} App Exists"
command: >
{{ openshift.common.client_binary }} get dc {{ app.name }} -n {{ project.name }} -o json
register: get_app_name_result
failed_when: false
changed_when: false

# This covers the corner case where we are making an app from an imagestream in the same workspace
# Was useful in testing, not sure if really needed
- name: "Determine if {{ app.base_image }} Imagestream Exists"
command: >
{{ openshift.common.client_binary }} get istag {{ app.base_image }}:latest -n {{ project.name }} -o json
register: get_imagestream_result
when: ( not ('/' in app.base_image) ) and build_project_name == project.name
failed_when: false
changed_when: false
until: get_imagestream_result.rc == 0
retries: 12
delay: 5
ignore_errors: yes

## This is confusing to me. Dunno why the app_item is not passed to the includes context...
- name: Set Facts Not Sure Why
set_fact:
app_name: "{{ app.name }}"
project_name: "{{ project.name }}"
when: get_app_name_result.rc == 1 and project.promotion_environment is defined and project.promotion_environment == true

- include: promote_image.yml
when: get_app_name_result.rc == 1 and project.promotion_environment is defined and project.promotion_environment == true

- name: "Create App: {{ app.name }}"
command: >
{{ openshift.common.client_binary }} new-app {{ app_source }} -n {{ project.name }} {{ app_options }}
when: get_app_name_result.rc == 1
register: create_app_result

- name: "Expose App: {{ app.name }}"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are we always going to just use the app.name for the route, or should we allow for custom routes? I think the latter would be good, but may introduce a bit of complexity that's not needed for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree here. Do you want that changed before merge?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can merge this as-is for now, and enhance this later on

command: >
{{ openshift.common.client_binary }} expose service {{ app.name }} -n {{ project.name }}
when: get_app_name_result.rc == 1 and create_app_result.rc == 0

# TODO Add a check here to make sure build passed

- name: "Wait For Image To Be Published if Build Environment"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you mean to say "in" instead of "if" here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nah it means if. There is a when here that only waits to ensure the image is published if the image is part of a build environment. This helps the playbook run faster, although it does mean failures are possible in developer sandboxes if say the github url is wrong

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh, sure - thx for the clarification. I didn't look far enough into the implementation - just reading it made it a bit unclear.

command: >
{{ openshift.common.client_binary }} get istag {{ app.name }}:latest -n {{ project.name }} -o json
register: get_build_imagestream_result
when: build_project_name == project.name and app.git_url is defined and app.git_url != ''
changed_when: false
until: get_build_imagestream_result.rc == 0
retries: 60
delay: 5 # this is 5 min
36 changes: 36 additions & 0 deletions roles/create-openshift-resources/tasks/create_project.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
---
- name: Fail for Missing Project Name
fail: msg="This role requires project.name to be set and non empty"
when: project.name is not defined or project.name == ''

- name: "Set Basic Project Facts"
set_fact:
project_options: ''

- name: "Create Imagestream Fact For Build Environment"
set_fact:
imagestream_names: []
build_project_name: "{{ project.name }}"
when: project.build_environment is defined and project.build_environment == true

- name: "Add display-name Option"
set_fact:
project_options: "{{ project_options }} --display-name='{{ project.display_name }}'"
when: project.display_name is defined and project.display_name != ''

- name: "Determine If {{ project.name }} Project Exists"
command: >
{{ openshift.common.client_binary }} get project {{ project.name }} -o json
register: project_name_taken
failed_when: false
changed_when: false

- name: "Create Project {{ project.name }}"
when: project_name_taken.rc == 1
command: >
{{ openshift.common.client_binary }} new-project {{ project.name }} {{ project_options }}

- include: create_app.yml app={{ app_item }}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd argue that we should leave this to the caller - i.e.: the playbook to do. Could be that we'd want to just create a project and not have the app side populated right away

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I follow. Let's chat

with_items: '{{ project.apps }}'
loop_control:
loop_var: app_item
35 changes: 35 additions & 0 deletions roles/create-openshift-resources/tasks/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
#### Defensive Programming
# https://github.com/openshift/openshift-ansible/blob/master/docs/best_practices_guide.adoc

- name: Fail for Missing User Name
fail: msg="This role requires openshift_user to be set and non empty"
when: openshift_user is not defined or openshift_user == ''

- name: Fail for Missing Password
fail: msg="This role requires openshift_password to be set and non empty"
when: openshift_password is not defined or openshift_password == ''

- name: Fail for Missing OpenShift Host Env
fail: msg="This role requires openshift_host_env to be set and non empty"
when: openshift_host_env is not defined or openshift_host_env == ""

- name: Fail for Missing OpenShift Resources
fail: msg="This role requires openshift_resources_to_create to be set and non empty"
when: openshift_resources_to_create is not defined or openshift_resources_to_create == ""

- name: Fail for Missing OpenShift Projects
fail: msg="This role requires openshift_resources_to_create.projects to be set and non empty"
when: openshift_resources_to_create.projects is not defined or openshift_resources_to_create.projects == ""


- name: "Log in to OpenShift Client"
command: >
{{ openshift.common.client_binary }} login {{ openshift_host_env }}
--insecure-skip-tls-verify=true --username={{ openshift_user }} --password={{ openshift_password }}
changed_when: False

- include: create_project.yml project={{ project_item }}
with_items: '{{ openshift_resources_to_create.projects }}'
loop_control:
loop_var: project_item
39 changes: 39 additions & 0 deletions roles/create-openshift-resources/tasks/promote_image.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
---
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In order for promotion to be successful, the user needs to have the proper permissions in OpenShift. We should create another ansible role / tasks to do this. See the docs for more details:
https://docs.openshift.com/enterprise/3.2/install_config/install/docker_registry.html#access-user-prerequisites

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. This gets into the question of the service user. Now that we have IDM, questions of a identity and RBAC matter, where as previously they did not.

# TODO: we could push the docker login up to main so that it is done few times.
# the problem is that requires every run to have a docker registry defined.
# some users may only want to create "build" environment and not "promotion" environments,
# so this may get in the way if we login into the registry when its not needed
- name: Get User Token
command: >
{{ openshift.common.client_binary }} whoami -t
register: user_token_results

- name: Login To OpenShift Docker Registry
command: >
{{ docker.common.client_binary }} login -u={{ openshift_user }} -e={{ docker.user.email }} -p={{ user_token_results.stdout }} {{ docker.registry.host }}

- name: Set Docker Image Names
set_fact:
build_image_name: "{{ docker.registry.host }}/{{ build_project_name }}/{{ app_name}}"
promotion_image_name: "{{ docker.registry.host }}/{{ project_name }}/{{ app_name }}"

- name: Pull Build Environment Image
docker_image:
name: "{{ build_image_name }}"

# Docker push doesn't work right until ansible 2.2, so we need to do the below in commands
# This is docker 1.10 syntax. We don't support docker 1.9 right now
# crappy syntax here between go templates and jenga templates

- name: Retrieve Build Image ID
command: >
{{ docker.common.client_binary }} images --format '{{ '{{' }} .ID {{ '}}' }}' {{ build_image_name }}:latest
register: docker_tag_image_result

- name: Tag Build Image With Promotion Image
command: >
{{ docker.common.client_binary }} tag {{ docker_tag_image_result.stdout }} {{ promotion_image_name }}:latest

- name: Push Image to Promotion Environment
command: >
{{ docker.common.client_binary }} push {{ promotion_image_name }}
Loading