Name: nodepool-tooling-config-map Namespace: sf Labels: Annotations: Data ==== ansible.cfg: ---- [defaults] stdout_callback=timestamp dib-ansible.py: ---- #!/usr/bin/env python3 # Licensed under the Apache License, Version 2.0 (the "License"); you may # not use this file except in compliance with the License. You may obtain # a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the # License for the specific language governing permissions and limitations # under the License. import argparse import subprocess import os # Wrapper to be called by nodepool-builder to start ansible-playbook # To call it outside of nodepool-builder to debug images # run: dib-ansible -t qcow2 -o /tmp/test ./fedora-30-cloud.yaml def main(): # Fake dib interface inventory_path = "/var/lib/nodepool/config/nodepool/dib-ansible/inventory.yaml" parser = argparse.ArgumentParser() parser.add_argument("-x", action='store_true', help="noop") parser.add_argument("-t", help="Image types") parser.add_argument("--checksum", action='store_true', help="noop") parser.add_argument("--no-tmpfs", action='store_true', help="noop") parser.add_argument("--qemu-img-options", help="noop") parser.add_argument("-o", help="Image output") parser.add_argument("playbook", help="noop") args = parser.parse_args() cmd = ["/usr/bin/ansible-playbook", "-v", "-i", inventory_path] playbook = args.playbook playbook_path = None if not os.path.exists(inventory_path): print("No inventory file provided in nodepool/dib-ansible/") exit(1) if os.path.exists(playbook): playbook_path = playbook else: vp = os.path.join( "/var/lib/nodepool/config/nodepool/dib-ansible", playbook) if os.path.exists(vp): playbook_path = vp if not playbook_path: print("Can't find playbook %s" % playbook) exit(1) cmd.append(playbook_path) # Set the image output var cmd.extend(["-e", "image_output=%s" % args.o]) # Look for image types img_types = set(args.t.split(',')) unsupported_types = img_types.difference(set(('raw', 'qcow2'))) if unsupported_types: raise RuntimeError("Unsupported type: %s" % unsupported_types) if "raw" in img_types: cmd.extend(["-e", "raw_type=True"]) if "qcow2" in img_types: cmd.extend(["-e", "qcow2_type=True"]) # Execute the playbook print("Running: %s" % " ".join(cmd)) return subprocess.Popen(cmd).wait() if __name__ == "__main__": exit(main()) fetch-config-repo.sh: ---- #!/bin/sh set -ex # config-update usage context required a specific git ref REF=$1 if [[ "$CONFIG_REPO_BASE_URL" =~ https://gerrit.sfop.me.* ]]; then # This url is not easily reachable from within pods thus into that # specific context we can use the Service address. CONFIG_REPO_BASE_URL="http://gerrit-httpd:8080" fi # Clone or fetch config repository if [ -d ~/config/.git ]; then pushd ~/config git remote | grep origin && git remote remove origin git remote add origin ${CONFIG_REPO_BASE_URL}/${CONFIG_REPO_NAME} if [ -z "$REF" ]; then # Discover default remote branch ref REF="origin/$(git remote show origin | sed -n '/HEAD branch/s/.*: //p')" fi if [ "$INIT_CONTAINER" == "1" ]; then git fetch origin || true git reset --hard $REF || true else git fetch origin git reset --hard $REF fi popd else pushd ~/ if [ "$INIT_CONTAINER" == "1" ]; then git clone ${CONFIG_REPO_BASE_URL}/${CONFIG_REPO_NAME} config || true else git clone ${CONFIG_REPO_BASE_URL}/${CONFIG_REPO_NAME} config fi popd fi generate-config.sh: ---- #!/bin/sh set -ex # The script expects by default to find the 'nodepool.yaml' file in # the config repository. However the same for nodepool-builder the script # must find the 'nodepool-builder.yaml' in the config repo. Thus, this script # can be parameterized via the NODEPOOL_CONFIG_FILE environment variable. NODEPOOL_CONFIG_FILE="${NODEPOOL_CONFIG_FILE:-nodepool.yaml}" # TODO the nodepool containers need hostname to figure out the actual domain. For now it is safe to assume # the base domain to be svc.local.cluster but other defaults exist. # DOMAIN=$(hostname -d) # Generate the default tenants configuration file # TODO loop on Zookeeper replicas cat << EOF > ~/nodepool.yaml --- webapp: port: 8006 zookeeper-servers: - host: zookeeper-0.zookeeper-headless.sf.svc.cluster.local port: 2281 zookeeper-tls: ca: /tls/client/ca.crt cert: /tls/client/tls.crt key: /tls/client/tls.key # images-dir is mandatory key for nodepool-builder process images-dir: /var/lib/nodepool/dib build-log-dir: /var/lib/nodepool/builds/logs EOF if [ "$CONFIG_REPO_SET" == "TRUE" ]; then # A config repository has been set # config-update usage context required a specific git ref REF=$1 /usr/local/bin/fetch-config-repo.sh $REF # Append the config repo provided config file to the default one if [ -f ~/config/nodepool/${NODEPOOL_CONFIG_FILE} ]; then cat ~/config/nodepool/${NODEPOOL_CONFIG_FILE} >> ~/nodepool.yaml fi fi echo "Generated nodepool config:" echo cat ~/nodepool.yaml cp ~/nodepool.yaml /etc/nodepool/nodepool.yaml init-container.sh: ---- #!/bin/sh set -ex # Update the CA Trust chain update-ca-trust extract -o /etc/pki/ca-trust/extracted # This create some directory expected by nodepool-builder mkdir -p ~/dib ~/nodepool/builds # Generate the Nodepool configuration /usr/local/bin/generate-config.sh ssh_config: ---- Host * IdentityFile /var/lib/nodepool-ssh-key/priv UserKnownHostsFile /var/lib/nodepool/known_hosts ServerAliveInterval 60 timestamp.py: ---- import datetime from ansible import constants as C from ansible import context from ansible import __version__ as ansiblecore_version from ansible.plugins.callback import default, CallbackBase import ansible.utils.display as dsplay """ Timestamped output callback plugin This simple plugin will prefix ansible-playbook's stdout with human-readable timestamps. This also makes fluent bit able to timestamp events properly, so that build logs can be queried/displayed in order. MAKE SURE THAT THIS MODULE MATCHES ANSIBLE-CORE'S VERSION SHIPPED ON THE NODEPOOL-BUILDER CONTAINER! See https://softwarefactory-project.io/r/plugins/gitiles/containers/+/refs/heads/master/images-sf/master/versions.dhall It is based on the [default callback plugin](https://github.com/ansible/ansible/blob/2.16/lib/ansible/plugins/callback/default.py) """ def ts(msg): ts_msg = [] for l in msg.split('\n'): now = datetime.datetime.now() ts_msg.append(u"{now} | {line}".format(now=now, line=l)) return '\n'.join(ts_msg) class TimestampedDisplay(dsplay.Display): @dsplay.proxy_display def display( self, msg, color=None, stderr=False, screen_only=False, log_only=False, newline=True, ): super().display( ts(msg), color, stderr, screen_only, log_only, newline ) def banner(self, msg, color=None, cows=True): # we don't care about cowsay, only use stars. msg = msg.strip() star_len = self.columns - (len(msg) + 3 + len("{now}".format(now=datetime.datetime.now()))) if star_len <= 3: star_len = 3 stars = u"*" * star_len self.display(u"%s %s" % (msg, stars), color=color) class CallbackModule(default.CallbackModule): ''' Simple output callback that appends a timestamp in front of each line of ansible-playbook's output. Other than that, it behaves exactly like the "default" callback plugin. ''' CALLBACK_VERSION = 2.0 ANSIBLE_VERSION = "2.16" CALLBACK_TYPE = 'stdout' CALLBACK_NAME = 'timestamp_output' def __init__(self): if not ansiblecore_version.startswith(self.ANSIBLE_VERSION): raise Exception( "Timestamp callback module is not compatible with the installed " "version of ansible-core ({ac}), expected: {av}".format(ac=ansiblecore_version, av=self.ANSIBLE_VERSION) ) self._play = None self._last_task_banner = None self._last_task_name = None self._task_type_cache = {} super(default.CallbackModule, self).__init__(display=TimestampedDisplay()) # Override plugin options with default's ... default values def get_option(self, k): options = { 'display_skipped_hosts': True, 'display_ok_hosts': True, 'display_failed_stderr': False, 'show_custom_stats': False, 'show_per_host_start': False, 'check_mode_markers': False, 'show_task_path_on_failure': False, } return options[k] BinaryData ==== Events: