| # Licensed to the Apache Software Foundation (ASF) under one or more contributor |
| # license agreements; and to You under the Apache License, Version 2.0. |
| --- |
| # This role installs invokers. |
| |
| - import_tasks: docker_login.yml |
| |
| - name: "pull invoker image with tag {{docker.image.tag}}" |
| shell: "docker pull {{docker_registry}}{{ docker.image.prefix }}/invoker:{{docker.image.tag}}" |
| when: docker_registry != "" |
| register: result |
| until: (result.rc == 0) |
| retries: "{{ docker.pull.retries }}" |
| delay: "{{ docker.pull.delay }}" |
| |
| ### |
| # This task assumes that the images are local to the invoker host already if there is no prefix or tag |
| # which is usually the case for a local deployment. A distributed deployment will specify the prefix, or tag |
| # to pull the images from the appropriate registry. If a runtimes_registry is optionally specified, pull images |
| # from there; this permits a (private) registry to be used for caching the images. The registry if specified |
| # must include a trailing '/'. |
| # |
| - name: "pull runtime action images per manifest" |
| shell: "docker pull {{runtimes_registry | default()}}{{item.prefix}}/{{item.name}}:{{item.tag | default()}}" |
| loop: "{{ runtimesManifest.runtimes.values() | sum(start=[]) | selectattr('deprecated', 'equalto',false) | map(attribute='image') | list | unique }}" |
| when: skip_pull_runtimes is not defined or skip_pull_runtimes != True |
| register: result |
| until: (result.rc == 0) |
| retries: "{{ docker.pull.retries }}" |
| delay: "{{ docker.pull.delay }}" |
| |
| ### |
| # See comment above for pulling other runtime images. |
| # |
| - name: "pull blackboxes action images per manifest" |
| shell: "docker pull {{runtimes_registry | default()}}{{item.prefix}}/{{item.name}}:{{item.tag | default()}}" |
| loop: "{{ runtimesManifest.blackboxes }}" |
| when: skip_pull_runtimes is not defined or skip_pull_runtimes != True |
| register: result |
| until: (result.rc == 0) |
| retries: "{{ docker.pull.retries }}" |
| delay: "{{ docker.pull.delay }}" |
| |
| - name: "determine docker root dir on docker-machine" |
| uri: url="http://{{ ansible_host }}:{{ docker.port }}/info" return_content=yes |
| register: dockerInfo_output |
| when: environmentInformation.type == 'docker-machine' |
| |
| - set_fact: |
| dockerInfo: "{{ dockerInfo_output['json'] }}" |
| when: environmentInformation.type == "docker-machine" |
| |
| - name: "determine docker root dir" |
| shell: echo -e "GET http:/v1.24/info HTTP/1.0\r\n" | nc -U /var/run/docker.sock | grep "{" |
| args: |
| executable: /bin/bash |
| register: dockerInfo_output |
| when: environmentInformation.type != "docker-machine" |
| |
| - set_fact: |
| dockerInfo: "{{ dockerInfo_output.stdout|from_json }}" |
| when: environmentInformation.type != "docker-machine" |
| |
| - name: ensure invoker log directory is created with permissions |
| file: |
| path: "{{ whisk_logs_dir }}/invoker{{ groups['invokers'].index(inventory_hostname) }}" |
| state: directory |
| mode: 0777 |
| become: "{{ logs.dir.become }}" |
| |
| - name: ensure invoker config directory is created with permissions |
| file: |
| path: "{{ invoker.confdir }}/invoker{{ groups['invokers'].index(inventory_hostname) }}" |
| state: directory |
| mode: 0777 |
| become: "{{ invoker.dir.become }}" |
| |
| - name: "copy kafka truststore/keystore" |
| when: kafka.protocol == 'SSL' |
| copy: |
| src: "{{ openwhisk_home }}/ansible/roles/kafka/files/{{ kafka.ssl.keystore.name }}" |
| dest: "{{ invoker.confdir }}/invoker{{ groups['invokers'].index(inventory_hostname) }}" |
| |
| - name: check, that required databases exist |
| include_tasks: "{{ openwhisk_home }}/ansible/tasks/db/checkDb.yml" |
| vars: |
| dbName: "{{ item }}" |
| with_items: |
| - "{{ db.whisk.actions }}" |
| - "{{ db.whisk.activations }}" |
| |
| - name: get running invoker information |
| uri: url="http://{{ ansible_host }}:{{ docker.port }}/containers/json?filters={{ '{"name":[ "invoker" ],"ancestor":[ "invoker" ]}' | urlencode }}" return_content=yes |
| register: invokerInfo_output |
| when: environmentInformation.type == "docker-machine" |
| |
| - set_fact: |
| invokerInfo: "{{ invokerInfo_output['json'] }}" |
| when: environmentInformation.type == "docker-machine" |
| |
| - name: "get invoker info" |
| shell: | |
| INFO=`echo -e "GET http:/v1.24/containers/json?filters={{ '{"name":[ "invoker" ],"ancestor":[ "invoker" ]}' | urlencode }} HTTP/1.0\r\n" | nc -U /var/run/docker.sock | grep "{"` |
| if [ -z "$INFO" ]; then |
| echo [] |
| else |
| echo $INFO |
| fi |
| args: |
| executable: /bin/bash |
| register: invokerInfo_output |
| when: environmentInformation.type != "docker-machine" |
| |
| - set_fact: |
| invokerInfo: "{{ invokerInfo_output.stdout|from_json }}" |
| when: environmentInformation.type != "docker-machine" |
| |
| - name: determine if more than one invoker is running |
| fail: |
| msg: "more than one invoker is running" |
| when: not invoker.allowMultipleInstances and invokerInfo|length > 1 |
| |
| - name: determine if index of invoker is same with index of inventory host |
| fail: |
| msg: "invoker index is invalid. expected: /invoker{{ groups['invokers'].index(inventory_hostname) }} found: {{ item.Names[0] }}" |
| with_items: "{{ invokerInfo }}" |
| when: not invoker.allowMultipleInstances and item.Names[0] != "/invoker{{ groups['invokers'].index(inventory_hostname) }}" |
| |
| - name: copy jmxremote password file |
| when: jmx.enabled |
| template: |
| src: "jmxremote.password.j2" |
| dest: "{{ invoker.confdir }}/invoker{{ groups['invokers'].index(inventory_hostname) }}/jmxremote.password" |
| mode: 0777 |
| |
| - name: copy jmxremote access file |
| when: jmx.enabled |
| template: |
| src: "jmxremote.access.j2" |
| dest: "{{ invoker.confdir }}/invoker{{ groups['invokers'].index(inventory_hostname) }}/jmxremote.access" |
| mode: 0777 |
| |
| - name: add additional jvm params if jmxremote is enabled |
| when: jmx.enabled |
| set_fact: |
| invoker_args: "{{ invoker.arguments }} {{ invoker.jmxremote.jvmArgs }}" |
| |
| - name: prepare invoker ports |
| set_fact: |
| ports_to_expose: ["{{ invoker.port + groups['invokers'].index(inventory_hostname) }}:8080"] |
| |
| - name: expose additional ports if jmxremote is enabled |
| when: jmx.enabled |
| set_fact: |
| ports_to_expose: "{{ ports_to_expose }} + [ \"{{ jmx.basePortInvoker + groups['invokers'].index(inventory_hostname) }}:{{ jmx.basePortInvoker + groups['invokers'].index(inventory_hostname) }}\" ] + [ \"{{ jmx.rmiBasePortInvoker + groups['invokers'].index(inventory_hostname) }}:{{ jmx.rmiBasePortInvoker + groups['invokers'].index(inventory_hostname) }}\" ]" |
| |
| - name: prepare invoker env |
| set_fact: |
| invoker_env: |
| "JAVA_OPTS": "-Xmx{{ invoker.heap }} -XX:+CrashOnOutOfMemoryError -XX:+UseGCOverheadLimit -XX:ErrorFile=/logs/java_error.log" |
| "INVOKER_OPTS": "{{ invoker_args | default(invoker.arguments) }}" |
| "JMX_REMOTE": "{{ jmx.enabled }}" |
| "COMPONENT_NAME": "invoker{{ groups['invokers'].index(inventory_hostname) }}" |
| "PORT": 8080 |
| "KAFKA_HOSTS": "{{ kafka_connect_string }}" |
| "CONFIG_whisk_kafka_replicationFactor": "{{ kafka.replicationFactor | default() }}" |
| "CONFIG_whisk_kafka_topics_invoker_retentionBytes": "{{ kafka_topics_invoker_retentionBytes | default() }}" |
| "CONFIG_whisk_kafka_topics_invoker_retentionMs": "{{ kafka_topics_invoker_retentionMS | default() }}" |
| "CONFIG_whisk_kakfa_topics_invoker_segmentBytes": "{{ kafka_topics_invoker_segmentBytes | default() }}" |
| "CONFIG_whisk_kafka_common_securityProtocol": "{{ kafka.protocol }}" |
| "CONFIG_whisk_kafka_common_sslTruststoreLocation": "/conf/{{ kafka.ssl.keystore.name }}" |
| "CONFIG_whisk_kafka_common_sslTruststorePassword": "{{ kafka.ssl.keystore.password }}" |
| "CONFIG_whisk_kafka_common_sslKeystoreLocation": "/conf/{{ kafka.ssl.keystore.name }}" |
| "CONFIG_whisk_kafka_common_sslKeystorePassword": "{{ kafka.ssl.keystore.password }}" |
| "CONFIG_whisk_userEvents_enabled": "{{ user_events }}" |
| "ZOOKEEPER_HOSTS": "{{ zookeeper_connect_string }}" |
| "CONFIG_whisk_couchdb_protocol": "{{ db_protocol }}" |
| "CONFIG_whisk_couchdb_host": "{{ db_host }}" |
| "CONFIG_whisk_couchdb_port": "{{ db_port }}" |
| "CONFIG_whisk_couchdb_username": "{{ db_username }}" |
| "CONFIG_whisk_couchdb_password": "{{ db_password }}" |
| "CONFIG_whisk_couchdb_provider": "{{ db_provider }}" |
| "CONFIG_whisk_couchdb_databases_WhiskAuth": "{{ db.whisk.auth }}" |
| "CONFIG_whisk_couchdb_databases_WhiskEntity": "{{ db.whisk.actions }}" |
| "CONFIG_whisk_couchdb_databases_WhiskActivation": "{{ db.whisk.activations }}" |
| "DB_WHISK_ACTIONS": "{{ db.whisk.actions }}" |
| "DB_WHISK_ACTIVATIONS": "{{ db.whisk.activations }}" |
| "DB_WHISK_AUTHS": "{{ db.whisk.auth }}" |
| "CONFIG_whisk_db_actionsDdoc": "{{ db_whisk_actions_ddoc | default() }}" |
| "CONFIG_whisk_db_activationsDdoc": "{{ db_whisk_activations_ddoc | default() }}" |
| "CONFIG_whisk_db_activationsFilterDdoc": "{{ db_whisk_activations_filter_ddoc | default() }}" |
| "WHISK_API_HOST_PROTO": "{{ whisk_api_host_proto | default('https') }}" |
| "WHISK_API_HOST_PORT": "{{ whisk_api_host_port | default('443') }}" |
| "WHISK_API_HOST_NAME": "{{ whisk_api_host_name | default(groups['edge'] | first) }}" |
| "RUNTIMES_REGISTRY": "{{ runtimes_registry | default('') }}" |
| "RUNTIMES_MANIFEST": "{{ runtimesManifest | to_json }}" |
| "CONFIG_whisk_runtimes_bypassPullForLocalImages": "{{ runtimes_bypass_pull_for_local_images | default() }}" |
| "CONFIG_whisk_runtimes_localImagePrefix": "{{ runtimes_local_image_prefix | default() }}" |
| "CONFIG_whisk_containerFactory_containerArgs_network": "{{ invoker_container_network_name | default('bridge') }}" |
| "INVOKER_CONTAINER_POLICY": "{{ invoker_container_policy_name | default()}}" |
| "CONFIG_whisk_containerPool_numCore": "{{ invoker.numcore }}" |
| "CONFIG_whisk_containerPool_coreShare": "{{ invoker.coreshare }}" |
| "CONFIG_whisk_docker_containerFactory_useRunc": "{{ invoker.useRunc }}" |
| "INVOKER_NAME": "{{ groups['invokers'].index(inventory_hostname) }}" |
| "WHISK_LOGS_DIR": "{{ whisk_logs_dir }}" |
| "METRICS_KAMON": "{{ metrics.kamon.enabled }}" |
| "METRICS_KAMON_TAGS": "{{ metrics.kamon.tags }}" |
| "METRICS_LOG": "{{ metrics.log.enabled }}" |
| "CONFIG_kamon_statsd_hostname": "{{ metrics.kamon.host }}" |
| "CONFIG_kamon_statsd_port": "{{ metrics.kamon.port }}" |
| "CONFIG_whisk_spi_LogStoreProvider": "{{ userLogs.spi }}" |
| "CONFIG_logback_log_level": "{{ invoker.loglevel }}" |
| "CONFIG_whisk_memory_min": "{{ limit_action_memory_min | default() }}" |
| "CONFIG_whisk_memory_max": "{{ limit_action_memory_max | default() }}" |
| "CONFIG_whisk_memory_std": "{{ limit_action_memory_std | default() }}" |
| "CONFIG_whisk_timeLimit_min": "{{ limit_action_time_min | default() }}" |
| "CONFIG_whisk_timeLimit_max": "{{ limit_action_time_max | default() }}" |
| "CONFIG_whisk_timeLimit_std": "{{ limit_action_time_std | default() }}" |
| "CONFIG_whisk_activation_payload_max": "{{ limit_activation_payload | default() }}" |
| "CONFIG_whisk_transactions_header": "{{ transactions.header }}" |
| |
| - name: extend invoker dns env |
| set_fact: |
| invoker_env: "{{ invoker_env | default({}) | combine( {'CONFIG_whisk_containerFactory_containerArgs_dnsServers_' ~ item.0: item.1} ) }}" |
| with_indexed_items: "{{ (invoker_container_network_dns_servers | default()).split(' ')}}" |
| |
| - name: merge extra env variables |
| set_fact: |
| invoker_env: "{{ invoker_env | combine(invoker.extraEnv) }}" |
| |
| - name: set invoker volumes |
| set_fact: |
| volumes: "/sys/fs/cgroup:/sys/fs/cgroup,/run/runc:/run/runc,\ |
| {{ whisk_logs_dir }}/invoker{{ groups['invokers'].index(inventory_hostname) }}:/logs,\ |
| {{ invoker.confdir }}/invoker{{ groups['invokers'].index(inventory_hostname) }}:/conf,\ |
| {{ dockerInfo['DockerRootDir'] }}/containers/:/containers,\ |
| {{ docker_sock | default('/var/run/docker.sock') }}:/var/run/docker.sock" |
| |
| - name: define options when deploying invoker on Ubuntu |
| set_fact: |
| volumes: "{{ volumes|default('') }},/usr/lib/x86_64-linux-gnu/libapparmor.so.1:/usr/lib/x86_64-linux-gnu/libapparmor.so.1" |
| when: ansible_distribution == "Ubuntu" |
| |
| - name: start invoker using docker cli |
| docker_container: |
| userns_mode: "host" |
| pid_mode: "host" |
| privileged: "yes" |
| name: invoker{{ groups['invokers'].index(inventory_hostname) }} |
| hostname: "invoker{{ groups['invokers'].index(inventory_hostname) }}" |
| restart_policy: "{{ docker.restart.policy }}" |
| image: "{{ docker_registry }}{{ docker.image.prefix }}/invoker:{{ docker.image.tag }}" |
| state: started |
| recreate: true |
| env: "{{ invoker_env }}" |
| volumes: "{{ volumes }}" |
| ports: "{{ ports_to_expose }}" |
| command: /bin/sh -c "exec /init.sh {{ groups['invokers'].index(inventory_hostname) }} >> /logs/invoker{{ groups['invokers'].index(inventory_hostname) }}_logs.log 2>&1" |
| |
| - name: wait until Invoker is up and running |
| uri: |
| url: "http://{{ ansible_host }}:{{ invoker.port + groups['invokers'].index(inventory_hostname) }}/ping" |
| register: result |
| until: result.status == 200 |
| retries: 12 |
| delay: 5 |