Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSON Templates Tests, S3 Events Support, and Moar Unit Tests #188

Merged
merged 6 commits into from
Jun 20, 2017

Conversation

jacknagz
Copy link
Contributor

to @ryandeivert
cc @airbnb/streamalert-maintainers

Changes

  • Move format_lambda_test_record into the cli.helpers package: This is an effort to share this method across tests (for main/handler, which will come soon). I also removed the nesting of helper methods within a CLIHelpers class since that paradigm wasn't being adopted.
  • Modularize terraform_generate: All cluster generation was in one massive method before, this has been broken out into multiple methods for easier management.
  • Unit testing: Adds initial unit tests to the terraform_generate code, there are more to add, they will come later.
  • Moar unit testing: Get our coverage to 100% for the rule processor config module.

Jack Naglieri added 3 commits June 19, 2017 17:23
@jacknagz jacknagz force-pushed the jacknaglieri-s3-events-json-clusters branch from 33310b6 to 3e03747 Compare June 20, 2017 00:23
@jacknagz jacknagz added this to the 1.4.0 milestone Jun 20, 2017
@ryandeivert
Copy link
Contributor

nit - typo: moar --> more 🤣

@jacknagz
Copy link
Contributor Author

wow it's not a typo @ryandeivert

screen shot 2017-06-19 at 5 26 58 pm

@coveralls
Copy link

Coverage Status

Coverage increased (+0.8%) to 79.32% when pulling 3e03747 on jacknaglieri-s3-events-json-clusters into 8f086dd on master.

@jacknagz
Copy link
Contributor Author

Related: #176

Copy link
Contributor

@ryandeivert ryandeivert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great additions overall! Much needed stuff in here. A few comments in line.

}
# doing this because after kinesis_data is read in, types are casted per the schema
for alert in alerts:
assert_equal(set(alert['record'].keys()), set(kinesis_data.keys()))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Import and use assert_list_equal here instead of casting to set. Not essential, but makes what is being tested more clear and avoid casting

def test_load_config_invalid():
"""Config Validator - Load Config - Invalid"""
m = mock_open()
with patch('__builtin__.open', m, create=True):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👏 👏 👏 👏 👏 👏 👏 👏 👏 👏 👏 🎬

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should remove the argument to load_config (it was originally added for tests)

"""Test class for the Terraform Cluster Generating"""

@classmethod
def setup_class(cls):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

setup_class and teardown_class class are not actually required for nose to pick up a class and process tests within it. In fact teardown_class only gets called if setup_class is present, but if there is nothing in either they should be omitted.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

return False
try:
subprocess.check_call(runner_args, stdout=stdout_option, cwd=cwd)
except subprocess.CalledProcessError as e:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change var name e here to something... not one character long

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🆗

cwd (string): A path to execute commands from
error_message (string): Message to show if command fails
quiet (boolean): Whether to show command output or hide it
def run_command(cls, runner_args, **kwargs):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cls should be removed with refactor

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch

}
}

def teardown(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again not necessary


def test_generate_stream_alert(self):
"""CLI - Terraform Generate stream_alert Module"""
pass
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

where's the test bruh

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added a TODO


def test_generate_cluster_advanced(self):
"""CLI - Terraform Generate 'Advanced' Cluster"""
config = self.config
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

by reassigning to config here, you're essentially just creating a pointer to the self.config object anyway. omit this and just pass config=self.config in the generate_cluster call. the self.config is re-created in setup with each new method test anyway.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah it was just left in after a replace, I know how pointers work ;)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JUST CHECKIN

def test_generate_main(self):
"""CLI - Terraform Generate Main"""
init = False
config = self.config
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.


def test_generate_cluster_test(self):
"""CLI - Terraform Generate 'Test' Cluster"""
config = self.config
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import base64
import json

from nose.tools import assert_equal, assert_not_equal
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

assert_not_equal is unused here

'id': 'test',
'modules': {
'cloudwatch_monitoring': {
'enabled': True
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Weird indentation on this line.

'id': 'advanced',
'modules': {
'cloudwatch_monitoring': {
'enabled': True
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another weird indentation here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0_0

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's not weird, it's alt-proper

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alt facts

Copy link
Contributor

@ryandeivert ryandeivert left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A few more comments

default_error_message = "An error occurred while running: {}".format(
' '.join(runner_args)
)
error_message = kwargs.get('error_message', default_error_message)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like error_message is unused :hmm:

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this little fella is still hangin around

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's being used now.. check below


elif service == 'kinesis':
if compress:
kinesis_data = base64.b64encode(zlib.compress(data))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

zlib import is missing here


if service == 's3':
# Set the S3 object key to a random value for testing
test_record['key'] = ('{:032X}'.format(random.randrange(16**32)))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

import random is missing after migrating this function to helpers

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting, when testing it locally, it must have never made it into this if body

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually just checked to see why this passed integration tests - none of the rules we have in the integration tests are configured with "service": "s3". There are also none from kinesis configured to use compress, so that's also why that's not failing.

We should either add more encompassing integration tests or we should (need to) add cli unit tests that would have caught this.

@@ -306,77 +305,6 @@ def test_rule(rule_name, test_record, formatted_record):

return alerts, expected_alert_count

@staticmethod
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remember to remove zlib and random from imports in this file now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to pylint the whole cli module


account = config['global']['account']
prefix = account['prefix']
logging_bucket = '{}.streamalert.s3-logging'.format(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prefix, logging_bucket, & account_id are unused variables

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"""
logging_bucket = '{}.streamalert.s3-logging'.format(
config['global']['account']['prefix'])
firehose_suffix = config['clusters'][cluster_name]['modules']['kinesis']['firehose']['s3_bucket_suffix']
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

V long line. make this something like:

firehose_suffix = config['clusters'][cluster_name]['modules'] \ 
    ['kinesis']['firehose']['s3_bucket_suffix']

There are a few others like this pylint picks up.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

conf_logs.write('test logs string that will throw an error')
with open('conf/sources.json', 'w') as conf_sources:
conf_sources.write('test sources string that will throw an error')
config = load_config()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can just call the load_config here and not assign to variable since it's unused.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good point

@jacknagz
Copy link
Contributor Author

PTAL @ryandeivert

@coveralls
Copy link

coveralls commented Jun 20, 2017

Coverage Status

Coverage increased (+0.8%) to 79.32% when pulling aba4870 on jacknaglieri-s3-events-json-clusters into 8f086dd on master.

except subprocess.CalledProcessError as e:
LOGGER_CLI.error('Return Code %s - %s', e.returncode, e.cmd)
except subprocess.CalledProcessError as err:
LOGGER_CLI.error('%s\n%s', error_message)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why are there two %s format strings in this logging message but only one arg?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nm looks like this got changed in the next commit.

kms_client = boto3.client('kms', region_name=region)
response = kms_client.encrypt(KeyId=alias,
Plaintext=data)

return response['CiphertextBlob']


def _make_lambda_package():
def make_lambda_package():
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one isn't used outside of this helper file (not imported elsewhere) and could be kept private. It's only used by the create_lambda_function function.

default_error_message = "An error occurred while running: {}".format(
' '.join(runner_args)
)
error_message = kwargs.get('error_message', default_error_message)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this little fella is still hangin around

@ryandeivert
Copy link
Contributor

@jacknagz some comments

@jacknagz jacknagz force-pushed the jacknaglieri-s3-events-json-clusters branch from aba4870 to 32326a4 Compare June 20, 2017 21:53
@jacknagz
Copy link
Contributor Author

again, PTAL @ryandeivert

@airbnb airbnb deleted a comment from coveralls Jun 20, 2017
@coveralls
Copy link

Coverage Status

Coverage increased (+0.8%) to 79.32% when pulling 9482faa on jacknaglieri-s3-events-json-clusters into 5ec5109 on master.

@jacknagz jacknagz merged commit d203bbf into master Jun 20, 2017
@jacknagz jacknagz deleted the jacknaglieri-s3-events-json-clusters branch June 20, 2017 22:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants