Skip to content

Commit

Permalink
refactor shell script logic, add linting
Browse files Browse the repository at this point in the history
  • Loading branch information
jspaleta committed Dec 4, 2020
1 parent 2a3c2fd commit 0c42114
Show file tree
Hide file tree
Showing 7 changed files with 133 additions and 114 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ jobs:
sensu_user: ${{ secrets.SENSU_USER }}
sensu_password: ${{ secrets.SENSU_PASSWORD }}
namespaces_dir: ci-namespaces
required_label: "sensu.io/workflow"
label_matching_condition: "== ci_action"
matching_label: "sensu.io/workflow"
matching_condition: "== ci_action"


22 changes: 13 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Github Action for Sensu flow resource management pattern.

## Introduction
This github action will allow you to manage Sensu resources for a namespaces by making use of sensuctl prune and create commands. The `sensu prune` command is scope by the action's `required_label`, `label_matching_condition`, and `managed_resources`settings. Please see the sensuctl command documentation for information.
This github action will allow you to manage Sensu resources for a namespaces by making use of sensuctl prune and create commands. The `sensu prune` command is scope by the action's `matching_label`, `matching_condition`, and `managed_resources`settings. Please see the sensuctl command documentation for information.

In order to use this action, you'll need to define a Sensu user and associated role based access control.

Expand All @@ -29,7 +29,7 @@ namespaces
└── check-status.yaml
```

Using this example, this action would process the `test-namespace`, pruning the namespace resources according to `required_label`, `label_matching_condition`, and `managed_resources`settings
Using this example, this action would process the `test-namespace`, pruning the namespace resources according to `matching_label`, `matching_condition`, and `managed_resources`settings

### Optionally Preparing namespaces
If the `namespaces.yaml` file exists in the working directory (normally the top level of your repository) then this action will be used to create sensu namespaces before attempting to process the namespaces directory.
Expand All @@ -46,16 +46,20 @@ If the `namespaces.yaml` file exists in the working directory (normally the top
### Optional settings
#### configure_args:
description: "optional arguments to pass to sensuctl configure"
#### sensu_ca:
description: 'Optional Custom CA pem string'
#### sensu_ca_string:
description: 'Optional Custom CA pem string. Use this if you want to encode the CA pem as a github secret'
#### sensu_ca_file:
description: 'Optional Custom CA file location, this will override sensu_ca_string if used'
#### namespaces_dir:
description: "Optional directory to process default: 'namespaces' "
#### required_label:
#### namespaces_file:
description: "Optional YAML file containing Sensu namespace resources to create"
#### matching_label:
description: "Option Sensu label selector, default: 'sensu.io/workflow'"
#### label_matching_condition:
#### matching_condition:
description: "Option Sensu label matching condition, default: '== sensu_flow'"
#### managed_resources:
description: 'Optional comma seperated list of managed resources'
description: 'Optional comma seperated list of managed resources, default: "checks,handlers,filters,mutators,assets,secrets/v1.Secret,roles,role-bindings"'
#### disable_sanity_checks:
description: 'Optional boolean argument to to disable sanity checks default: false'

Expand All @@ -77,8 +81,8 @@ jobs:
sensu_user: ${{ secrets.SENSU_USER }}
sensu_password: ${{ secrets.SENSU_PASSWORD }}
namespaces_dir: namespaces
required_label: "sensu.io/workflow"
label_matching_condition: "== sensu_flow"
matching_label: "sensu.io/workflow"
matching_condition: "== sensu_flow"
```
### RBAC Policy
Expand Down
16 changes: 11 additions & 5 deletions action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,23 @@ inputs:
configure_args:
description: "optional arguments to pass to sensuctl configure"
required: false
sensu_ca:
sensu_ca_string:
description: 'Optional Custom CA pem string'
required: false
sensu_ca_file:
description: 'Optional Custom CA pem file location'
required: false
namespaces_dir:
description: "Optional directory to process default: 'namespaces' "
required: false
required_label:
description: "Option Sensu label selector, default: 'sensu.io/workflow'"
namespaces_files:
description: "Optional YAML file containing namespace resource to create default: 'namespaces.yaml' "
required: false
matching_label:
description: "Option Sensu label to use in label selector, default: 'sensu.io/workflow'"
required: false
label_matching_condition:
description: "Option Sensu label matching condition, default: '== sensu_flow'"
matching_condition:
description: "Option Sensu label matching condition for label selector, default: '== sensu_flow'"
required: false
managed_resources:
description: 'Optional comma seperated list of managed resources'
Expand Down
1 change: 1 addition & 0 deletions ci-namespaces/ci-namespace/checks/check-cpu.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ type: CheckConfig
api_version: core/v2
metadata:
name: cpu
namespace: ci-namespace
labels:
sensu.io/workflow: ci_action
spec:
Expand Down
3 changes: 3 additions & 0 deletions ci-namespaces/ci-namespace/filters/fatigue-check.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ type: EventFilter
api_version: core/v2
metadata:
name: fatigue-check
labels:
sensu.io/workflow: sensu-flow
spec:
action: allow
expressions:
Expand All @@ -14,6 +16,7 @@ api_version: core/v2
metadata:
name: sensu-go-fatigue-check-filter
labels:
sensu.io/workflow: sensu-flow
annotations:
io.sensu.bonsai.url: https://bonsai.sensu.io/assets/nixwiz/sensu-go-fatigue-check-filter
io.sensu.bonsai.api_url: https://bonsai.sensu.io/api/v1/assets/nixwiz/sensu-go-fatigue-check-filter
Expand Down
3 changes: 3 additions & 0 deletions ci-namespaces/ci-namespace/mutators/check-status.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ type: Mutator
api_version: core/v2
metadata:
name: sensu-check-status-metric-mutator
labels:
sensu.io/workflow: sensu-flow
spec:
command: >-
sensu-check-status-metric-mutator
Expand All @@ -14,6 +16,7 @@ api_version: core/v2
metadata:
name: sensu-check-status-metric-mutator:0.2.1
labels:
sensu.io/workflow: sensu-flow
annotations:
io.sensu.bonsai.url: https://bonsai.sensu.io/assets/nixwiz/sensu-check-status-metric-mutator
io.sensu.bonsai.api_url: https://bonsai.sensu.io/api/v1/assets/nixwiz/sensu-check-status-metric-mutator
Expand Down
198 changes: 100 additions & 98 deletions sensuflow.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,125 +16,93 @@
# SENSU_CA_FILE: CA certificate file, if set overrides SENSU_CA
# CONFIGURE_OPTIONS: Additional sensuctl configure options
# NAMESPACES_DIR: directory holding sensuflow namepace subdirectories
# NAMESPACES_FILE: file holding namespace resource definitions sensuflow action should create
# MANAGED_RESOURCES: comma seperated list of resources
# REQUIRED_LABEL: resource label required
# LABEL_MATCHING_CONDITION: condition to match
###
# MATCHING_LABEL: resource label to match
# MATCHING_CONDITION: condition to match
# DISABLE_SANITY_CHECKS: if set disable sanity checks

### Defaults
preflight_check=0
REQUIRED_LABEL="sensu.io/workflow"
LABEL_MATCHING_CONDITION="== sensu_flow"
DISABLE_SANITY_CHECKS=""
MANAGED_RESOURCES="checks,handlers,filters,mutators,assets,secrets/v1.Secret,roles,role-bindings"
NAMESPACES_DIR="namespaces"
JSON_DIR="/tmp/json"
echo "Working Directory: $PWD"
## Github Action Notes
# Github Actions prefaces variables with INPUT_

## Read in envvars from .env from current directory
if [ -f ./.env ] ; then
source ./.env
fi

[ -z "$SENSU_USER" ] && [ -z "$INPUT_SENSU_USER" ] && echo "SENSU_USER environment variable empty" && preflight_check=1
[ -z "$SENSU_PASSWORD" ] && [ -z "$INPUT_SENSU_PASSWORD" ] && echo "SENSU_PASSWORD environment variable empty" && preflight_check=1
[ -z "$SENSU_BACKEND_URL" ] && [ -z "$INPUT_SENSU_BACKEND_URL" ] && echo "SENSU_BACKEND_URL environment variable empty" && preflight_check=1

[ -z "$REQUIRED_LABEL" ] && [ -z "$INPUT_REQUIRED_LABEL" ] && echo "REQUIRED_LABEL environment variable empty" && preflight_check=1
[ -z "$LABEL_MATCHING_CONDITION" ] && [ -z "$INPUT_LABEL_MATCHING_CONDITION" ] && echo "LABEL_MATCHING_CONDITION environment variable empty" && preflight_check=1

[ -z "$MANAGED_RESOURCES" ] && [ -z "$INPUT_MANAGED_RESOURCES" ] && echo "MANAGED_RESOURCES environment variable empty" && preflight_check=1
[ -z "$NAMESPACES_DIR" ] && [ -z "$INPUT_NAMESPACES_DIR" ] && echo "NAMESPACES_DIE environment variable empty" && preflight_check=1
### Setup envvar values, including fallback defaults where needed
: ${MATCHING_LABEL:=${INPUT_MATCHING_LABEL:="sensu.io/workflow"}}
: ${MATCHING_CONDITION:=${INPUT_MATCHING_CONDITION:="== sensu_flow"}}
: ${MANAGED_RESOURCES:=${INPUT_MANAGED_RESOURCES:="checks,handlers,filters,mutators,assets,secrets/v1.Secret,roles,role-bindings"}}
: ${NAMESPACES_DIR:=${INPUT_NAMESPACES_DIR:="namespaces"}}
: ${NAMESPACES_FILE:=${INPUT_NAMESPACES_FILE:="namespaces.yaml"}}
: ${DISABLE_SANITY_CHECKS:=${INPUT_DISABLE_SANITY_CHECKS:="false"}}
: ${VERBOSE:=${INPUT_VERBOSE:=""}}
: ${SENSU_USER:=${INPUT_SENSU_USER}}
: ${SENSU_PASSWORD:=${INPUT_SENSU_PASSWORD}}
: ${SENSU_BACKEND_URL:=${INPUT_SENSU_BACKEND_URL}}
: ${CONFIGURE_ARGS:=${INPUT_CONFIGURE_ARGS}}
: ${SENSU_CA_STRING:=${INPUT_SENSU_CA_STRING}}
: ${SENSU_CA_FILE:=${INPUT_SENSU_CA_FILE}}

if [[ $VERBOSE ]]; then echo "Working Directory: $PWD"; fi
# Check for required envvars to be defined
preflight_check=0
[ -z "$SENSU_USER" ] && echo "SENSU_USER environment variable empty" && preflight_check=1
[ -z "$SENSU_PASSWORD" ] && echo "SENSU_PASSWORD environment variable empty" && preflight_check=1
[ -z "$SENSU_BACKEND_URL" ] && echo "SENSU_BACKEND_URL environment variable empty" && preflight_check=1
[ -z "$MATCHING_LABEL" ] && echo "MATCHING_LABEL environment variable empty" && preflight_check=1
[ -z "$MATCHING_CONDITION" ] && echo "MATCHING_CONDITION environment variable empty" && preflight_check=1
[ -z "$MANAGED_RESOURCES" ] && echo "MANAGED_RESOURCES environment variable empty" && preflight_check=1
[ -z "$NAMESPACES_DIR" ] && echo "NAMESPACES_DIE environment variable empty" && preflight_check=1

if test $preflight_check -ne 0 ; then
echo "Missing environment variables"
exit 1
else
echo "All needed environment variables are available"
if [[ $VERBOSE ]]; then echo "All needed environment variables are available"; fi
fi

if [ -z "$INPUT_SENSU_USER" ] ; then
username=$SENSU_USER
else
username=$INPUT_SENSU_USER
fi
if [ -z "$INPUT_SENSU_PASSWORD" ] ; then
password=$SENSU_PASSWORD
else
password=$INPUT_SENSU_PASSWORD
fi
if [ -z "$INPUT_SENSU_COMMAND" ] ; then
cmd=$SENSU_COMMAND
else
cmd=$INPUT_SENSU_COMMAND
fi
if [ -z "$INPUT_SENSU_BACKEND_URL" ] ; then
url=$SENSU_BACKEND_URL
else
url=$INPUT_SENSU_BACKEND_URL
fi
if [ -z "$INPUT_CONFIGURE_ARGS" ] ; then
optional_args=$CONFIGURE_ARGS
else
optional_args=$INPUT_CONFIGURE_ARGS
fi
if [ -z "$INPUT_SENSU_CA" ] ; then
ca_string=$SENSU_CA
else
ca_string=$INPUT_SENSU_CA
fi

if [ -z "$INPUT_REQUIRED_LABEL" ] ; then
label=$REQUIRED_LABEL
else
label=$INPUT_REQUIRED_LABEL
fi

if [ -z "$INPUT_LABEL_MATCHING_CONDITION" ] ; then
matching_condition=$LABEL_MATCHING_CONDITION
LABEL_SELECTOR="${MATCHING_LABEL} ${MATCHING_CONDITION}"
if [ -z "$SENSU_CA_STRING" ] ; then
touch /tmp/sensu_ca.pem
else
matching_condition=$INPUT_LABEL_MATCHING_CONDITION
echo $SENSU_CA_STRING > /tmp/sensu_ca.pem
fi
label_selector=${label}+" "+${matching_condition}
: ${SENSU_CA_FILE:="/tmp/sensu_ca.pem"}

if [ -z "$INPUT_MANAGED_RESOURCES" ] ; then
managed_resources=$MANAGED_RESOURCES
else
managed_resources=$INPUT_MANAGED_RESOURCES
fi
if [ -z "$INPUT_NAMESPACES_DIR" ] ; then
namespaces_dir=$NAMESPACES_DIR
if [ -s $SENSU_CA_FILE ]; then
if [[ $VERBOSE ]]; then echo "custom CA file present"; fi
CA_ARG="--trusted-ca-file ${SENSU_CA_FILE}"
else
namespaces_dir=$INPUT_NAMESPACES_DIR
CA_ARG=''
fi

if [ -z "$ca_string" ] ; then
touch /tmp/sensu_ca.pem
else
echo $ca_string > /tmp/sensu_ca.pem
if [ "$DISABLE_SANITY_CHECKS" = "false" ]; then
DISABLE_SANITY_CHECKS=""
fi
ca_file="/tmp/sensu_ca.pem"

if [ -s $ca_file ]; then
echo "custom CA file present"
ca_arg="--trusted-ca-file ${ca_file}"
if [ -z "$DISABLE_SANITY_CHECKS" ]; then
if [[ $VERBOSE ]]; then echo "sanity checks enabled"; fi
else
ca_arg=''
if [[ $VERBOSE ]]; then echo "sanity checks disabled"; fi
fi

echo "Configuring sensuctl:"
sensuctl configure -n --username ${username} --password ${password} --url ${url} ${ca_arg} ${optional_args}
if [[ $VERBOSE ]]; then echo "Configuring sensuctl:"; fi
sensuctl configure -n --username ${SENSU_USER} --password ${SENSU_PASSWORD} --url ${SENSU_BACKEND_URL} ${CA_ARG} ${CONFIGURE_OPTIONS}
retval=$?
sensuctl config view
if test $retval -ne 0; then
echo "sensuctl configure failed"
exit $retval
fi
echo "Current Directory:"
pwd

echo "Executing Sensuflow"
echo "Required Label: $(label)"
echo "Label Matching Condition: $(matching_condition)"
echo "Label Selector: $(label_selector)"
if [[ $VERBOSE ]]; then
echo "Current Directory:"
pwd
echo "Executing Sensuflow"
echo "Matching Label: ${MATCHING_LABEL}"
echo "Matching Condition: ${MATCHING_CONDITION}"
echo "Label Selector: ${LABEL_SELECTOR}"
fi
# Functions

# Display error message and exit
Expand All @@ -150,27 +118,61 @@ function is_namespace {
return $?
}

function lint_resource_metadata {
resource_dir=$1
required_label=$2
allowed_namespace=$3
if [[ $VERBOSE ]]; then echo "linting resource metadata in $resource_dir"; fi
yaml_files=$(find $resource_dir -name "*.y?ml")
for file in $yaml_files ; do
if [[ $required_label ]] ; then
items=($(yq read -d '*' $file 'metadata.name'))
labels=($(yq read -d '*' $file "metadata.labels(${required_label}"))
if [ ${#items[@]} -ne ${#labels[@]} ] ; then die "resource in $file may be missing label $MATCHING_LABEL" ; fi
fi
result=$(yq read -d '*' $file 'metadata.namespace')
for line in $result; do
if [[ $allowed_namespace ]] ; then
if [ $line -ne $allowed_namespace ]; then die "resource in $file has metadata.namespace defined as $line" ; fi
else
if [[ $line ]]; then die "resource in $file has metadata.namespace defined as $line" ; fi
fi
done

done
json_files=$(find $resource_dir -name "*.json")
for file in $json_files ; do
result=$(jq $file 'metadata.namespace')
for line in $result; do
if [[ $line ]]; then die "json resource $file has .metadata.namespace defined" ; fi
done
done
}

# Main

# First, make sure we have our namespaces
if test -f namespaces.yaml
if test -f ${NAMESPACES_FILE}
then
yq v namespaces.yaml || die "namespaces.yaml is not valid yaml"
yq v namespaces.yaml || die "$NAMESPACES_FILE is not valid yaml"

sensuctl create -f namespaces.yaml
sensuctl create -f namespaces.yaml || die "sensuctl error creating namespaces file"

fi

cd $namespaces_dir || die "Failed to cd to namespaces directory!"
echo "Namespaces Directory: $(pwd)"

cd $NAMESPACES_DIR || die "Failed to cd to namespaces directory!"
if [[ $VERBOSE ]]; then echo "Namespaces Directory: $(pwd)"; fi

for namespace in $(ls -1)
do
# If not a directory of resources then skip
if ! test -d ${namespace}
then
echo "${namespace} in $namespaces_dir/ is not a directory, skipping"
echo "${namespace} in ${NAMESPACES_DIR}/ is not a directory, skipping"
continue
fi
if [ -z $DISABLE_SANITY_CHECKS ]; then lint_resource_metadata ${namespace} ${MATCHING_LABEL} ${namespace}; fi

if ! is_namespace ${namespace}
then
Expand All @@ -184,8 +186,8 @@ do

echo "Namespace ${namespace}"
echo -e "Pruning resources...\c"
NUM=$(sensuctl prune ${MANAGED_RESOURCES} --namespace ${namespace} --label-selector "${label_selector}" -r -f ${namespace} | jq '. | length')
echo "${NUM} resources deleted"
num=$(sensuctl prune ${MANAGED_RESOURCES} --namespace ${namespace} --label-selector "${LABEL_SELECTOR}" -r -f ${namespace} | jq '. | length')
echo "${num} resources deleted"

echo -e "Creating/Updating resources...\c"
# Would be really nice if this gave us some type of output
Expand Down

0 comments on commit 0c42114

Please sign in to comment.