# Default environment is development
export ENVIRONMENT ?= development
TWITCH_ENV ?= "development"

# Autohost is being built with go 1.16, which defaults to treating packages as go modules.
# Since Autohost is not a go module, we have to configure go to use the previous behavior
# by setting GO111MODULE to auto.
export GO111MODULE ?= auto

GOBIN := $(CURDIR)/_bin
PATH := $(GOBIN):$(PATH)

.PHONY: setup
setup:
	retool build

# dev: Run Autohost Server locally.
.PHONY: dev
dev: export HTTP_PROXY ?= socks5://localhost:1080
dev: export HTTPS_PROXY ?= socks5://localhost:1080
dev: export NO_PROXY ?= localhost,127.0.0.1
dev:
	go run cmd/autohost/main.go

# socks-proxy: Starts a SOCKS proxy to the SPIE Bastion in the Staging AWS account.
# The SOCKS proxy runs in the foreground, so you may want to run this in another shell.
.PHONY: socks-proxy
socks-proxy:
	ssh -D 127.0.0.1:1080 ssm-jumpbox.038504843107 -N

# ssh-staging SSHs into the SPIE Bastion in the Staging AWS account.
.PHONY: ssh-staging
ssh-staging:
	ssh ssm-jumpbox.038504843107

# fmt: Format the go code.
.PHONY: fmt
fmt:
	find . -iname '*.go' \
		-not -path './_tools/*' \
		-not -path './cdk/*'  \
		-not -path '*/mock/*' \
		-not -path '*/mocks/*' \
		-not -path './rpc/*'  \
		-not -path './vendor/*' \
		-print0 | xargs -0 goimports -w

# build-server-linux: Build the Autohost Server binary, targeting linux
.PHONY: build-server-linux
build-server-linux:
	GOOS=linux GOARCH=amd64 go build \
		-o autohost-server \
		cmd/autohost/main.go

# build-server-linux: Build the Autohost Worker binary, targeting linux
.PHONY: build-server-worker
build-worker-linux:
	GOOS=linux GOARCH=amd64 go build \
		-o autohost-worker \
		cmd/worker/main.go

# lint: Detects problems in the go code.
.PHONY: lint
lint:
	golangci-lint run --enable gosec --out-format checkstyle > golangci-report.xml || { cat golangci-report.xml; exit 1; }

# revendor: Ensure that Autohost's dependencies are in the vendor directory.
.PHONY: revendor
revendor:
	retool do dep ensure

# revendor: Ensure that Autohost's dependencies are in the vendor directory.
.PHONY: proto_lint
proto_lint:
	clang-format -style="{BasedOnStyle: Google, IndentWidth: 4}" -verbose -i rpc/*.proto

# twirp: Generate twirp client and server stubs from protobuf schema files.
.PHONY: twirp
twirp:
	retool do protoc \
		--proto_path=./rpc/hosting \
		--lint_out=sort_imports:./rpc/hosting \
		--go_out=${GOPATH}/src \
		--twirp_out=${GOPATH}/src \
		./rpc/hosting/*.proto

# mocks: Generate mock clients from interfaces.
.PHONY: mocks
mocks:
	mockery --name Database --output internal/database/mocks --dir internal/database
	# Worker mocks
	mockery --inpackage --name Client --dir internal/worker/clients/clue
	mockery --name LiveService --output internal/worker/mocks --dir internal/worker
	mockery --name UsersService --output internal/worker/mocks --dir internal/worker
	mockery --name InternalUsersClient --output internal/worker/clients/users/mocks --dir internal/worker/clients/users
	mockery --name Client --output internal/worker/clients/multiplex/mocks --dir internal/worker/clients/multiplex
	# Hosting mocks
	mockery --inpackage --name Auth --dir internal/hosting/auth
	mockery --inpackage --name Client --dir internal/hosting/clients/clue
	mockery --inpackage --name Client --dir internal/hosting/clients/hallpass
	mockery --inpackage --name Client --dir internal/hosting/clients/liveline
	mockery --inpackage --name Client --dir internal/hosting/clients/sns
	mockery --inpackage --name Client --dir internal/hosting/clients/users
	mockery --inpackage --name Logic --dir internal/hosting/logic
	mockery --inpackage --name Client --dir internal/hosting/pdms

# jenkins_setup: Install build dependnecies on Jenkins.
.PHONY: jenkins_setup
jenkins_setup:
	@wget -O - -q https://install.goreleaser.com/github.com/golangci/golangci-lint.sh | sh -s -- -b $(GOBIN) v1.23.8

# test: Run unit tests.
.PHONY: test
test:
	go test -race ./...

# integration: Run integration tests.
.PHONY: integration
integration:
	# Run integration tests
	# We set -count=1 to disable caching test output and rerun all tests.
	# We set -p 1 to force go test to run all tests sequentially.
	# We temporarily are not using the race detector because there is a race condition in foundation/twitchclient
	# (https://git-aws.internal.justin.tv/foundation/twitchclient/pull/57)
	go test -tags=integration -count=1 -p 1 -timeout 5m ./...

# smoke_tests_staging: Run smoke tests against the Staging environment.
.PHONY: smoke_tests_staging
smoke_tests_staging:
	# We set -count=1 to disable caching test output and rerun all tests.
	#
	# Run the tests but ignore failures to allow the environment to warm up. (This should work around the issue
	# where the tests often fail due to connection timeouts.)
	-ENVIRONMENT=staging go test -v -tags=smoke_tests -count=1 code.justin.tv/live/autohost/smoke_tests
	# Run the tests again, and fail if they error.
	ENVIRONMENT=staging go test -v -tags=smoke_tests -count=1 code.justin.tv/live/autohost/smoke_tests

# smoke_tests_staging: Run smoke tests against the Production environment.
.PHONY: smoke_tests_production
smoke_tests_production:
	# We set -count=1 to disable caching test output and rerun all tests.
	ENVIRONMENT=production go test -v -tags=smoke_tests -count=1 code.justin.tv/live/autohost/smoke_tests

# create_local_env: Spin up a development environment with Autohost's dependencies.
.PHONY: create_local_env
create_local_env:
	# Authenticate docker to the ECR repositories in the Staging environment.
	aws ecr get-login-password --region us-west-2 --profile twitch-ce-host-dev-admin | \
		docker login --username AWS --password-stdin 038504843107.dkr.ecr.us-west-2.amazonaws.com
	# Spin up dynamodb, memcached and redis containers which can be used for local development.
	docker-compose -f docker-compose.dev.yml up -d
	# Create the tables in the local dynamodb.
	go run ./cmd/init-local-dynamodb/main.go


# fetch_staging_admin_credentials uses ada to fetch admin credentials for the staging account. It puts them under the
# twitch-ce-host-dev-admin profile.
.PHONY: fetch_staging_admin_credentials
fetch_staging_admin_credentials:
	ada credentials update --account 038504843107 --role admin --once --profile twitch-ce-host-dev-admin

# create_local_env: Delete the development environment.
.PHONY: destroy_local_env
destroy_local_env:
	# Shut down local dynamodb and redis containers.
	docker-compose -f docker-compose.dev.yml down

# ci: Run integration tests on the build server.
.PHONY: ci
ci: integration jenkins_setup lint

#
# Cloudformation
#

TWITCH_CE_HOST_AWS = "447680546588"
TWITCH_CE_HOST_DEV = "038504843107"
EPOCH = $(shell date +"%s")

.PHONY: validate_cloudformation_templates
validate_cloudformation_templates:
	python scripts/validate_aws.py ${TWITCH_CE_HOST_DEV}
	aws cloudformation validate-template --template-body file://cloudformation/autohost_server_eb/autohost_server_eb.yaml
	aws cloudformation validate-template --template-body file://cloudformation/creator_collab_pagerduty/pagerduty.yaml
	aws cloudformation validate-template --template-body file://cloudformation/host_dynamodb/dynamodb.yaml
	aws cloudformation validate-template --template-body file://cloudformation/vpc_endpoints/vpc_endpoints.yaml

.PHONY: create_autohost_server_staging_eb
create_autohost_server_staging_eb: 
	python scripts/validate_aws.py ${TWITCH_CE_HOST_DEV}
	aws cloudformation create-stack \
		--template-body file://cloudformation/autohost_server_eb/autohost_server_eb.yaml \
		--cli-input-json file://cloudformation/autohost_server_eb/create_autohost_server_staging_eb.json

.PHONY: create_autohost_server_production_eb
create_autohost_server_production_eb: 
	python scripts/validate_aws.py ${TWITCH_CE_HOST_AWS}
	aws cloudformation create-stack \
		--template-body file://cloudformation/autohost_server_eb/autohost_server_eb.yaml \
		--cli-input-json file://cloudformation/autohost_server_eb/create_autohost_server_production_eb.json

.PHONY: update_autohost_server_staging_eb
update_autohost_server_staging_eb:
	python scripts/validate_aws.py ${TWITCH_CE_HOST_DEV}
	aws cloudformation create-change-set \
		--template-body file://cloudformation/autohost_server_eb/autohost_server_eb.yaml \
		--cli-input-json file://cloudformation/autohost_server_eb/update_autohost_server_staging_eb.json \
		--change-set-name latest-${EPOCH}
	@echo "Apply updates from the AWS console. (CloudFormation > [Stack] > Change sets > latest-${EPOCH})"

.PHONY: update_autohost_server_production_eb
update_autohost_server_production_eb:
	python scripts/validate_aws.py ${TWITCH_CE_HOST_AWS}
	aws cloudformation create-change-set \
		--template-body file://cloudformation/autohost_server_eb/autohost_server_eb.yaml \
		--cli-input-json file://cloudformation/autohost_server_eb/update_autohost_server_production_eb.json \
		--change-set-name latest-${EPOCH}
	@echo "Apply updates at https://us-west-2.console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks?tab=changesets"

.PHONY: create_autohost_vpc_endpoints_staging
create_autohost_vpc_endpoints_staging: 
	python scripts/validate_aws.py ${TWITCH_CE_HOST_DEV}
	aws cloudformation create-stack \
		--template-body file://cloudformation/vpc_endpoints/vpc_endpoints.yaml \
		--cli-input-json file://cloudformation/vpc_endpoints/create_vpc_endpoints_staging.json

.PHONY: create_autohost_vpc_endpoints_production
create_autohost_vpc_endpoints_production: 
	python scripts/validate_aws.py ${TWITCH_CE_HOST_AWS}
	aws cloudformation create-stack \
		--template-body file://cloudformation/vpc_endpoints/vpc_endpoints.yaml \
		--cli-input-json file://cloudformation/vpc_endpoints/create_vpc_endpoints_production.json

.PHONY: update_autohost_vpc_endpoints_staging
update_autohost_vpc_endpoints_staging:
	python scripts/validate_aws.py ${TWITCH_CE_HOST_DEV}
	aws cloudformation create-change-set \
		--template-body file://cloudformation/vpc_endpoints/vpc_endpoints.yaml \
		--cli-input-json file://cloudformation/vpc_endpoints/update_vpc_endpoints_staging.json \
		--change-set-name latest-${EPOCH}
	@echo "Apply updates from the AWS console. (CloudFormation > [Stack] > Change sets > latest-${EPOCH})"

.PHONY: update_autohost_vpc_endpoints_production
update_autohost_vpc_endpoints_production:
	python scripts/validate_aws.py ${TWITCH_CE_HOST_AWS}
	aws cloudformation create-change-set \
		--template-body file://cloudformation/vpc_endpoints/vpc_endpoints.yaml \
		--cli-input-json file://cloudformation/vpc_endpoints/update_vpc_endpoints_production.json \
		--change-set-name latest-${EPOCH}
	@echo "Apply updates at https://us-west-2.console.aws.amazon.com/cloudformation/home?region=us-west-2#/stacks?tab=changesets"

# Host DynamoDB Cloudformation

.PHONY: create_host_dynamo_db_staging
create_host_dynamo_db_staging:
	python scripts/validate_aws.py ${TWITCH_CE_HOST_DEV}
	aws cloudformation create-stack \
		--template-body file://cloudformation/host_dynamodb/dynamodb.yaml \
		--cli-input-json file://cloudformation/host_dynamodb/dynamodb.yaml

.PHONY: update_host_dynamo_db_staging
update_host_dynamo_db_staging:
	python scripts/validate_aws.py ${TWITCH_CE_HOST_DEV}
	aws cloudformation create-change-set \
		--template-body file://cloudformation/host_dynamodb/dynamodb.yaml \
		--cli-input-json file://cloudformation/host_dynamodb/update_db_staging.json \
		--change-set-name latest-${EPOCH}
	@echo "Apply updates from the AWS console. (CloudFormation > host-staging-db > Change sets > latest-${EPOCH})"

.PHONY: create_host_dynamo_db_production
create_host_dynamo_db_production:
	python scripts/validate_aws.py ${TWITCH_CE_HOST_AWS}
	aws cloudformation create-stack \
		--template-body file://cloudformation/host_dynamodb/dynamodb.yaml \
		--cli-input-json file://cloudformation/host_dynamodb/create_db_production.json

.PHONY: update_host_dynamo_db_production
update_host_dynamo_db_production:
	python scripts/validate_aws.py ${TWITCH_CE_HOST_AWS}
	aws cloudformation create-change-set \
		--template-body file://cloudformation/host_dynamodb/dynamodb.yaml \
		--cli-input-json file://cloudformation/host_dynamodb/update_db_production.json \
		--change-set-name latest-${EPOCH}
	@echo "Apply updates from the AWS console. (CloudFormation > host-production-db > Change sets)"

# Creator Collab PagerDuty Cloudformation
.PHONY: create_creator_collab_pagerduty
create_creator_collab_pagerduty:
	python scripts/validate_aws.py ${TWITCH_CE_HOST_AWS}
	aws cloudformation create-stack \
		--template-body file://cloudformation/creator_collab_pagerduty/pagerduty.yaml \
		--cli-input-json file://cloudformation/creator_collab_pagerduty/create_pagerduty.json

.PHONY: update_creator_collab_pagerduty
update_creator_collab_pagerduty:
	python scripts/validate_aws.py ${TWITCH_CE_HOST_AWS}
	aws cloudformation create-change-set \
		--template-body file://cloudformation/creator_collab_pagerduty/pagerduty.yaml \
		--cli-input-json file://cloudformation/creator_collab_pagerduty/update_pagerduty.json \
		--change-set-name latest-${EPOCH}
	@echo "Apply updates from the AWS console. (CloudFormation > host-production-pagerduty > Change sets)"

# Replicate Load Balancer Logs CloudFormation

.PHONY: create_production_replicate_load_balancer_logs
create_production_replicate_load_balancer_logs:
	aws cloudformation create-stack \
		--template-body file://cloudformation/replicate-load-balancer-logs/s3-replicate.yaml \
		--cli-input-json file://cloudformation/replicate-load-balancer-logs/production.json

.PHONY: update_production_replicate_load_balancer_logs
update_production_replicate_load_balancer_logs:
	aws cloudformation create-change-set \
		--template-body file://cloudformation/replicate-load-balancer-logs/s3-replicate.yaml \
		--cli-input-json file://cloudformation/replicate-load-balancer-logs/production.json
		--change-set-name latest-${EPOCH}
	@echo "Apply updates from the AWS console. (CloudFormation > [Stack] > Change sets > latest-${EPOCH})"

.PHONY: create_staging_replicate_load_balancer_logs
create_staging_replicate_load_balancer_logs:
	aws cloudformation create-stack \
		--template-body file://cloudformation/replicate-load-balancer-logs/s3-replicate.yaml \
		--cli-input-json file://cloudformation/replicate-load-balancer-logs/staging.json

.PHONY: update_staging_replicate_load_balancer_logs
update_staging_replicate_load_balancer_logs:
	aws cloudformation create-change-set \
		--template-body file://cloudformation/replicate-load-balancer-logs/s3-replicate.yaml \
		--cli-input-json file://cloudformation/replicate-load-balancer-logs/staging.json
		--change-set-name latest-${EPOCH}
	@echo "Apply updates from the AWS console. (CloudFormation > [Stack] > Change sets > latest-${EPOCH})"

# Twitch Security Log Funnel CloudFormation

.PHONY: create_production_twitch_security_log_funnel
create_production_twitch_security_log_funnel:
	aws cloudformation create-stack \
		--template-body file://cloudformation/twitch-security-log-funnel/stream-funnel.yaml \
		--cli-input-json file://cloudformation/twitch-security-log-funnel/production.json

.PHONY: update_production_twitch_security_log_funnel
update_production_twitch_security_log_funnel:
	aws cloudformation create-change-set \
		--template-body file://cloudformation/twitch-security-log-funnel/stream-funnel.yaml \
		--cli-input-json file://cloudformation/twitch-security-log-funnel/production.json
		--change-set-name latest-${EPOCH}
	@echo "Apply updates from the AWS console. (CloudFormation > [Stack] > Change sets > latest-${EPOCH})"

.PHONY: create_staging_twitch_security_log_funnel
create_staging_twitch_security_log_funnel:
	aws cloudformation create-stack \
		--template-body file://cloudformation/twitch-security-log-funnel/stream-funnel.yaml \
		--cli-input-json file://cloudformation/twitch-security-log-funnel/staging.json

.PHONY: update_staging_twitch_security_log_funnel
update_staging_twitch_security_log_funnel:
	aws cloudformation create-change-set \
		--template-body file://cloudformation/twitch-security-log-funnel/stream-funnel.yaml \
		--cli-input-json file://cloudformation/twitch-security-log-funnel/staging.json
		--change-set-name latest-${EPOCH}
	@echo "Apply updates from the AWS console. (CloudFormation > [Stack] > Change sets > latest-${EPOCH})"

# send-user-destroy: Create a eventbus payload for testing
.PHONY: send-user-destroy-staging
send-user-destroy-staging:
	go run cmd/send-user-destroy/main.go staging

.PHONY: send-user-destroy-production
send-user-destroy-production:
	go run cmd/send-user-destroy/main.go production