diff --git a/Makefile b/Makefile index ac8575b..f088e67 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -local_team_servers := $(shell vagrant status | grep -E -o 'team[0-9]+') +local_team_servers = $(shell vagrant status | grep -E -o 'team[0-9]+') ci: @bash ./scripts/ci.sh @@ -20,7 +20,7 @@ connect-aws: provision-local: # Don't re-provision DB at the same time, since it throws off team server tests - @vagrant provision db + @vagrant provision hub @vagrant provision $(local_team_servers) provision-aws: diff --git a/Vagrantfile b/Vagrantfile index a7f78d1..515d400 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -22,26 +22,26 @@ Vagrant.configure("2") do |config| config.vbguest.auto_update = false end - # DB server static IP - db_addr = "10.0.1.10" - ip_bytes = db_addr.split(".") + # hub server static IP + hub_addr = "10.0.1.10" + ip_bytes = hub_addr.split(".") - config.vm.define "db" do |db| - db.vm.box = box + config.vm.define "hub" do |hub| + hub.vm.box = box - db.vm.network "private_network", ip: db_addr - db.vm.network "forwarded_port", guest: 5432, host: 5432, protocol: "tcp" # DB - db.vm.network "forwarded_port", guest: 8000, host: 8000, protocol: "tcp" # Dummy web app - db.vm.network "forwarded_port", guest: 8080, host: 8080, protocol: "tcp" # Score dashboard + hub.vm.network "private_network", ip: hub_addr + hub.vm.network "forwarded_port", guest: 5432, host: 5432, protocol: "tcp" # hub + hub.vm.network "forwarded_port", guest: 8000, host: 8000, protocol: "tcp" # Dummy web app + hub.vm.network "forwarded_port", guest: 8080, host: 8080, protocol: "tcp" # Score dashboard - db.vm.synced_folder ".", "/vagrant", disabled: true + hub.vm.synced_folder ".", "/vagrant", disabled: true - db.vm.provision "file", source: "./scripts", destination: "/tmp/scripts" - db.vm.provision "file", source: "./services", destination: "/tmp/services" - db.vm.provision "file", source: "./score-server", destination: "/tmp/score-server" - db.vm.provision "file", source: "./dummy-web-app", destination: "/tmp/dummy-web-app" + hub.vm.provision "file", source: "./scripts", destination: "/tmp/scripts" + hub.vm.provision "file", source: "./services", destination: "/tmp/services" + hub.vm.provision "file", source: "./score-server", destination: "/tmp/score-server" + hub.vm.provision "file", source: "./dummy-web-app", destination: "/tmp/dummy-web-app" - db.vm.provision "shell", + hub.vm.provision "shell", inline: <<-SCRIPT #!/usr/bin/env bash set -euo pipefail @@ -52,7 +52,7 @@ Vagrant.configure("2") do |config| rm -rf /root/{score-server,services,dummy-web-app} sudo cp -r /tmp/{score-server,services,dummy-web-app} /root/ - bash /tmp/scripts/init-db.sh + bash /tmp/scripts/init-hub.sh SCRIPT end @@ -81,7 +81,7 @@ Vagrant.configure("2") do |config| sudo systemctl restart ssh export team_name="Team-#{i}" - export db_addr='#{db_addr}' + export hub_addr='#{hub_addr}' bash /tmp/scripts/init.sh bats -F pretty /.ws/scripts/test.bats SCRIPT diff --git a/instructions/challenge_2.md b/instructions/challenge_2.md index 7379a4d..5cd5253 100644 --- a/instructions/challenge_2.md +++ b/instructions/challenge_2.md @@ -18,6 +18,6 @@ following: - Once there, the app there needs to be named `run-app`, not `app` - To ensure both locations always have the same version (e.g. during hotfixes), - make a reference from the binary location to the target location without - copying the actual file. This way, any update or change will reflect in both + make a reference from the binary location to the target location *without + copying the actual file*. This way, any update or change will reflect in both places at once without needing to manually sync them. diff --git a/instructions/challenge_3.md b/instructions/challenge_3.md index 31a1739..df7d085 100644 --- a/instructions/challenge_3.md +++ b/instructions/challenge_3.md @@ -15,5 +15,5 @@ Create that service, and get it running. You need to make sure it runs *even if the system reboots* -- meaning that if the server is restarted for any reason, the app service needs to start again *without you starting it manually*. -If for any reason you need to check out more detailed logs of the service, you -can also use the separate `journalctl` command to inspect them. +If for any reason you need to check out more detailed logs of the service you're +creating, you can also use the separate `journalctl` command to inspect them. diff --git a/instructions/challenge_4.md b/instructions/challenge_4.md index d732017..6f9634d 100644 --- a/instructions/challenge_4.md +++ b/instructions/challenge_4.md @@ -24,5 +24,5 @@ look at the `/opt/app` directory again, you may have noticed that there is a correctly-installed app binary. Once you do that, be sure to check the `systemd` and/or `journald` logs of the -new `app-deb.service` to make sure it's running successfully! (and, just like -the last one, that it would keep running after a reboot) +new `app-deb.service` to make sure it's running successfully (and, just like +the last one, that it would keep running after a reboot). diff --git a/instructions/challenge_6.md b/instructions/challenge_6.md index 9e09159..25ecd5b 100644 --- a/instructions/challenge_6.md +++ b/instructions/challenge_6.md @@ -8,7 +8,7 @@ dissappeared while on a golfing trip a few weeks past. We were told that the code was about ready to deploy, just hadn't gotten the chance to merge it into the main branch. See if you can figure out how to get it up and running. -The name of the app is 'carrot-cruncher'. The last dev got the repo set up +The name of the app is "carrot-cruncher". The last dev got the repo set up somewhere on disk, but they never said where... hopefully you'll able to find it. When you do, supposedly there was a new working branch pushed to the remote repo, so you'll need to figure out how to authenticate to that repo. diff --git a/score-server/pkg/fetch-server/serve.go b/score-server/internal/hub-server/serve.go similarity index 96% rename from score-server/pkg/fetch-server/serve.go rename to score-server/internal/hub-server/serve.go index 1bbf6b4..067663b 100644 --- a/score-server/pkg/fetch-server/serve.go +++ b/score-server/internal/hub-server/serve.go @@ -1,6 +1,6 @@ -// Package fetchserver implements server-side and template-rendering logic for -// the score fetcher service -package fetchserver +// Package hubserver implements server-side and template-rendering logic for +// the Hub server's score retrieval & display services +package hubserver import ( "bytes" diff --git a/score-server/pkg/fetch-server/serve_test.go b/score-server/internal/hub-server/serve_test.go similarity index 96% rename from score-server/pkg/fetch-server/serve_test.go rename to score-server/internal/hub-server/serve_test.go index ae52c0f..4fc0017 100644 --- a/score-server/pkg/fetch-server/serve_test.go +++ b/score-server/internal/hub-server/serve_test.go @@ -1,4 +1,4 @@ -package fetchserver +package hubserver import ( "reflect" diff --git a/score-server/internal/team-server/serve.go b/score-server/internal/team-server/serve.go new file mode 100644 index 0000000..40a1e7c --- /dev/null +++ b/score-server/internal/team-server/serve.go @@ -0,0 +1,3 @@ +// Package teamserver implements score-serving functionality on each workshop +// team's server, which is retrieved by the Hub server +package teamserver diff --git a/score-server/internal/team-server/serve_test.go b/score-server/internal/team-server/serve_test.go new file mode 100644 index 0000000..a226917 --- /dev/null +++ b/score-server/internal/team-server/serve_test.go @@ -0,0 +1 @@ +package teamserver diff --git a/score-server/main.go b/score-server/main.go index 9419830..8f54fee 100644 --- a/score-server/main.go +++ b/score-server/main.go @@ -5,12 +5,12 @@ import ( "net" "net/http" - fetchserver "github.com/opensourcecorp/workshops/linux/score-server/pkg/fetch-server" + hubserver "github.com/opensourcecorp/workshops/linux/score-server/internal/hub-server" "github.com/sirupsen/logrus" ) func main() { - http.HandleFunc("/", fetchserver.Root) + http.HandleFunc("/", hubserver.Root) addr := net.JoinHostPort("0.0.0.0", "8080") logrus.Infof("Starting server on %s\n", addr) diff --git a/scripts/ci.sh b/scripts/ci.sh index 93b120f..4a7eb9e 100644 --- a/scripts/ci.sh +++ b/scripts/ci.sh @@ -24,6 +24,7 @@ if [[ "$( Installing CI checks for Go...\n' for pkg in \ honnef.co/go/tools/cmd/staticcheck@latest \ + github.com/mgechev/revive@latest \ github.com/kisielk/errcheck@latest \ ; do go install "${pkg}" @@ -39,9 +40,11 @@ while read -r module ; do cd "${mod_dir}" printf '>> Running go vet...\n' go vet ./... - printf '>> Running linter...\n' + printf '>> Running staticcheck linter...\n' staticcheck ./... - printf '>> Running error checker...\n' + printf '>> Running revive linter...\n' + revive --set_exit_status ./... + printf '>> Running error-checker...\n' errcheck ./... ) done < /tmp/go-modules diff --git a/scripts/init-db.sh b/scripts/init-hub.sh similarity index 100% rename from scripts/init-db.sh rename to scripts/init-hub.sh diff --git a/scripts/init.sh b/scripts/init.sh index 0f92f0d..70d3675 100755 --- a/scripts/init.sh +++ b/scripts/init.sh @@ -18,8 +18,8 @@ if [[ -z "${team_name}" ]]; then log-fatal 'Env var "team_name" not set at runtime' fi -if [[ -z "${db_addr}" ]]; then - log-fatal 'Env var "db_addr" not set at runtime' +if [[ -z "${hub_addr}" ]]; then + log-fatal 'Env var "hub_addr" not set at runtime' fi ### @@ -84,13 +84,13 @@ ufw default allow incoming ufw default allow outgoing ufw deny out 8000 log-info 'Adding file for teams to know which IP to use for one of the networking challenges' -printf '%s\n' "${db_addr}" > /home/appuser/.remote-ip.txt +printf '%s\n' "${hub_addr}" > /home/appuser/.remote-ip.txt ### log-info 'Writing out vars to env file(s) for systemd services' rm -f "${wsroot}"/env && touch "${wsroot}"/env { - printf 'db_addr=%s\n' "${db_addr}" + printf 'hub_addr=%s\n' "${hub_addr}" printf 'team_name=%s\n' "$(hostname)" } >> "${wsroot}"/env @@ -103,24 +103,24 @@ systemctl enable linux-workshop-admin.timer systemctl start linux-workshop-admin.timer ### -_db_init() { +_hub_init() { # shellcheck disable=SC1091 source /usr/local/share/ezlog/src/main.sh log-info 'Waiting for DB to be reachable...' - until timeout 2s psql -U postgres -h "${db_addr}" -c 'SELECT NOW();' > /dev/null ; do + until timeout 2s psql -U postgres -h "${hub_addr}" -c 'SELECT NOW();' > /dev/null ; do log-info 'Still waiting for DB to be reachable...' sleep 5 done log-info 'Successfully reached DB, trying to initialize with base values so team appears on dashboard...' # until-loop because DB can be reachable before schema is made - until psql -U postgres -h "${db_addr}" -c "INSERT INTO scoring (timestamp, team_name, last_challenge_completed, score) VALUES (NOW(), '$(hostname)', 0, 0);" > /dev/null ; do + until psql -U postgres -h "${hub_addr}" -c "INSERT INTO scoring (timestamp, team_name, last_challenge_completed, score) VALUES (NOW(), '$(hostname)', 0, 0);" > /dev/null ; do log-info 'Issue with setting base values; trying again...' sleep 1 done log-info 'Successfully initialized with base values' } -export -f _db_init -timeout 180s bash -c _db_init +export -f _hub_init +timeout 180s bash -c _hub_init ### log-info 'Dumping the first instruction(s) to the appuser homedir' diff --git a/scripts/linux-workshop-admin.sh b/scripts/linux-workshop-admin.sh index f3aff85..9f3cb43 100755 --- a/scripts/linux-workshop-admin.sh +++ b/scripts/linux-workshop-admin.sh @@ -35,13 +35,13 @@ _score-for-challenge() { log-info "Providing instruction to user for Challenge ${next_challenge}" cp "${wsroot}/instructions/challenge_${next_challenge}.md" /home/appuser/ # Also broadcast message to user when challenge is complete - wall "Congrats on finishing Challenge ${which_challenge}! Be sure to check your home directory for any new instruction files! (hit any key to dismiss this message)" + wall "Congrats on finishing Challenge ${which_challenge}! Be sure to check your home directory for any new instruction files! (hit Enter to dismiss this message)" else log-info 'Team is done with the workshop!' cp "${wsroot}/instructions/congrats.md" /home/appuser/ # This check suppresses an infinite loop of congratulations, lol if [[ ! -f "${wsroot}"/team_has_been_congratulated ]] ; then - wall "Congratulations -- you have completed ALL CHALLENGES! Be sure to read congrats.md in your home directory! (hit any key to dismiss this message)" + wall "Congratulations -- you have completed ALL CHALLENGES! Be sure to read congrats.md in your home directory! (hit Enter to dismiss this message)" touch "${wsroot}"/team_has_been_congratulated fi fi @@ -67,7 +67,7 @@ _get-last-challenge-completed() { # _accrue-points adds monotonically-increasing point values, the rate of which # will increase over time at aggregate since this is called per-challenge. _accrue-points() { - psql -U postgres -h "${db_addr:-NOT_SET}" -c " + psql -U postgres -h "${hub_addr:-NOT_SET}" -c " INSERT INTO scoring ( timestamp, team_name, @@ -131,7 +131,7 @@ _check-debfile-service-running() { } _check-webapp-reachable() { - if timeout 1s curl -fsSL "${db_addr:-NOT_SET}:8000" > /dev/null ; then + if timeout 1s curl -fsSL "${hub_addr:-NOT_SET}:8000" > /dev/null ; then _score-for-challenge 5 else log-error "web app is not reachable" diff --git a/scripts/provision-ec2-team-parallelizer.sh b/scripts/provision-ec2-team-parallelizer.sh index bcc33a2..61bea22 100644 --- a/scripts/provision-ec2-team-parallelizer.sh +++ b/scripts/provision-ec2-team-parallelizer.sh @@ -18,8 +18,8 @@ source "${HOME}/.local/ezlog/src/main.sh" server_num="${1:-NOT_SET}" -if [[ -z "${db_priv_ip:-NOT_SET}" ]] ; then - log-fatal 'db_priv_ip not provided to team server provisioning script' +if [[ -z "${hub_priv_ip:-NOT_SET}" ]] ; then + log-fatal 'hub_priv_ip not provided to team server provisioning script' fi if [[ -z "${team_server_ips:-NOT_SET}" ]] ; then log-fatal 'team_server_ips not provided to team server provisioning script' @@ -32,7 +32,7 @@ log-info "Adding files to Team server ${server_num} at ${server_ip}..." scp -P 2332 -r -o StrictHostKeyChecking=accept-new ../scripts ../services ../instructions ../dummy-app-src admin@"${server_ip}":/tmp log-info "Running init on Team server ${server_num} at ${server_ip}..." -ssh -p 2332 admin@"${server_ip}" "export team_name=Team-${server_num} && export db_addr=${db_priv_ip} && sudo -E bash /tmp/scripts/init.sh" +ssh -p 2332 admin@"${server_ip}" "export team_name=Team-${server_num} && export hub_addr=${hub_priv_ip} && sudo -E bash /tmp/scripts/init.sh" log-info "Running tests on Team server ${server_num} at ${server_ip}..." ssh -p 2332 admin@"${server_ip}" "sudo -E bats /.ws/scripts/test.bats" diff --git a/scripts/provision-ec2.sh b/scripts/provision-ec2.sh index 814115c..9784652 100755 --- a/scripts/provision-ec2.sh +++ b/scripts/provision-ec2.sh @@ -4,7 +4,7 @@ set -euo pipefail ################################################################################ # Root script to provision AWS EC2 instances for the workshop. # -# The DB server is provisioned first, and then each team server is provisioned +# The Hub server is provisioned first, and then each team server is provisioned # in parallel by the neighbor script. ################################################################################ @@ -31,25 +31,25 @@ log-info 'Getting Terraform outputs...' (cd ../terraform && terraform output -json) > "${outputs_file}" log-info 'Determining IP addresses of DB server...' -db_pub_ip="$(jq -rc '.db_pub_ip.value' ${outputs_file})" -db_priv_ip="$(jq -rc '.db_priv_ip.value' ${outputs_file})" -log-info "DB IPs: Public ${db_pub_ip}, Private ${db_priv_ip}" +hub_pub_ip="$(jq -rc '.hub_pub_ip.value' ${outputs_file})" +hub_priv_ip="$(jq -rc '.hub_priv_ip.value' ${outputs_file})" +log-info "Hub IPs: Public ${hub_pub_ip}, Private ${hub_priv_ip}" log-info 'Determining IP addresses of Team servers...' num_teams="$(jq '[.instance_ips.value[]] | length' ${outputs_file})" team_server_ips="$(jq -c '[.instance_ips.value[]]' ${outputs_file})" log-info "${num_teams} teams, with IPs of: ${team_server_ips}" -# Provision the DB server first, so that if it fails we know we're about to have +# Provision the Hub server first, so that if it fails we know we're about to have # a bad time overall -log-info 'Adding DB server init script...' -scp -P 2332 -o StrictHostKeyChecking=accept-new -r ../{scripts,services,score-server,dummy-web-app} "admin@${db_pub_ip}":/tmp -ssh -p 2332 admin@"${db_pub_ip}" -- 'sudo cp -r /tmp/{score-server,services,dummy-web-app} /root/' -log-info 'Running DB server init script...' -ssh -p 2332 admin@"${db_pub_ip}" 'sudo bash /tmp/scripts/init-db.sh' +log-info 'Adding Hub server init script...' +scp -P 2332 -o StrictHostKeyChecking=accept-new -r ../{scripts,services,score-server,dummy-web-app} "admin@${hub_pub_ip}":/tmp +ssh -p 2332 admin@"${hub_pub_ip}" -- 'sudo cp -r /tmp/{score-server,services,dummy-web-app} /root/' +log-info 'Running Hub server init script...' +ssh -p 2332 admin@"${hub_pub_ip}" 'sudo bash /tmp/scripts/init-hub.sh' # Export needed vars so the subscript can see them -export db_priv_ip +export hub_priv_ip export team_server_ips # Parallelize provisioning of the team servers diff --git a/scripts/test.bats b/scripts/test.bats index 77d7148..6c0c95c 100755 --- a/scripts/test.bats +++ b/scripts/test.bats @@ -20,7 +20,7 @@ fi # This file should have been populated on init # shellcheck disable=SC1091 source "${wsroot}"/env || exit 1 -[[ -n "${db_addr:-}" ]] || exit 1 +[[ -n "${hub_addr:-}" ]] || exit 1 # setup* and teardown* are bats-specifically-named pre-/post-test hook # functions. _file run once, period, and run @@ -89,7 +89,7 @@ teardown_file() { } _reset-score() { - psql -U postgres -h "${db_addr}" -c " + psql -U postgres -h "${hub_addr}" -c " DELETE FROM scoring WHERE team_name = '$(hostname)'; INSERT INTO scoring (timestamp, team_name, last_challenge_completed, score) VALUES (NOW(), '$(hostname)', 0, 0); " @@ -101,7 +101,7 @@ _get-score() { # Need to stop again becaue starting the .service restarts the timer because # of its 'Want' directive systemctl stop linux-workshop-admin.timer - local score="$(psql -U postgres -h "${db_addr}" -tAc 'SELECT SUM(score) FROM scoring;')" + local score="$(psql -U postgres -h "${hub_addr}" -tAc 'SELECT SUM(score) FROM scoring;')" printf '%s' "${score}" } @@ -288,7 +288,7 @@ _solve-challenge-7() { sleep 1 printf 'DEBUG: Score from challenge 5: %s\n' "${score}" counter=0 - until timeout 1s curl -fsSL "${db_addr}:8000" ; do + until timeout 1s curl -fsSL "${hub_addr}:8000" ; do printf 'Web app not reachable, trying again...\n' >&2 counter="$((counter + 1))" if [[ "${counter}" -ge 30 ]] ; then diff --git a/terraform/main.tf b/terraform/main.tf index 97d969b..cbcba0b 100644 --- a/terraform/main.tf +++ b/terraform/main.tf @@ -5,7 +5,7 @@ provider "aws" { } locals { - db_ip = "10.0.1.10" + hub_ip = "10.0.1.10" region = var.aws_region name = "${var.event_name}-osc-workshop-linux" my_cidr = "${chomp(data.http.my_ip.response_body)}/32" @@ -89,11 +89,11 @@ module "security_group" { tags = local.tags } -module "db" { +module "hub" { source = "terraform-aws-modules/ec2-instance/aws" version = "~> 4.0" - name = "${local.name}-db" + name = "${local.name}-hub" ami = data.aws_ami.latest.id instance_type = "t3a.micro" diff --git a/terraform/outputs.tf b/terraform/outputs.tf index 3928af0..c0af411 100644 --- a/terraform/outputs.tf +++ b/terraform/outputs.tf @@ -2,14 +2,14 @@ output "instance_ips" { value = { for instance in module.team_servers : instance.tags_all["Name"] => instance.public_ip } } -output "db_pub_ip" { - value = module.db.public_ip +output "hub_pub_ip" { + value = module.hub.public_ip } -output "db_pub_endpoint" { - value = "http://${module.db.public_ip}:8080" +output "hub_pub_endpoint" { + value = "http://${module.hub.public_ip}:8080" } -output "db_priv_ip" { - value = module.db.private_ip +output "hub_priv_ip" { + value = module.hub.private_ip }