Skip to content

Commit

Permalink
Refactor deployment scripts and Makefiles for autoscaler
Browse files Browse the repository at this point in the history
 - Replace `mta-deploy` target with `deploy-apps` in Makefile
 - Add `bbl print-env` setup in `deploy-apps.sh`
 - Remove `deploy-multiapps-controller.sh` script's redundant newline
 - Remove metricsforwarder route port configuration in `use-cf-services.yml`
 - Remove instance group `metricsforwarder` from `use-cf-services.yml`
 - Update `autoscaler/Makefile` to use `build-extension-file.sh` for extension file generation
 - Add `build-extension-file.sh` script for dynamic extension file creation
 - Introduce `configutil` package with `cf.go` for VCAP service configuration parsing
 - Add `configutil_suite_test.go` and `configutil_test.go` for the new `configutil` package
 - Remove `example.mtaext` as extension file generation is now dynamic
 - Update `generate-fakes.go` to include fake VCAP configuration reader
 - Remove `helpers/cf.go` as its functionality is replaced by `configutil`
 - Update `metricsforwarder/Makefile` to remove obsolete targets and variables
 - Refactor `metricsforwarder` main and config to use `configutil` for VCAP services
 - Add `default_config.json` for `metricsforwarder` default configuration
 - Update `mta.yaml` to define `metricsforwarder` module with new resources and parameters
  • Loading branch information
bonzofenix committed Aug 27, 2024
1 parent ef8ebd0 commit 10499bd
Show file tree
Hide file tree
Showing 18 changed files with 626 additions and 235 deletions.
6 changes: 4 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -453,5 +453,7 @@ go-get-u: $(addsuffix .go-get-u,$(go_modules))
go get -u ./...


mta-deploy:
@make --directory='./src/autoscaler' mta-deploy
deploy-apps:
echo " - deploying apps"
DEBUG="${DEBUG}" ${CI_DIR}/autoscaler/scripts/deploy-apps.sh

4 changes: 4 additions & 0 deletions ci/autoscaler/scripts/deploy-apps.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ script_dir=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
source "${script_dir}/common.sh"
source "${script_dir}/vars.source.sh"

pushd "${bbl_state_path}" > /dev/null
eval "$(bbl print-env)"
popd > /dev/null

function deploy() {
log "Deploying autoscaler apps for bosh deployment '${deployment_name}' "
pushd "${autoscaler_dir}/src/autoscaler" > /dev/null
Expand Down
1 change: 0 additions & 1 deletion ci/infrastructure/scripts/deploy-multiapps-controller.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ function deploy_multiapps_controller() {
mv multiapps-controller-web-war/*.war .
pushd multiapps-controller-web-manifest
cf push -f ./*.yml "${app_name}"

popd
}

Expand Down
8 changes: 3 additions & 5 deletions operations/use-cf-services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,6 @@
host: ((metricsforwarder_host))
mtls_host: ((metricsforwarder_host))

# Set the same port for metricsforwarder and healthenpoint routes
- type: replace
path: /instance_groups/name=metricsforwarder/jobs/name=route_registrar/properties/route_registrar/routes/name=autoscaler_metricsforwarder_health/port
value: 6201

## add router tcp route for postgres
- type: replace
path: /instance_groups/name=postgres/jobs/-
Expand Down Expand Up @@ -53,3 +48,6 @@
- type: replace
path: /variables/name=postgres_client/options/alternative_names/-
value: ((deployment_name))-postgres.tcp.((system_domain))

- type: remove
path: /instance_groups/name=metricsforwarder
11 changes: 4 additions & 7 deletions src/autoscaler/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ PACKAGE_DIRS = $(shell go list './...' | grep --invert-match --regexp='/vendor/'
DB_HOST ?= localhost
DBURL ?= "postgres://postgres:postgres@${DB_HOST}/autoscaler?sslmode=disable"

METRICSFORWARDER_APPNAME ?= "metricsforwarder"
MAKEFILE_DIR := $(dir $(lastword $(MAKEFILE_LIST)))
EXTENSION_FILE := $(shell mktemp)

export GOWORK=off
Expand Down Expand Up @@ -154,14 +154,12 @@ clean:
.PHONY: mta-deploy
mta-deploy: mta-build build-extension-file
$(MAKE) -f metricsforwarder/Makefile set-security-group
$(MAKE) -f metricsforwarder/Makefile stop-metricsforwarder-vm
@echo "Deploying with extension file: $(EXTENSION_FILE)"
@cf deploy mta_archives/*.mtar -f -e $(EXTENSION_FILE)
@cf deploy mta_archives/*.mtar -f --delete-services -e $(EXTENSION_FILE)

build-extension-file:
cp example.mtaext $(EXTENSION_FILE);
sed -i "s/APP_NAME/$(METRICSFORWARDER_APPNAME)/g" $(EXTENSION_FILE);
echo "EXTENSION_FILE: $(EXTENSION_FILE)"
echo "extension file at: $(EXTENSION_FILE)"
$(MAKEFILE_DIR)/build-extension-file.sh $(EXTENSION_FILE);

mta-logs:
rm -rf mta-*
Expand All @@ -170,7 +168,6 @@ mta-logs:

.PHONY: mta-build
mta-build: mta-build-clean cf-build
$(MAKE) -f metricsforwarder/Makefile fetch-config
mbt build

mta-build-clean:
Expand Down
71 changes: 71 additions & 0 deletions src/autoscaler/build-extension-file.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#!/usr/bin/env bash
# shellcheck disable=SC2155,SC2034,SC2086

set -e

if [ -z "$1" ]; then
echo "extension file path not provided"
exit 1
else
extension_file_path=$1
fi

if [ -z "${DEPLOYMENT_NAME}" ]; then
echo "DEPLOYMENT_NAME is not set"
exit 1
fi

if [ -z "${PR_NUMBER}" ]; then
echo "PR_NUMBER is not set"
exit 1
fi

export SYSTEM_DOMAIN="autoscaler.app-runtime-interfaces.ci.cloudfoundry.org"
export POSTGRES_ADDRESS="${DEPLOYMENT_NAME}-postgres.tcp.${SYSTEM_DOMAIN}"
export POSTGRES_EXTERNAL_PORT="${PR_NUMBER:-5432}"

export METRICSFORWARDER_HEALTH_PASSWORD="$(credhub get -n /bosh-autoscaler/${DEPLOYMENT_NAME}/autoscaler_metricsforwarder_health_password --quiet)"
export METRICSFORWARDER_APPNAME="${METRICSFORWARDER_APPNAME:-"${DEPLOYMENT_NAME}-metricsforwarder"}"

export POLICY_DB_PASSWORD="$(credhub get -n /bosh-autoscaler/${DEPLOYMENT_NAME}/database_password --quiet)"
export POLICY_DB_SERVER_CA="$(credhub get -n /bosh-autoscaler/${DEPLOYMENT_NAME}/postgres_server --key ca --quiet )"
export POLICY_DB_CLIENT_CERT="$(credhub get -n /bosh-autoscaler/${DEPLOYMENT_NAME}/postgres_server --key certificate --quiet)"
export POLICY_DB_CLIENT_KEY="$(credhub get -n /bosh-autoscaler/${DEPLOYMENT_NAME}/postgres_server --key private_key --quiet)"

export SYSLOG_CLIENT_CA="$(credhub get -n /bosh-autoscaler/cf/syslog_agent_log_cache_tls --key ca --quiet)"
export SYSLOG_CLIENT_CERT="$(credhub get -n /bosh-autoscaler/cf/syslog_agent_log_cache_tls --key certificate --quiet)"
export SYSLOG_CLIENT_KEY="$(credhub get -n /bosh-autoscaler/cf/syslog_agent_log_cache_tls --key private_key --quiet)"

cat <<EOF > "${extension_file_path}"
ID: development
extends: com.github.cloudfoundry.app-autoscaler-release
version: 1.0.0
_schema-version: 3.3.0
modules:
- name: metricsforwarder
parameters:
routes:
- route: ${METRICSFORWARDER_APPNAME}.\${default-domain}
resources:
- name: config
parameters:
config:
metricsforwarder:
health:
password: "${METRICSFORWARDER_HEALTH_PASSWORD}"
- name: policydb
parameters:
config:
uri: "postgres://postgres:${POLICY_DB_PASSWORD}@${POSTGRES_ADDRESS}:${POSTGRES_EXTERNAL_PORT}/autoscaler?application_name=metricsforwarder&sslmode=verify-full"
client_cert: "${POLICY_DB_CLIENT_CERT//$'\n'/\\n}"
client_key: "${POLICY_DB_CLIENT_KEY//$'\n'/\\n}"
server_ca: "${POLICY_DB_SERVER_CA//$'\n'/\\n}"
- name: syslog-client
parameters:
config:
client_cert: "${SYSLOG_CLIENT_CERT//$'\n'/\\n}"
client_key: "${SYSLOG_CLIENT_KEY//$'\n'/\\n}"
server_ca: "${SYSLOG_CLIENT_CA//$'\n'/\\n}"
EOF
151 changes: 151 additions & 0 deletions src/autoscaler/configutil/cf.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
package configutil

import (
"errors"
"fmt"
"net/url"
"os"

"code.cloudfoundry.org/app-autoscaler/src/autoscaler/models"
"github.com/cloudfoundry-community/go-cfenv"
)

var ErrReadEnvironment = errors.New("failed to read environment variables")
var ErrDbServiceNotFound = errors.New("failed to get service by name")

type VCAPConfigurationReader interface {
MaterializeDBFromService(dbName string) (string, error)
MaterializeTLSConfigFromService(serviceName string) (models.TLSCerts, error)
}

type VCAPConfiguration struct {
VCAPConfigurationReader
appEnv *cfenv.App
}

func NewVCAPConfigurationReader() (*VCAPConfiguration, error) {
vcapConfiguration := &VCAPConfiguration{}
appEnv, err := cfenv.Current()
if err != nil {
return nil, fmt.Errorf("%w: %w", ErrReadEnvironment, err)
}

vcapConfiguration.appEnv = appEnv
return vcapConfiguration, nil
}

func (vc *VCAPConfiguration) MaterializeTLSConfigFromService(serviceName string) (models.TLSCerts, error) {
tlsCerts := models.TLSCerts{}
services, err := vc.appEnv.Services.WithTag(serviceName)
if err != nil {
return tlsCerts, fmt.Errorf("%w: %w", ErrDbServiceNotFound, err)
}

service := services[0]

if clientCertContent, ok := service.CredentialString("client_cert"); ok {
fileName := fmt.Sprintf("%s.%s", "client_cert", "sslcert")
createdClientCert, err := materializeServiceProperty(serviceName, fileName, clientCertContent)
if err != nil {
return models.TLSCerts{}, err
}
tlsCerts.CertFile = createdClientCert
} else {
return models.TLSCerts{}, fmt.Errorf(fmt.Sprintf("failed to get %s from db service", "client_cert"))
}

if clientKeyContent, ok := service.CredentialString("client_key"); ok {
fileName := fmt.Sprintf("%s.%s", "client_key", "sslkey")
createdClientKey, err := materializeServiceProperty(serviceName, fileName, clientKeyContent)
if err != nil {
return models.TLSCerts{}, err
}
tlsCerts.KeyFile = createdClientKey
} else {
return models.TLSCerts{}, fmt.Errorf(fmt.Sprintf("failed to get %s from db service", "client_key"))
}

if serverCAContent, ok := service.CredentialString("server_ca"); ok {
fileName := fmt.Sprintf("%s.%s", "server_ca", "sslrootcert")
createServerCA, err := materializeServiceProperty(serviceName, fileName, serverCAContent)
if err != nil {
return models.TLSCerts{}, err
}
tlsCerts.CACertFile = createServerCA
} else {
return models.TLSCerts{}, fmt.Errorf(fmt.Sprintf("failed to get %s from db service", "server_ca"))
}

return tlsCerts, nil
}

func (vc *VCAPConfiguration) MaterializeDBFromService(dbName string) (string, error) {
var dbURL *url.URL
var err error

service, err := vc.appEnv.Services.WithTag(dbName)
if err != nil {
return "", fmt.Errorf("%w: %w", ErrDbServiceNotFound, err)
}

dbService := service[0]

dbURI, ok := dbService.CredentialString("uri")
if !ok {
return "", fmt.Errorf("failed to get uri from db service")
}

dbURL, err = url.Parse(dbURI)
if err != nil {
return "", err
}

parameters, err := url.ParseQuery(dbURL.RawQuery)
if err != nil {
return "", err
}

err = materializeConnectionParameter(dbName, dbService, &parameters, "client_cert", "sslcert")
if err != nil {
return "", err
}

err = materializeConnectionParameter(dbName, dbService, &parameters, "client_key", "sslkey")
if err != nil {
return "", err
}

err = materializeConnectionParameter(dbName, dbService, &parameters, "server_ca", "sslrootcert")
if err != nil {
return "", err
}

dbURL.RawQuery = parameters.Encode()

return dbURL.String(), nil
}

func materializeConnectionParameter(dbName string, dbService cfenv.Service, parameters *url.Values, bindingProperty string, connectionParameter string) error {
if content, hasProperty := dbService.CredentialString(bindingProperty); hasProperty {
fileName := fmt.Sprintf("%s.%s", bindingProperty, connectionParameter)
createdFile, err := materializeServiceProperty(dbName, fileName, content)
if err != nil {
return err
}
parameters.Set(connectionParameter, createdFile)
}
return nil
}

func materializeServiceProperty(serviceName, fileName, content string) (createdFile string, err error) {
err = os.MkdirAll(fmt.Sprintf("/tmp/%s", serviceName), 0700)
if err != nil {
return "", err
}
createdFile = fmt.Sprintf("/tmp/%s/%s", serviceName, fileName)
err = os.WriteFile(createdFile, []byte(content), 0600)
if err != nil {
return "", err
}
return
}
13 changes: 13 additions & 0 deletions src/autoscaler/configutil/configutil_suite_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package configutil_test

import (
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

func TestConfigutil(t *testing.T) {
RegisterFailHandler(Fail)
RunSpecs(t, "Configutil Suite")
}
Loading

0 comments on commit 10499bd

Please sign in to comment.