Skip to content
This repository has been archived by the owner on Oct 24, 2020. It is now read-only.

Commit

Permalink
feat: Check names for invalid characters and lengths
Browse files Browse the repository at this point in the history
closes #46
  • Loading branch information
jrconlin committed Apr 10, 2017
1 parent 3c8127a commit c886f6a
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 0 deletions.
33 changes: 33 additions & 0 deletions ardere/step_functions.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json
import logging
import os
import re
import time
from collections import defaultdict

Expand Down Expand Up @@ -31,6 +32,15 @@
logger = logging.getLogger()
logger.setLevel(logging.INFO)

# Step name is used as the Log stream name.
# Log stream names are limited to 512 characters (no ":" or "*")
# Name format is
# ardere-UUID/STEP_NAME/LUUID
# where UUID is dashed, and LUUID is not
# therefore: 512 - (9 + 36 + 32) = max name len
MAX_NAME_LEN = 435
INVALID_NAME_CHECK = re.compile("([:\*]+)")


class StepValidator(Schema):
name = fields.String(required=True)
Expand All @@ -47,6 +57,15 @@ class StepValidator(Schema):
env = fields.Dict()
docker_series = fields.String(missing="default")

@decorators.validates("name")
def validate_name(self, value):
if len(value) == 0:
raise ValidationError("Step name missing")
if len(value) > MAX_NAME_LEN:
raise ValidationError("Step name too long")
if INVALID_NAME_CHECK.search(value):
raise ValidationError("Step name contains invalid characters")


class DashboardOptions(Schema):
admin_user = fields.String(missing="admin")
Expand All @@ -72,16 +91,30 @@ class PlanValidator(Schema):

steps = fields.Nested(StepValidator, many=True)

def _log_validate_name(self, value, name_type):
if len(value) == 0:
raise ValidationError("{} missing".format(name_type))
if len(value) > MAX_NAME_LEN:
raise ValidationError("{} too long".format(name_type))
if INVALID_NAME_CHECK.search(value):
raise ValidationError(
"{} contained invalid characters".format(name_type))

@decorators.validates("ecs_name")
def validate_ecs_name(self, value):
"""Verify a cluster exists for this name"""
self._log_validate_name(value, "Plan ecs_name")
client = self.context["boto"].client('ecs')
response = client.describe_clusters(
clusters=[value]
)
if not response.get("clusters"):
raise ValidationError("No cluster with the provided name.")

@decorators.validates("name")
def validate_name(self, value):
self._log_validate_name(value, "Step name")


class AsynchronousPlanRunner(object):
"""Asynchronous Test Plan Runner
Expand Down
33 changes: 33 additions & 0 deletions config.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#! /bin/bash -w

ctrlc()
{
echo " Exiting..."
rm ~/.aws/credentials
exit 1
}
set -e

if [[ "`which serverless`" == "" ]]
then
echo "Hrm, serverless is not installed. "
echo "See https://serverless.com/framework/docs/providers/aws/guide/installation/"
return
fi
if [[ ! -e ~/.aws/credentials ]]
then
trap ctrlc SIGINT
echo " credential file was not found. Let's make one."
echo ""
echo " If you haven't already, you'll need to create an access key."
echo " e.g. go to https://console.aws.amazon.com/iam/home#/users/${USER}/?security_credientials"
echo " and click [Create access key]."
echo ""
read -p "Access Key ID: " access_key
read -p "Secret Key ID: " secret_key
echo " Thanks! Running configuration";
echo serverless config credentials --provider aws --key $access_key --secret $secret_key
serverless config credentials --provider aws --key $access_key --secret $secret_key
fi
echo " You're configured. The next step is to deploy."

5 changes: 5 additions & 0 deletions serverless.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ package:
- node_modules/**
- ardenv/**
- tests/**
- lib/**
- share/**
- man/**
- bin/**
- serverless/**
include:
- ardere/**

Expand Down
30 changes: 30 additions & 0 deletions tests/test_step_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,36 @@ def test_validate_success(self):
eq_(errors, {})
eq_(len(data["steps"]), len(plan["steps"]))

def test_validate_fail_ecs_name(self):
schema = self._make_FUT()
schema.context["boto"] = mock.Mock()
plan = json.loads(fixtures.sample_basic_test_plan)
plan['ecs_name'] = ''
data, errors = schema.load(plan)
eq_(errors, {'ecs_name': ['Plan ecs_name missing']})
plan['ecs_name'] += '*'
data, errors = schema.load(plan)
eq_(errors, {'ecs_name':
['Plan ecs_name contained invalid characters']})
plan['ecs_name'] = 'a' * 512
data, errors = schema.load(plan)
eq_(errors, {'ecs_name': ['Plan ecs_name too long']})

def test_validate_fail_step_name(self):
schema = self._make_FUT()
schema.context["boto"] = mock.Mock()
plan = json.loads(fixtures.sample_basic_test_plan)
plan['steps'][0]['name'] = ''
data, errors = schema.load(plan)
eq_(errors, {'steps': {0: {'name': ['Step name missing']}}})
plan['steps'][0]['name'] = '*'
data, errors = schema.load(plan)
eq_(errors, {'steps': {0: {'name':
['Step name contains invalid characters']}}})
plan['steps'][0]['name'] = 'a' * 512
data, errors = schema.load(plan)
eq_(errors, {'steps': {0: {'name': ['Step name too long']}}})

def test_validate_fail(self):
schema = self._make_FUT()
schema.context["boto"] = mock_boto = mock.Mock()
Expand Down

0 comments on commit c886f6a

Please sign in to comment.