You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficcontrol.apache.org by ro...@apache.org on 2022/02/22 19:22:18 UTC
[trafficcontrol] branch master updated: adding health-client integration tests (#6564)
This is an automated email from the ASF dual-hosted git repository.
rob pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficcontrol.git
The following commit(s) were added to refs/heads/master by this push:
new bc0b5fc adding health-client integration tests (#6564)
bc0b5fc is described below
commit bc0b5fcf35550ac42ff6aff4c4d1f07bd07eb25d
Author: John J. Rushford <jr...@apache.org>
AuthorDate: Tue Feb 22 12:22:03 2022 -0700
adding health-client integration tests (#6564)
---
.../health-client-integration-tests/README.md | 77 ++++++++++
.../health-client-integration-tests/action.yml | 22 +++
.../health-client-integration-tests/main.js | 34 +++++
.github/workflows/health-client-tests.yml | 165 +++++++++++++++++++++
cache-config/testing/ort-tests/tc-fixtures.json | 2 +-
tc-health-client/README.md | 14 ++
tc-health-client/config/config.go | 8 +
tc-health-client/testing/docker/db_init/Dockerfile | 42 ++++++
tc-health-client/testing/docker/db_init/dbInit.sh | 30 ++++
tc-health-client/testing/docker/docker-compose.yml | 83 +++++++++++
.../testing/docker/health-check-test/Dockerfile | 69 +++++++++
.../testing/docker/health-check-test/parent.config | 20 +++
.../testing/docker/health-check-test/run.sh | 67 +++++++++
.../docker/health-check-test/strategies.yaml | 61 ++++++++
.../testing/docker/health-check-test/systemctl.sh | 88 +++++++++++
.../docker/health-check-test/tc-health-client.json | 13 ++
.../testing/docker/traffic_ops/Dockerfile | 84 +++++++++++
.../docker/traffic_ops/profile.origin.traffic_ops | 18 +++
tc-health-client/testing/docker/traffic_ops/run.sh | 108 ++++++++++++++
tc-health-client/testing/docker/variables.env | 50 +++++++
.../testing/tests/conf/docker-edge-cache.conf | 38 +++++
tc-health-client/testing/tests/hcutil/hcutil.go | 42 ++++++
.../testing/tests/health-client-main_test.go | 118 +++++++++++++++
.../testing/tests/health-client-startup_test.go | 128 ++++++++++++++++
tc-health-client/tmagent/tmagent.go | 31 ++++
25 files changed, 1411 insertions(+), 1 deletion(-)
diff --git a/.github/actions/health-client-integration-tests/README.md b/.github/actions/health-client-integration-tests/README.md
new file mode 100644
index 0000000..5a0cd44
--- /dev/null
+++ b/.github/actions/health-client-integration-tests/README.md
@@ -0,0 +1,77 @@
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you 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.
+-->
+
+# health-client-integration-tests JavaScript action
+This action runs the Traffic Control Health client integration tests.
+
+## Inputs
+
+### `Trafficserver RPM`
+**Required** A trafficserver RPM used to install on the Edge server.
+
+### `Trafficcontrol Health cliet RPM`
+**Required** A trafficserver RPM used to install on the Edge server.
+
+## Outputs
+
+### `exit-code`
+1 if the Go program(s) could be built successfully.
+
+## Example usage
+```yaml
+jobs:
+ tests:
+ runs-on: ubuntu-latest
+
+ services:
+ postgres:
+ image: postgres:11.9
+ env:
+ POSTGRES_USER: traffic_ops
+ POSTGRES_PASSWORD: twelve
+ POSTGRES_DB: traffic_ops
+ ports:
+ - 5432:5432
+ options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
+
+ smtp:
+ image: maildev/maildev:2.0.0-beta3
+ ports:
+ - 25:25
+ options: >-
+ --entrypoint=bin/maildev
+ --user=root
+ --health-cmd="sh -c \"[[ \$(wget -qO- http://smtp/healthz) == true ]]\""
+ --
+ maildev/maildev:2.0.0-beta3
+ --smtp=25
+ --hide-extensions=STARTTLS
+ --web=80
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@master
+ - name: initialize database
+ uses: ./.github/actions/todb-init
+ - name: Run API v5 tests
+ uses: ./.github/actions/health-client-integration-tests
+ with:
+ version: 5
+ smtp_address: localhost
+```
diff --git a/.github/actions/health-client-integration-tests/action.yml b/.github/actions/health-client-integration-tests/action.yml
new file mode 100644
index 0000000..34e5845
--- /dev/null
+++ b/.github/actions/health-client-integration-tests/action.yml
@@ -0,0 +1,22 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+name: 'health-client-integration-tests'
+description: 'Runs health client integration tests'
+runs:
+ using: 'node12'
+ main: 'main.js'
diff --git a/.github/actions/health-client-integration-tests/main.js b/.github/actions/health-client-integration-tests/main.js
new file mode 100644
index 0000000..561cf84
--- /dev/null
+++ b/.github/actions/health-client-integration-tests/main.js
@@ -0,0 +1,34 @@
+/*
+* 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.
+*/
+
+"use strict";
+const child_process = require("child_process");
+const spawnOptions = {
+ stdio: "inherit",
+ stderr: "inherit",
+};
+
+const dockerCompose = ["docker-compose", "-f", `${process.env.GITHUB_WORKSPACE}/tc-health-client/testing/docker/docker-compose.yml`];
+
+function runProcess(...commandArguments) {
+ console.info(...commandArguments);
+ const status = child_process.spawnSync(commandArguments[0], commandArguments.slice(1), spawnOptions).status;
+ if (status === 0) {
+ return;
+ }
+ console.error("Child process \"", ...commandArguments, "\" exited with status code", status, "!");
+ process.exit(status ? status : 1);
+}
+
+runProcess(...dockerCompose, "run", "health-check-test");
diff --git a/.github/workflows/health-client-tests.yml b/.github/workflows/health-client-tests.yml
new file mode 100644
index 0000000..850583e
--- /dev/null
+++ b/.github/workflows/health-client-tests.yml
@@ -0,0 +1,165 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+name: Traffic Control Health Client integration tests
+
+env:
+ RHEL_VERSION: 8
+ ATS_VERSION: 8.1.x
+
+on:
+ workflow_dispatch:
+ push:
+ paths:
+ - .github/workflows/health-client-tests.yml
+ - go.mod
+ - go.sum
+ - GO_VERSION
+ - lib/go-atscfg/**.go
+ - traffic_ops/*client/**.go
+ - traffic_ops/toclientlib/**.go
+ - lib/atscfg-go/**.go
+ - traffic_ops/traffic_ops_golang/**.go
+ - tc-health-client/**.go
+ - tc-health-client/testing/**
+ - vendor/**.go
+ - vendor/modules.txt
+ - .github/actions/build-ats-test-rpm/**
+ - .github/actions/fetch-github-branch-sha/**
+ - .github/actions/health-client-integration-tests/**
+ create:
+ pull_request:
+ paths:
+ - .github/workflows/health-client-tests.yml
+ - go.mod
+ - go.sum
+ - GO_VERSION
+ - lib/go-atscfg/**.go
+ - traffic_ops/*client/**.go
+ - traffic_ops/toclientlib/**.go
+ - lib/atscfg-go/**.go
+ - traffic_ops/traffic_ops_golang/**.go
+ - tc-health-client/**.go
+ - tc-health-client/testing/**
+ - vendor/**.go
+ - vendor/modules.txt
+ - .github/actions/build-ats-test-rpm/**
+ - .github/actions/fetch-github-branch-sha/**
+ - .github/actions/health-client-integration-tests/**
+ types: [opened, reopened, ready_for_review, synchronize]
+
+jobs:
+
+ traffic_ops:
+ if: github.event.pull_request.draft == false
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+ with:
+ fetch-depth: 5
+ - name: Build RPM
+ uses: ./.github/actions/build-rpms
+ env:
+ ATC_COMPONENT: ${{ github.job }}
+ - name: Upload RPM
+ uses: actions/upload-artifact@v2
+ with:
+ name: ${{ github.job }}
+ path: ${{ github.workspace }}/dist/${{ github.job }}-*.x86_64.rpm
+
+ tc-health-client:
+ if: github.event.pull_request.draft == false
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+ with:
+ fetch-depth: 5
+ - name: Build RPM
+ uses: ./.github/actions/build-rpms
+ env:
+ NO_SOURCE: 1
+ ATC_COMPONENT: ${{ github.job }}
+ - name: Upload RPM
+ uses: actions/upload-artifact@v2
+ with:
+ name: ${{ github.job }}
+ path: ${{ github.workspace }}/dist/trafficcontrol-health-client-*.x86_64.rpm
+
+ trafficserver:
+ if: github.event.pull_request.draft == false
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+ - name: Get latest commit sha and latest tag
+ uses: ./.github/actions/fetch-github-branch-sha
+ with:
+ owner: apache
+ repo: trafficserver
+ branch: ${{ env.ATS_VERSION }}
+ id: git-repo-sha
+ - name: Check Cache
+ id: ats-rpm-cache
+ uses: actions/cache@v2
+ with:
+ path: ${{ github.workspace }}/dist
+ key: ${{ steps.git-repo-sha.outputs.sha }}-${{ steps.git-repo-sha.outputs.latest-tag }}-el${{ env.RHEL_VERSION }}-${{ hashFiles('tc-health-client/testing/docker/trafficserver/**') }}
+ - name: Build ATS RPM
+ if: steps.ats-rpm-cache.outputs.cache-hit != 'true'
+ uses: ./.github/actions/build-ats-test-rpm
+ env:
+ ATC_COMPONENT: ${{ github.job }}
+ - name: Upload RPM
+ uses: actions/upload-artifact@v2
+ with:
+ name: ${{ github.job }}
+ path: ${{ github.workspace }}/dist/${{ github.job }}-*.x86_64.rpm
+
+ health-client_tests:
+ if: github.event.pull_request.draft == false
+ runs-on: ubuntu-latest
+ needs:
+ - traffic_ops
+ - tc-health-client
+ - trafficserver
+
+ steps:
+ - name: Checkout
+ uses: actions/checkout@master
+ - name: Download TO RPM
+ uses: actions/download-artifact@v2
+ with:
+ name: traffic_ops
+ path: ${{ github.workspace }}/tc-health-client/testing/docker/traffic_ops
+ - name: Download Health Client RPM
+ uses: actions/download-artifact@v2
+ with:
+ name: tc-health-client
+ path: ${{ github.workspace }}/tc-health-client/testing/docker/health-check-test
+ - name: Download ATS RPM
+ uses: actions/download-artifact@v2
+ with:
+ name: trafficserver
+ path: ${{ github.workspace }}/tc-health-client/testing/docker/health-check-test
+ - name: display directory
+ run: ls -l ${{ github.workspace }}/tc-health-client/testing/docker/health-check-test
+ - name: Build health client test containers
+ run: docker-compose -f ${{ github.workspace }}/tc-health-client/testing/docker/docker-compose.yml build --parallel
+ - name: Run health client integration tests
+ uses: ./.github/actions/health-client-integration-tests
diff --git a/cache-config/testing/ort-tests/tc-fixtures.json b/cache-config/testing/ort-tests/tc-fixtures.json
index 70313d4..4f7098a 100644
--- a/cache-config/testing/ort-tests/tc-fixtures.json
+++ b/cache-config/testing/ort-tests/tc-fixtures.json
@@ -3135,7 +3135,7 @@
"revalPending": false,
"routerHostName": "",
"routerPortName": "",
- "status": "REPORTED",
+ "status": "ONLINE",
"tcpPort": 81,
"type": "RASCAL",
"updPending": false,
diff --git a/tc-health-client/README.md b/tc-health-client/README.md
index 4e6e272..8853462 100644
--- a/tc-health-client/README.md
+++ b/tc-health-client/README.md
@@ -108,6 +108,8 @@ Sample configuarion file:
"unavailable-poll-threshold": 2,
"trafficserver-config-dir": "/opt/trafficserver/etc/trafficserver",
"trafficserver-bin-dir": "/opt/trafficserver/bin",
+ "poll-state-json-log": "/var/log/trafficcontrol/poll-state.json",
+ "enable-poll-state-log": false
}
```
@@ -179,6 +181,18 @@ Sample configuarion file:
The location on the host where **Traffic Server** **traffic_ctl** tool may
be found.
+### poll-state-json-log ###
+
+ The full path to the polling state file which contains information
+ about the current status of parents and the health client configuration.
+ Polling state data is written to this file after each polling cycle when
+ enabled, see **enable-poll-state-log**
+
+### enable-poll-state-log ###
+
+ Enable writing the Polling state to the **poll-state-json-log** after
+ eache polling cycle. Default **false**, disabled
+
# Files
* /etc/trafficcontrol/tc-health-client.json
diff --git a/tc-health-client/config/config.go b/tc-health-client/config/config.go
index be74cbf..ca6db3a 100644
--- a/tc-health-client/config/config.go
+++ b/tc-health-client/config/config.go
@@ -43,6 +43,7 @@ var tmPollingInterval time.Duration
var toRequestTimeout time.Duration
const (
+ DefaultPollStateJSONLog = "/var/log/trafficcontrol/poll-state.json"
DefaultConfigFile = "/etc/trafficcontrol/tc-health-client.json"
DefaultLogDirectory = "/var/log/trafficcontrol"
DefaultLogFile = "tc-health-client.log"
@@ -67,6 +68,8 @@ type Cfg struct {
UnavailablePollThreshold int `json:"unavailable-poll-threshold"`
TrafficServerConfigDir string `json:"trafficserver-config-dir"`
TrafficServerBinDir string `json:"trafficserver-bin-dir"`
+ PollStateJSONLog string `json:"poll-state-json-log"`
+ EnablePollStateLog bool `json:"enable-poll-state-log"`
TrafficMonitors map[string]bool `json:"trafficmonitors,omitempty"`
HealthClientConfigFile util.ConfigFile
CredentialFile util.ConfigFile
@@ -329,6 +332,9 @@ func LoadConfig(cfg *Cfg) (bool, error) {
if cfg.UnavailablePollThreshold == 0 {
cfg.UnavailablePollThreshold = DefaultUnavailablePollThreshold
}
+ if cfg.PollStateJSONLog == "" {
+ cfg.PollStateJSONLog = DefaultPollStateJSONLog
+ }
cfg.HealthClientConfigFile.LastModifyTime = modTime
@@ -372,6 +378,8 @@ func UpdateConfig(cfg *Cfg, newCfg *Cfg) {
cfg.TrafficServerBinDir = newCfg.TrafficServerBinDir
cfg.TrafficMonitors = newCfg.TrafficMonitors
cfg.HealthClientConfigFile = newCfg.HealthClientConfigFile
+ cfg.PollStateJSONLog = newCfg.PollStateJSONLog
+ cfg.EnablePollStateLog = newCfg.EnablePollStateLog
}
func Usage() {
diff --git a/tc-health-client/testing/docker/db_init/Dockerfile b/tc-health-client/testing/docker/db_init/Dockerfile
new file mode 100644
index 0000000..e101c4f
--- /dev/null
+++ b/tc-health-client/testing/docker/db_init/Dockerfile
@@ -0,0 +1,42 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+############################################################
+# Dockerfile to initialized Traffic Ops Database container
+# Based on CentOS 7.2
+############################################################
+
+FROM centos/systemd
+
+RUN yum install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm
+
+RUN yum -y install \
+ postgresql13 \
+ nmap-ncat \
+ cpanminus && \
+ yum clean all
+
+ENV POSTGRES_HOME $POSTGRES_HOME
+ENV PGPASSWORD $PGPASSWORD
+ENV DB_USERNAME $DB_USERNAME
+ENV DB_NAME $DB_NAME
+ENV DB_USER_PASS $DB_USER_PASS
+ENV DB_SERVER $DB_SERVER
+ENV DB_PORT $DB_PORT
+
+ADD db_init/dbInit.sh /
+CMD /dbInit.sh
diff --git a/tc-health-client/testing/docker/db_init/dbInit.sh b/tc-health-client/testing/docker/db_init/dbInit.sh
new file mode 100755
index 0000000..f4392d4
--- /dev/null
+++ b/tc-health-client/testing/docker/db_init/dbInit.sh
@@ -0,0 +1,30 @@
+#!/usr/bin/env bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+############################################################
+# Script for creating the database user account for traffic
+# ops.
+# Used while the Docker Image is initializing itself
+############################################################
+
+while ! nc $DB_SERVER $DB_PORT </dev/null; do # &>/dev/null; do
+ echo "waiting for $DB_SERVER:$DB_PORT"
+ sleep 3
+done
+psql -h $DB_SERVER -U postgres -c "CREATE USER $DB_USER WITH ENCRYPTED PASSWORD '$DB_USER_PASS'"
+createdb $DB_NAME -h $DB_SERVER -U postgres --owner $DB_USER
diff --git a/tc-health-client/testing/docker/docker-compose.yml b/tc-health-client/testing/docker/docker-compose.yml
new file mode 100644
index 0000000..b096c97
--- /dev/null
+++ b/tc-health-client/testing/docker/docker-compose.yml
@@ -0,0 +1,83 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+#
+# Build trafficcontrol:
+# Copy the traffic_ops rpm to traffic_ops/traffic_ops.rpm
+# Copy the trafficcontrol-cache-config rpm to ort_test/trafficcontrol-cache-config.rpm
+# Copy an ATS rpm to yumserver/test-rpms (the ort_tests
+# container updates ../ort-tests/tc-fixtures.json with
+# the corresponding version string)
+#
+# Run: docker-compose build
+# Run: docker-compose run ort_test
+#
+
+---
+version: '3.8'
+
+volumes:
+ trafficcontrol:
+ traffic_ops:
+ conf:
+
+services:
+ db:
+ image: postgres:13.2
+ env_file:
+ - variables.env
+ ports:
+ - "5432:5432"
+
+ db_init:
+ env_file:
+ - variables.env
+ build:
+ context: .
+ dockerfile: db_init/Dockerfile
+ depends_on:
+ - db
+
+ health-check-test:
+ env_file:
+ - variables.env
+ build:
+ context: .
+ dockerfile: health-check-test/Dockerfile
+ args:
+ - OS_DISTRO=${OS_DISTRO:-rockylinux}
+ - OS_VERSION=${OS_VERSION:-8}
+ depends_on:
+ - to_server
+ volumes:
+ - ../../..:/root/go/src/github.com/apache/trafficcontrol
+
+ to_server:
+ env_file:
+ - variables.env
+ ports:
+ - "443:443"
+ build:
+ context: .
+ dockerfile: traffic_ops/Dockerfile
+ args:
+ - OS_DISTRO=${OS_DISTRO:-rockylinux}
+ - OS_VERSION=${OS_VERSION:-8}
+ volumes:
+ - ../../../GO_VERSION:/GO_VERSION
+ depends_on:
+ - db_init
+
diff --git a/tc-health-client/testing/docker/health-check-test/Dockerfile b/tc-health-client/testing/docker/health-check-test/Dockerfile
new file mode 100644
index 0000000..a601987
--- /dev/null
+++ b/tc-health-client/testing/docker/health-check-test/Dockerfile
@@ -0,0 +1,69 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+# For cache, you may either use (RAM or disk) block devices or disk directories
+# To use RAM block devices, pass them as /dev/ram0 and /dev/ram1 via `docker run --device`
+# To use disk directories, simply don't pass devices, and the container will configure Traffic Server for directories
+
+# Block devices may be created on the native machine with, for example, `modprobe brd`.
+# The recommended minimum size for each block devices is 1G.
+# For example, `sudo modprobe brd rd_size=1048576 rd_nr=2`
+
+ARG OS_DISTRO=rockylinux
+ARG OS_VERSION=8
+FROM ${OS_DISTRO}:${OS_VERSION}
+ARG OS_DISTRO
+ARG OS_VERSION
+# Makes OS_VERSION available in later layers without needing to specify it again
+ENV OS_VERSION=$OS_VERSION
+ENV OS_DISTRO=$OS_DISTRO
+MAINTAINER dev@trafficcontrol.apache.org
+EXPOSE 80 443
+
+# these packages load for both centos 7 and rockylinux 8
+# no checks required at this time.
+RUN yum install -y epel-release && yum repolist && \
+ yum install -y brotli initscripts jansson jansson-devel \
+ git gcc hwloc jq lua luajit man-db tcl && \
+ yum clean all
+
+RUN echo "Using Image ${OS_DISTRO}:${OS_VERSION}"
+
+ADD health-check-test/systemctl.sh /
+RUN cp /usr/bin/systemctl /usr/bin/systemctl.save
+RUN cp /systemctl.sh /usr/bin/systemctl && chmod 0755 /usr/bin/systemctl
+
+# Note that if more than one t3c RPM matches this wildcard, this Dockerfile will
+# break because this will create a directory instead of an RPM file, which it
+# will then fail to install.
+ADD health-check-test/trafficserver-[0-9]*.rpm /trafficserver.rpm
+ADD health-check-test/trafficcontrol-health-client*x86_64.rpm /trafficcontrol-health-client.rpm
+RUN rpm -i /trafficserver.rpm /trafficcontrol-health-client.rpm
+ADD health-check-test/tc-health-client.json /etc/trafficcontrol/
+
+RUN sed -i 's/HOME\/bin/HOME\/bin:\/usr\/local\/go\/bin:/g' /root/.bash_profile &&\
+ echo "GOPATH=/root/go; export GOPATH" >> /root/.bash_profile &&\
+ echo "StrictHostKeyChecking no" >> /etc/ssh/ssh_config &&\
+ mkdir /root/go
+
+ADD variables.env /
+ADD health-check-test/run.sh /
+ADD health-check-test/parent.config /
+ADD health-check-test/strategies.yaml /
+RUN chmod +x /run.sh
+
+ENTRYPOINT /run.sh
diff --git a/tc-health-client/testing/docker/health-check-test/parent.config b/tc-health-client/testing/docker/health-check-test/parent.config
new file mode 100644
index 0000000..c5dfa5f
--- /dev/null
+++ b/tc-health-client/testing/docker/health-check-test/parent.config
@@ -0,0 +1,20 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+#
+dest_domain=foo.com parent="atlanta-mid-16.ga.atlanta.kabletown.net:80|0.5;atlanta-mid-01.ga.atlanta.kabletown.net:80|0.5" rount_robin=consistent_hash
+dest_domain=bar.com parent="dtrc-mid-01.kabletown.net:80|0.5;dtrc-mid-02.kabletown.net:80|0.5" rount_robin=consistent_hash
diff --git a/tc-health-client/testing/docker/health-check-test/run.sh b/tc-health-client/testing/docker/health-check-test/run.sh
new file mode 100644
index 0000000..481d577
--- /dev/null
+++ b/tc-health-client/testing/docker/health-check-test/run.sh
@@ -0,0 +1,67 @@
+#!/bin/bash
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+#
+
+GOPATH=/root/go; export GOPATH
+PATH=$PATH:/usr/local/go/bin:; export PATH
+TERM=xterm; export TERM
+
+# set up some convienient links
+/bin/ln -s /root/go/src/github.com/apache/trafficcontrol /trafficcontrol
+
+# install go
+if [[ -f /trafficcontrol/GO_VERSION ]]; then
+ go_version=$(cat /trafficcontrol/GO_VERSION) && \
+ curl -Lo go.tar.gz https://dl.google.com/go/go${go_version}.linux-amd64.tar.gz && \
+ tar -C /usr/local -xvzf go.tar.gz && \
+ ln -s /usr/local/go/bin/go /usr/bin/go && \
+ rm go.tar.gz
+else
+ echo "no GO_VERSION file, unable to install go"
+ exit 1
+fi
+
+# write the to-creds file
+. /variables.env
+echo "#!/bin/bash" > /etc/to-creds
+echo "TO_USER=${TO_ADMIN_USER}" >> /etc/to-creds
+echo "TO_PASS=${TO_ADMIN_PASS}" >> /etc/to-creds
+echo "TO_URL=${TO_URI}" >> /etc/to-creds
+chmod +x /etc/to-creds
+
+/usr/bin/ln -s /trafficcontrol/tc-health-client/testing/tests /tests
+mkdir /tests/conf
+/usr/bin/cp /trafficcontrol/cache-config/testing/ort-tests/conf/docker-edge-cache.conf /tests/conf
+/usr/bin/cp /trafficcontrol/cache-config/testing/ort-tests/tc-fixtures.json /tests
+
+cd "$(realpath /tests)"
+touch test.log && chmod a+rw test.log && nohup tail -f test.log&
+go mod vendor -v
+
+# setup trafficserver config files
+/usr/bin/cp /strategies.yaml /opt/trafficserver/etc/trafficserver/strategies.yaml
+/usr/bin/cp /parent.config /opt/trafficserver/etc/trafficserver/parent.config
+# start trafficserver
+systemctl start trafficserver
+
+go test --cfg=conf/docker-edge-cache.conf 2>&1 >> test.log
+
+rm /tests/tc-fixtures.json
+
+exit 0
diff --git a/tc-health-client/testing/docker/health-check-test/strategies.yaml b/tc-health-client/testing/docker/health-check-test/strategies.yaml
new file mode 100644
index 0000000..6d2a934
--- /dev/null
+++ b/tc-health-client/testing/docker/health-check-test/strategies.yaml
@@ -0,0 +1,61 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+#
+hosts:
+ - &mid3
+ host: dtrc-mid-03.kabletown.net
+ protocol:
+ - scheme: http
+ port: 80
+ health_check_url: http://192.168.2.1:80
+ - scheme: https
+ port: 443
+ health_check_url: https://192.168.2.1:443
+ - &mid16
+ host: atlanta-mid-16.ga.atlanta.kabletown.net
+ protocol:
+ - scheme: http
+ port: 80
+ health_check_url: http://192.168.2.2:80
+ - scheme: https
+ port: 443
+ health_check_url: https://192.168.2.2:443
+groups:
+ - &mid-tier
+ - <<: *mid3
+ weight: 0.5
+ - <<: *mid16
+ weight: 0.5
+strategies:
+ - strategy: "peering-g1"
+ policy: consistent_hash
+ cache_peer_result: false
+ go_direct: true
+ parent_is_proxy: true
+ groups:
+ - *mid-tier
+ scheme: http
+ failover:
+ max_simple_retries: 2
+ ring_mode:
+ peering_ring
+ response_codes:
+ - 404
+ health_check:
+ - passive
+ - active
diff --git a/tc-health-client/testing/docker/health-check-test/systemctl.sh b/tc-health-client/testing/docker/health-check-test/systemctl.sh
new file mode 100755
index 0000000..d02c93d
--- /dev/null
+++ b/tc-health-client/testing/docker/health-check-test/systemctl.sh
@@ -0,0 +1,88 @@
+#!/bin/bash
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+#
+
+# This is a work around for testing t3c which uses systemctl.
+# systemctl does not work in a container very well so this script
+# replaces systemctl in the container and always returns a
+# sucessful result to t3c.
+
+USAGE="\nsystemctl COMMAND UNIT\n"
+
+if [ -z $1 ]; then
+ echo -e $USAGE
+ exit 0
+else
+ COMMAND=$1
+ UNIT=$2
+fi
+
+if [ "$COMMAND" != "daemon-reload" ]; then
+ if [ "$UNIT" != "trafficserver" ] && [ "$UNIT" != "tc-health-client" ]; then
+ echo -e "\nFailed to start ${UNIT}: Unit not found"
+ exit 0
+ fi
+fi
+
+case $COMMAND in
+ daemon-reload)
+ ;;
+ enable)
+ ;;
+ restart)
+ case $UNIT in
+ trafficserver)
+ /opt/trafficserver/bin/trafficserver restart
+ ;;
+ tc-health-client)
+ kill `cat /var/run/tc-health-client.pid`
+ tc-health-client -vvv &
+ ;;
+ esac
+ ;;
+ status)
+ if [ "${UNIT}" = "trafficserver" ]; then
+ /opt/trafficserver/bin/trafficserver status
+ fi
+ ;;
+ start)
+ case $UNIT in
+ trafficserver)
+ /opt/trafficserver/bin/trafficserver start
+ ;;
+ tc-health-client)
+ nohup tc-health-client -vvv&
+ ;;
+ esac
+ ;;
+ stop)
+ if [ "${UNIT}" = "trafficserver" ]; then
+ /opt/trafficserver/bin/trafficserver stop
+ fi
+ case $UNIT in
+ trafficserver)
+ /opt/trafficserver/bin/trafficserver start
+ ;;
+ tc-health-client)
+ kill `cat /var/run/tc-health-client.pid`
+ ;;
+ esac
+ ;;
+esac
+
+exit $?
diff --git a/tc-health-client/testing/docker/health-check-test/tc-health-client.json b/tc-health-client/testing/docker/health-check-test/tc-health-client.json
new file mode 100644
index 0000000..b6335e9
--- /dev/null
+++ b/tc-health-client/testing/docker/health-check-test/tc-health-client.json
@@ -0,0 +1,13 @@
+{
+ "cdn-name": "cdn1",
+ "enable-active-markdowns": true,
+ "reason-code": "active",
+ "to-credential-file": "/etc/to-creds",
+ "to-request-timeout-seconds": "5s",
+ "tm-poll-interval-seconds": "10s",
+ "tm-update-cycles": 20,
+ "unavailable-poll-threshold": 2,
+ "enable-poll-state-log": true,
+ "trafficserver-config-dir": "/opt/trafficserver/etc/trafficserver",
+ "trafficserver-bin-dir": "/opt/trafficserver/bin"
+}
diff --git a/tc-health-client/testing/docker/traffic_ops/Dockerfile b/tc-health-client/testing/docker/traffic_ops/Dockerfile
new file mode 100644
index 0000000..1e999e8
--- /dev/null
+++ b/tc-health-client/testing/docker/traffic_ops/Dockerfile
@@ -0,0 +1,84 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+############################################################
+# Dockerfile to build Traffic Ops container images
+# Based on CentOS 8
+############################################################
+
+ARG OS_DISTRO=rockylinux
+ARG OS_VERSION=8
+FROM ${OS_DISTRO}:${OS_VERSION}
+ARG OS_DISTRO
+ARG OS_VERSION
+ENV OS_DISTRO=${OS_DISTRO}
+ENV OS_VERSION=${OS_VERSION}
+
+RUN if [[ "${OS_VERSION%%.*}" -eq 7 ]]; then \
+ yum -y install dnf || exit 1; \
+ fi
+
+RUN set -o nounset -o errexit && \
+ mkdir -p /etc/cron.d; \
+ if [[ "${OS_VERSION%%.*}" -eq 7 ]]; then \
+ use_repo=''; \
+ enable_repo=''; \
+ # needed for llvm-toolset-7-clang, which is needed for postgresql13-devel-13.2-1PGDG, required by TO rpm
+ dnf -y install gcc centos-release-scl-rh; \
+ else \
+ use_repo='--repo=pgdg13'; \
+ enable_repo='--enablerepo=powertools'; \
+ fi; \
+ dnf -y install "https://download.postgresql.org/pub/repos/yum/reporpms/EL-${OS_VERSION%%.*}-x86_64/pgdg-redhat-repo-latest.noarch.rpm"; \
+ # libicu required by postgresql13
+ dnf -y install libicu; \
+ dnf -y $use_repo -- install postgresql13; \
+ dnf -y install epel-release; \
+ dnf -y $enable_repo install \
+ bind-utils \
+ gettext \
+ # ip commands is used in set-to-ips-from-dns.sh
+ iproute \
+ isomd5sum \
+ jq \
+ libidn-devel \
+ libpcap-devel \
+ mkisofs \
+ net-tools \
+ nmap-ncat \
+ openssl \
+ perl-Crypt-ScryptKDF \
+ perl-Digest-SHA1 \
+ perl-JSON-PP \
+ python3 \
+ # rsync is used to copy certs in "Shared SSL certificate generation" step
+ rsync; \
+ dnf clean all
+
+EXPOSE 443
+
+WORKDIR /opt/traffic_ops/app
+
+RUN yum -y install procps
+ADD traffic_ops/traffic_ops*x86_64.rpm /traffic_ops.rpm
+RUN yum -y install /traffic_ops.rpm && \
+ rm /traffic_ops.rpm
+
+ADD traffic_ops/run.sh /
+
+EXPOSE 443
+CMD /run.sh
diff --git a/tc-health-client/testing/docker/traffic_ops/profile.origin.traffic_ops b/tc-health-client/testing/docker/traffic_ops/profile.origin.traffic_ops
new file mode 100644
index 0000000..f655f89
--- /dev/null
+++ b/tc-health-client/testing/docker/traffic_ops/profile.origin.traffic_ops
@@ -0,0 +1,18 @@
+{
+ "parameters": [
+ {
+ "config_file": "CRConfig.json",
+ "name": "domain_name",
+ "value": "{{.Domain}}"
+ },
+ {
+ "config_file": "parent.config",
+ "name": "weight",
+ "value": "1.0"
+ }
+ ],
+ "profile": {
+ "description": "Multi site origin profile 1",
+ "name": "ORG1_CDN1"
+ }
+}
diff --git a/tc-health-client/testing/docker/traffic_ops/run.sh b/tc-health-client/testing/docker/traffic_ops/run.sh
new file mode 100755
index 0000000..874aefc
--- /dev/null
+++ b/tc-health-client/testing/docker/traffic_ops/run.sh
@@ -0,0 +1,108 @@
+#!/usr/bin/env bash
+set -x
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+# Script for running the Dockerfile for Traffic Ops.
+# The Dockerfile sets up a Docker image which can be used for any new Traffic Ops container;
+# This script, which should be run when the container is run (it's the ENTRYPOINT), will configure the container.
+#
+# The following environment variables must be set, ordinarily by `docker run -e` arguments:
+# DB_SERVER
+# DB_PORT
+# DB_ROOT_PASS
+# DB_USER
+# DB_USER_PASS
+# DB_NAME
+# TO_ADMIN_USER
+# TO_ADMIN_PASS
+# CERT_COUNTRY
+# CERT_STATE
+# CERT_CITY
+# CERT_COMPANY
+# TO_DOMAIN
+# TRAFFIC_VAULT_PASS
+
+# Check that env vars are set
+envvars=( DB_SERVER DB_PORT DB_ROOT_PASS DB_USER DB_USER_PASS TO_ADMIN_USER TO_ADMIN_PASS CERT_COUNTRY CERT_STATE CERT_CITY CERT_COMPANY TO_DOMAIN)
+for v in $envvars
+do
+ if [[ -z $$v ]]; then echo "$v is unset"; exit 1; fi
+done
+
+start() {
+ traffic_ops_golang_command=(./bin/traffic_ops_golang -cfg "$CDNCONF" -dbcfg "$DATABASECONF");
+ "${traffic_ops_golang_command[@]}" &
+ exec tail -f $TO_LOG
+}
+
+# generates and saves SSL certificates and database config files.
+init() {
+ # install certificates for TO
+ openssl req -newkey rsa:2048 -nodes -keyout /etc/pki/tls/private/localhost.key -x509 -days 365 \
+ -out /etc/pki/tls/certs/localhost.crt -subj "/C=$CERT_COUNTRY/ST=$CERT_STATE/L=$CERT_CITY/O=$CERT_COMPANY"
+ cp /etc/pki/tls/certs/localhost.crt /etc/pki/tls/certs/ca-bundle.crt
+
+ # update the base_url in cdn.conf
+ sed -i -e "s#http://localhost\:3000#http://${TO_HOSTNAME}\:443#" $CDNCONF
+ sed -i -e 's#https://\[::\]#https://127\.0\.0\.1#' $CDNCONF
+ sed -i -e 's#"use_ims": false,#"use_ims": true,#' $CDNCONF
+ #
+ cat > $DATABASECONF << EOM
+{
+ "type" : "Pg",
+ "description" : "Pg database on localhost:5432",
+ "port" : "$DB_PORT",
+ "dbname" : "$DB_NAME",
+ "password" : "$DB_USER_PASS",
+ "hostname" : "$DB_SERVER",
+ "user" : "$DB_USER"
+}
+EOM
+
+ cat > $DBCONF << EOM
+version: "1.0"
+name: dbconf.yml
+
+development:
+ driver: postgres
+ open: host=$DB_SERVER port=5432 user=traffic_ops password=$DB_USER_PASS dbname=to_development sslmode=disable
+
+test:
+ driver: postgres
+ open: host=$DB_SERVER port=5432 user=traffic_ops password=$DB_USER_PASS dbname=to_test sslmode=disable
+
+integration:
+ driver: postgres
+ open: host=$DB_SERVER port=5432 user=traffic_ops password=$DB_USER_PASS dbname=to_integration sslmode=disable
+
+production:
+ driver: postgres
+ open: host=$DB_SERVER port=5432 user=traffic_ops password=$DB_USER_PASS dbname=traffic_ops sslmode=disable
+EOM
+
+ touch $LOG_DEBUG $LOG_ERROR $LOG_EVENT $LOG_INFO $LOG_WARN $TO_LOG
+}
+
+source /etc/environment
+if [ -z "$INITIALIZED" ]; then init; fi
+
+# create the 'traffic_ops' database, tables and runs migrations
+(cd /opt/traffic_ops/app && db/admin --env=production reset > /admin.log 2>&1)
+
+# start traffic_ops
+start
diff --git a/tc-health-client/testing/docker/variables.env b/tc-health-client/testing/docker/variables.env
new file mode 100644
index 0000000..08ff604
--- /dev/null
+++ b/tc-health-client/testing/docker/variables.env
@@ -0,0 +1,50 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+#
+CDNCONF=/opt/traffic_ops/app/conf/cdn.conf
+CERT_COUNTRY=US
+CERT_STATE=Colorado
+CERT_CITY=Denver
+CERT_COMPANY=NotComcast
+DBCONF=/opt/traffic_ops/app/db/dbconf.yml
+DATABASECONF=/opt/traffic_ops/app/conf/production/database.conf
+POSTGRES_HOME=/usr/pgsql-13
+PGPASSWORD=secretrootpass
+POSTGRES_PASSWORD=secretrootpass
+DB_NAME=traffic_ops
+DB_PORT=5432
+DB_ROOT_PASS=null
+DB_USER=traffic_ops
+DB_USER_PASS=twelve
+DB_SERVER=db
+LOG_DEBUG=/var/log/traffic_ops/debug.log
+LOG_ERROR=/var/log/traffic_ops/error.log
+LOG_EVENT=/var/log/traffic_ops/event.log
+LOG_INFO=/var/log/traffic_ops/info.log
+LOG_WARN=/var/log/traffic_ops/warn
+TV_ADMIN_USER=admin
+TV_ADMIN_PASSWORD=tvsecret
+TV_FQDN=localhost
+TO_ADMIN_USER=admin
+TO_ADMIN_PASS=twelve
+TO_HOSTNAME=to_server
+TO_LOG=/var/log/traffic_ops/traffic_ops.log
+TO_DOMAIN=trafficops_default
+TO_URI=https://to_server:443
+X509_CA_PERSIST_DIR=/ca
+X509_CA_PERSIST_ENV_FILE=/ca/environment
+TV_HTTPS_PORT=8088
diff --git a/tc-health-client/testing/tests/conf/docker-edge-cache.conf b/tc-health-client/testing/tests/conf/docker-edge-cache.conf
new file mode 100644
index 0000000..d06370c
--- /dev/null
+++ b/tc-health-client/testing/tests/conf/docker-edge-cache.conf
@@ -0,0 +1,38 @@
+{
+ "default": {
+ "logLocations": {
+ "debug": "stdout",
+ "error": "stdout",
+ "event": "stdout",
+ "info": "stdout",
+ "warning": "stdout"
+ },
+ "session": {
+ "timeoutInSecs": 60
+ },
+ "includeSystemTests": false
+ },
+ "use_ims": true,
+ "trafficOps": {
+ "URL": "https://to_server:443",
+ "password": "twelve",
+ "users": {
+ "disallowed": "disallowed",
+ "operations": "operations",
+ "admin": "admin",
+ "federation": "federation",
+ "portal": "portal",
+ "readOnly": "readOnly",
+ "extension": "extension"
+ }
+ },
+ "trafficOpsDB": {
+ "dbname": "traffic_ops",
+ "description": "Test database to_test",
+ "hostname": "db",
+ "password": "twelve",
+ "port": "5432",
+ "type": "Pg",
+ "user": "traffic_ops"
+ }
+}
diff --git a/tc-health-client/testing/tests/hcutil/hcutil.go b/tc-health-client/testing/tests/hcutil/hcutil.go
new file mode 100644
index 0000000..e2ce6d8
--- /dev/null
+++ b/tc-health-client/testing/tests/hcutil/hcutil.go
@@ -0,0 +1,42 @@
+/*
+ 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.
+*/
+
+package hcutil
+
+import (
+ "bytes"
+ "os/exec"
+)
+
+func Do(cmdStr string, args ...string) ([]byte, []byte, int) {
+ cmd := exec.Command(cmdStr, args...)
+
+ var outbuf bytes.Buffer
+ var errbuf bytes.Buffer
+
+ cmd.Stdout = &outbuf
+ cmd.Stderr = &errbuf
+
+ code := 0
+ err := cmd.Run()
+ if err != nil {
+ if exitErr, ok := err.(*exec.ExitError); !ok {
+ return nil, []byte(err.Error()), -1
+ } else {
+ code = exitErr.ExitCode()
+ }
+ }
+
+ return outbuf.Bytes(), errbuf.Bytes(), code
+}
diff --git a/tc-health-client/testing/tests/health-client-main_test.go b/tc-health-client/testing/tests/health-client-main_test.go
new file mode 100644
index 0000000..9685959
--- /dev/null
+++ b/tc-health-client/testing/tests/health-client-main_test.go
@@ -0,0 +1,118 @@
+package hctest
+
+/*
+ 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 (
+ "database/sql"
+ "flag"
+ "fmt"
+ "os"
+ "testing"
+ "time"
+
+ "github.com/apache/trafficcontrol/cache-config/testing/ort-tests/config"
+ "github.com/apache/trafficcontrol/cache-config/testing/ort-tests/tcdata"
+ "github.com/apache/trafficcontrol/lib/go-log"
+)
+
+const cfgFmt = `Using Config values:
+ TO Config File: %s
+ TO Fixtures: %s
+ TO URL: %s
+ TO Session Timeout In Secs: %d
+ DB Server: %s
+ DB User: %s
+ DB Name: %s
+ DB Ssl: %t
+ UseIMS: %t`
+
+var (
+ Config config.Config
+ testData tcdata.TrafficControl
+ includeSystemTests bool
+ tcd *tcdata.TCData
+ TCD *tcdata.TCData
+)
+
+func TestMain(m *testing.M) {
+ tcd = tcdata.NewTCData()
+ configFileName := flag.String("cfg", "traffic-ops-test.conf", "The config file path")
+ tcFixturesFileName := flag.String("fixtures", "tc-fixtures.json", "The test fixtures")
+ cliIncludeSystemTests := *flag.Bool("includeSystemTests", false, "Whether to enable tests that have environment dependencies beyond a database")
+
+ flag.Parse()
+
+ // Skip loading configuration when run with `go test -list=<pat>`. The -list
+ // flag does not actually run tests, so configuration data is not needed in
+ // that mode. If the user is just trying to list the available tests we
+ // don't want to abort with an error about a bad configuration the user
+ // doesn't care about yet.
+ if f := flag.Lookup("test.list"); f != nil {
+ if f.Value.String() != "" {
+ os.Exit(m.Run())
+ }
+ }
+
+ var err error
+
+ if *tcd.Config, err = config.LoadConfig(*configFileName); err != nil {
+ fmt.Fprintf(os.Stderr, "Error Loading Config: %v\n", err)
+ os.Exit(1)
+ }
+ fmt.Fprintf(os.Stdout, "Config: %v\n", tcd.Config)
+
+ // CLI option overrides config
+ includeSystemTests = tcd.Config.Default.IncludeSystemTests || cliIncludeSystemTests
+
+ if err = log.InitCfg(tcd.Config); err != nil {
+ fmt.Fprintf(os.Stderr, "Error initializing loggers: %v\n", err)
+ os.Exit(1)
+ }
+
+ log.Infof(cfgFmt, *configFileName, *tcFixturesFileName, tcd.Config.TrafficOps.URL, tcd.Config.Default.Session.TimeoutInSecs, tcd.Config.TrafficOpsDB.Hostname, tcd.Config.TrafficOpsDB.User, tcd.Config.TrafficOpsDB.Name, tcd.Config.TrafficOpsDB.SSL, tcd.Config.UseIMS)
+
+ //Load the test data
+ tcd.LoadFixtures(*tcFixturesFileName)
+
+ var db *sql.DB
+ db, err = tcd.OpenConnection()
+ if err != nil {
+ log.Errorf("\nError opening connection to %s - %s, %v\n", tcd.Config.TrafficOps.URL, tcd.Config.TrafficOpsDB.User, err)
+ os.Exit(1)
+ }
+ defer db.Close()
+
+ err = tcd.Teardown(db)
+ if err != nil {
+ log.Errorf("\nError tearingdown data %s - %s, %v\n", tcd.Config.TrafficOps.URL, tcd.Config.TrafficOpsDB.User, err)
+ }
+
+ err = tcd.SetupTestData(db)
+ if err != nil {
+ log.Errorf("setting up data on TO instance %s as DB user '%s' failed: %v\n", tcd.Config.TrafficOps.URL, tcd.Config.TrafficOpsDB.User, err)
+ os.Exit(1)
+ }
+
+ toReqTimeout := time.Second * time.Duration(tcd.Config.Default.Session.TimeoutInSecs)
+ err = tcd.SetupSession(toReqTimeout, tcd.Config.TrafficOps.URL, tcd.Config.TrafficOps.Users.Admin, tcd.Config.TrafficOps.UserPassword)
+ if err != nil {
+ log.Errorf("\nError creating session to %s - %s, %v\n", tcd.Config.TrafficOps.URL, tcd.Config.TrafficOpsDB.User, err)
+ os.Exit(1)
+ }
+
+ // Now run the test case
+ rc := m.Run()
+ os.Exit(rc)
+}
diff --git a/tc-health-client/testing/tests/health-client-startup_test.go b/tc-health-client/testing/tests/health-client-startup_test.go
new file mode 100644
index 0000000..60c198b
--- /dev/null
+++ b/tc-health-client/testing/tests/health-client-startup_test.go
@@ -0,0 +1,128 @@
+/*
+ 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.
+*/
+
+package hctest
+
+import (
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "testing"
+ "time"
+
+ "github.com/apache/trafficcontrol/cache-config/testing/ort-tests/tcdata"
+ "github.com/apache/trafficcontrol/tc-health-client/testing/tests/hcutil"
+ "github.com/apache/trafficcontrol/tc-health-client/tmagent"
+)
+
+func startHealthClient() {
+ outbuf, errbuf, result := hcutil.Do("systemctl", "start", "tc-health-client", "-vvv")
+ if result != 0 {
+ fmt.Fprintf(os.Stdout, "Error starting the health-client: %s\n", string(errbuf))
+ } else {
+ fmt.Fprintf(os.Stdout, "the health-client was succesfully started: %s\n", string(outbuf))
+ }
+}
+
+func TestHealthClientStartup(t *testing.T) {
+ tcd.WithObjs(t, []tcdata.TCObj{
+ tcdata.CDNs, tcdata.Types, tcdata.Tenants, tcdata.Parameters,
+ tcdata.Profiles, tcdata.ProfileParameters, tcdata.Statuses,
+ tcdata.Divisions, tcdata.Regions, tcdata.PhysLocations,
+ tcdata.CacheGroups, tcdata.Servers, tcdata.Topologies,
+ }, func() {
+
+ // initialize variables
+ cfg := tmagent.ParentInfo{}
+ pollStateFile := "/var/log/trafficcontrol/poll-state.json"
+ atlantaMid := "atlanta-mid-16.ga.atlanta.kabletown.net"
+ dtrcMid := "dtrc-mid-02.kabletown.net"
+ rascal := "rascal01.kabletown.net"
+
+ waitTime, err := time.ParseDuration("5s")
+ if err != nil {
+ fmt.Fprintf(os.Stdout, "failed to parse a value for waitTime")
+ os.Exit(1)
+ }
+
+ // mark down some parents using ATS traffic_ctl
+ _, errbuf, result := hcutil.Do("/opt/trafficserver/bin/traffic_ctl", "host", "down", "--reason", "active", atlantaMid)
+ if result != 0 {
+ fmt.Fprintf(os.Stdout, "%s\n", string(errbuf))
+ t.Fatalf("unable to mark down parent '%s'\n", atlantaMid)
+ } else {
+ fmt.Fprintf(os.Stdout, "marked down '%s'\n", atlantaMid)
+ }
+ _, errbuf, result = hcutil.Do("/opt/trafficserver/bin/traffic_ctl", "host", "down", "--reason", "active", dtrcMid)
+ if result != 0 {
+ fmt.Fprintf(os.Stdout, "%s\n", string(errbuf))
+ t.Fatalf("unable to mark down parent '%s'\n", dtrcMid)
+ } else {
+ fmt.Fprintf(os.Stdout, "marked down '%s'\n", dtrcMid)
+ }
+
+ // startup the health-client
+ fmt.Fprintf(os.Stdout, "Starting the tc-health-client\n")
+ go startHealthClient()
+
+ // wait for the health client to write it's poll state
+ time.Sleep(waitTime)
+
+ fmt.Fprintf(os.Stdout, "Running tests\n")
+
+ // read the health-client poll-state file.
+ cfg = tmagent.ParentInfo{}
+ content, err := ioutil.ReadFile(pollStateFile)
+ if err != nil {
+ t.Fatalf("could not read the %s file: %s\n", pollStateFile, err.Error())
+ }
+ err = json.Unmarshal(content, &cfg)
+ if err != nil {
+ t.Fatalf("could not unmarshal %s: %s\n", pollStateFile, err.Error())
+ }
+
+ // we marked down mids, now test that the health client read the ATS
+ // Host Status and see's that they are down.
+ parents := cfg.Parents
+ p := parents[atlantaMid]
+ if p.ActiveReason != false {
+ t.Fatalf("Expected %s to be marked down but it's not", atlantaMid)
+ } else {
+ fmt.Fprintf(os.Stdout, "%s is available: %v\n", atlantaMid, p.ActiveReason)
+ }
+ p = parents[dtrcMid]
+ if p.ActiveReason != false {
+ t.Fatalf("Expected %s to be marked down but it's not", dtrcMid)
+ } else {
+ fmt.Fprintf(os.Stdout, "%s is available: %v\n", dtrcMid, p.ActiveReason)
+ }
+
+ // verify that the health-client was able to poll and get an available
+ // traffic monitor from TrafficOps
+ av := cfg.Cfg.TrafficMonitors[rascal]
+ if av != true {
+ t.Fatalf("Expected %s to be available but it's not", rascal)
+ } else {
+ fmt.Fprintf(os.Stdout, "%s is available: %v\n", rascal, av)
+ }
+
+ fmt.Fprintf(os.Stdout, "Stopping the tc-health-client\n")
+ _, errbuf, result = hcutil.Do("/usr/bin/systemctl", "stop", "tc-health-client", "-vvv")
+ if result != 0 {
+ fmt.Fprintf(os.Stdout, "%s\n", string(errbuf))
+ t.Fatalf("unable to stop the tc-health-client\n")
+ }
+ })
+}
diff --git a/tc-health-client/tmagent/tmagent.go b/tc-health-client/tmagent/tmagent.go
index e9211a7..0568587 100644
--- a/tc-health-client/tmagent/tmagent.go
+++ b/tc-health-client/tmagent/tmagent.go
@@ -22,6 +22,7 @@ package tmagent
import (
"bufio"
"bytes"
+ "encoding/json"
"errors"
"fmt"
"io/ioutil"
@@ -325,6 +326,15 @@ func (c *ParentInfo) PollAndUpdateCacheStatus() {
} else {
log.Infoln("updated TrafficMonitor statuses from TrafficOps")
}
+
+ // log the poll state data if enabled
+ if c.Cfg.EnablePollStateLog {
+ err = c.WritePollState()
+ if err != nil {
+ log.Errorf("could not write the poll state log: %s\n", err.Error())
+ }
+ }
+
time.Sleep(pollingInterval)
continue
}
@@ -375,6 +385,14 @@ func (c *ParentInfo) PollAndUpdateCacheStatus() {
cycleCount++
}
+ // log the poll state data if enabled
+ if c.Cfg.EnablePollStateLog {
+ err = c.WritePollState()
+ if err != nil {
+ log.Errorf("could not write the poll state log: %s\n", err.Error())
+ }
+ }
+
time.Sleep(pollingInterval)
}
}
@@ -418,6 +436,19 @@ func (c *ParentInfo) UpdateParentInfo() error {
return nil
}
+func (c *ParentInfo) WritePollState() error {
+ data, err := json.MarshalIndent(c, "", "\t")
+ if err != nil {
+ return fmt.Errorf("marshaling configuration state: %s\n", err.Error())
+ } else {
+ err = os.WriteFile(c.Cfg.PollStateJSONLog, data, 0644)
+ if err != nil {
+ return fmt.Errorf("writing configuration state: %s\n", err.Error())
+ }
+ }
+ return nil
+}
+
// choose an available trafficmonitor, returns an error if
// there are none.
func (c *ParentInfo) findATrafficMonitor() (string, error) {