Skip to content

Commit

Permalink
Merge pull request #70 from bonclay7/python3-support
Browse files Browse the repository at this point in the history
Python3 support
  • Loading branch information
bonclay7 committed Feb 4, 2018
2 parents e52a820 + 52e8099 commit 7580207
Show file tree
Hide file tree
Showing 10 changed files with 81 additions and 77 deletions.
31 changes: 1 addition & 30 deletions .gitignore
Expand Up @@ -38,48 +38,19 @@ pip-delete-this-directory.txt
htmlcov/
.tox/
.coverage
.coverage.*
.cache
.pytest_cache
nosetests.xml
coverage.xml
*,cover
.hypothesis/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py

# Flask instance folder
instance/

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
target/

# IPython Notebook
.ipynb_checkpoints

# pyenv
.python-version

# celery beat schedule file
celerybeat-schedule

# dotenv
.env

# Spyder project settings
.spyderproject

# Vagrant
Vagrantfile
.vagrant/
7 changes: 5 additions & 2 deletions .travis.yml
Expand Up @@ -4,13 +4,16 @@ env:

dist: trusty
language: python
python: "2.7"
python:
- "3.4"
- "3.5"
- "3.6"

install:
- pip install -r requirements_build.txt

script:
- py.test
- py.test -v

after_success:
- codecov
13 changes: 13 additions & 0 deletions Dockerfile-python3
@@ -0,0 +1,13 @@
FROM python:3.6

RUN apt-get update && apt-get install -y \
vim \
jq

WORKDIR /aws-amicleaner

ADD . .

RUN python setup.py install

CMD bash
46 changes: 25 additions & 21 deletions amicleaner/cli.py
@@ -1,17 +1,21 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import print_function
from __future__ import absolute_import
from builtins import input
from builtins import object
import sys

from amicleaner import __version__
from core import AMICleaner, OrphanSnapshotCleaner
from fetch import Fetcher
from resources.config import MAPPING_KEY, MAPPING_VALUES
from resources.config import TERM
from utils import Printer, parse_args
from .core import AMICleaner, OrphanSnapshotCleaner
from .fetch import Fetcher
from .resources.config import MAPPING_KEY, MAPPING_VALUES
from .resources.config import TERM
from .utils import Printer, parse_args


class App:
class App(object):

def __init__(self, args):

Expand Down Expand Up @@ -48,7 +52,7 @@ def fetch_candidates(self, available_amis=None, excluded_amis=None):

candidates = [v
for k, v
in available_amis.iteritems()
in available_amis.items()
if k not in excluded_amis]
return candidates

Expand All @@ -74,7 +78,7 @@ def prepare_candidates(self, candidates_amis=None):
candidates = []
report = dict()

for group_name, amis in mapped_amis.iteritems():
for group_name, amis in mapped_amis.items():
group_name = group_name or ""

if not group_name:
Expand All @@ -96,16 +100,16 @@ def prepare_delete_amis(self, candidates, from_ids=False):
failed = []

if from_ids:
print TERM.bold("\nCleaning from {} AMI id(s) ...".format(
print(TERM.bold("\nCleaning from {} AMI id(s) ...".format(
len(candidates))
)
))
failed = AMICleaner().remove_amis_from_ids(candidates)
else:
print TERM.bold("\nCleaning {} AMIs ...".format(len(candidates)))
print(TERM.bold("\nCleaning {} AMIs ...".format(len(candidates))))
failed = AMICleaner().remove_amis(candidates)

if failed:
print TERM.red("\n{0} failed snapshots".format(len(failed)))
print(TERM.red("\n{0} failed snapshots".format(len(failed))))
Printer.print_failed_snapshots(failed)

def clean_orphans(self):
Expand All @@ -120,22 +124,22 @@ def clean_orphans(self):

Printer.print_orphan_snapshots(snaps)

answer = raw_input(
answer = input(
"Do you want to continue and remove {} orphan snapshots "
"[y/N] ? : ".format(len(snaps)))
confirm = (answer.lower() == "y")

if confirm:
print "Removing orphan snapshots... "
print("Removing orphan snapshots... ")
count = cleaner.clean(snaps)
print "\n{0} orphan snapshots successfully removed !".format(count)
print("\n{0} orphan snapshots successfully removed !".format(count))

def print_defaults(self):

print TERM.bold("\nDefault values : ==>")
print TERM.green("mapping_key : {0}".format(self.mapping_key))
print TERM.green("mapping_values : {0}".format(self.mapping_values))
print TERM.green("keep_previous : {0}".format(self.keep_previous))
print(TERM.bold("\nDefault values : ==>"))
print(TERM.green("mapping_key : {0}".format(self.mapping_key)))
print(TERM.green("mapping_values : {0}".format(self.mapping_values)))
print(TERM.green("keep_previous : {0}".format(self.keep_previous)))

@staticmethod
def print_version():
Expand All @@ -152,7 +156,7 @@ def run_cli(self):
# print defaults
self.print_defaults()

print TERM.bold("\nRetrieving AMIs to clean ...")
print(TERM.bold("\nRetrieving AMIs to clean ..."))
candidates = self.prepare_candidates()

if not candidates:
Expand All @@ -161,7 +165,7 @@ def run_cli(self):
delete = False

if not self.force_delete:
answer = raw_input(
answer = input(
"Do you want to continue and remove {} AMIs "
"[y/N] ? : ".format(len(candidates)))
delete = (answer.lower() == "y")
Expand Down
15 changes: 9 additions & 6 deletions amicleaner/core.py
@@ -1,12 +1,15 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import print_function
from __future__ import absolute_import
from builtins import object
import boto3
from botocore.exceptions import ClientError
from resources.models import AMI
from .resources.models import AMI


class OrphanSnapshotCleaner:
class OrphanSnapshotCleaner(object):

""" Finds and removes ebs snapshots left orphaned """

Expand Down Expand Up @@ -82,10 +85,10 @@ def clean(self, snapshots):
return count

def log(self, msg):
print msg
print(msg)


class AMICleaner:
class AMICleaner(object):

def __init__(self, ec2=None):
self.ec2 = ec2 or boto3.client('ec2')
Expand All @@ -109,15 +112,15 @@ def remove_amis(self, amis):
amis = amis or []
for ami in amis:
self.ec2.deregister_image(ImageId=ami.id)
print "{0} deregistered".format(ami.id)
print("{0} deregistered".format(ami.id))
for block_device in ami.block_device_mappings:
try:
self.ec2.delete_snapshot(
SnapshotId=block_device.snapshot_id
)
except ClientError:
failed_snapshots.append(block_device.snapshot_id)
print "{0} deleted\n".format(block_device.snapshot_id)
print("{0} deleted\n".format(block_device.snapshot_id))

return failed_snapshots

Expand Down
6 changes: 4 additions & 2 deletions amicleaner/fetch.py
@@ -1,11 +1,13 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import absolute_import
from builtins import object
import boto3
from resources.models import AMI
from .resources.models import AMI


class Fetcher:
class Fetcher(object):

""" Fetches function for AMI candidates to deletion """

Expand Down
14 changes: 9 additions & 5 deletions amicleaner/resources/models.py
Expand Up @@ -2,7 +2,11 @@
# -*- coding: utf-8 -*-


class AMI:
from builtins import str
from builtins import object


class AMI(object):
def __init__(self):
self.id = None
self.architecture = None
Expand Down Expand Up @@ -52,7 +56,7 @@ def object_with_json(json):
AWSBlockDevice.object_with_json(block_device) for block_device
in json.get('BlockDeviceMappings', [])
]
o.block_device_mappings = filter(None, ebs_snapshots)
o.block_device_mappings = [f for f in ebs_snapshots if f]

return o

Expand All @@ -62,7 +66,7 @@ def __repr__(self):
self.creation_date)


class AWSEC2Instance:
class AWSEC2Instance(object):
def __init__(self):
self.id = None
self.name = None
Expand Down Expand Up @@ -110,7 +114,7 @@ def object_with_json(json):
return o


class AWSBlockDevice:
class AWSBlockDevice(object):
def __init__(self):
self.device_name = None
self.snapshot_id = None
Expand Down Expand Up @@ -146,7 +150,7 @@ def object_with_json(json):
return o


class AWSTag:
class AWSTag(object):
def __init__(self):
self.key = None
self.value = None
Expand Down
23 changes: 13 additions & 10 deletions amicleaner/utils.py
@@ -1,14 +1,17 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import print_function
from __future__ import absolute_import
from builtins import object
import argparse

from prettytable import PrettyTable

from resources.config import KEEP_PREVIOUS
from .resources.config import KEEP_PREVIOUS


class Printer:
class Printer(object):

""" Pretty table prints methods """
@staticmethod
Expand All @@ -21,7 +24,7 @@ def print_report(candidates, full_report=False):

groups_table = PrettyTable(["Group name", "candidates"])

for group_name, amis in candidates.iteritems():
for group_name, amis in candidates.items():
groups_table.add_row([group_name, len(amis)])
eligible_amis_table = PrettyTable(
["AMI ID", "AMI Name", "Creation Date"]
Expand All @@ -33,11 +36,11 @@ def print_report(candidates, full_report=False):
ami.creation_date
])
if full_report:
print group_name
print eligible_amis_table.get_string(sortby="AMI Name"), "\n\n"
print(group_name)
print(eligible_amis_table.get_string(sortby="AMI Name"), "\n\n")

print "\nAMIs to be removed:"
print groups_table.get_string(sortby="Group name")
print("\nAMIs to be removed:")
print(groups_table.get_string(sortby="Group name"))

@staticmethod
def print_failed_snapshots(snapshots):
Expand All @@ -46,7 +49,7 @@ def print_failed_snapshots(snapshots):

for snap in snapshots:
snap_table.add_row([snap])
print snap_table
print(snap_table)

@staticmethod
def print_orphan_snapshots(snapshots):
Expand All @@ -55,7 +58,7 @@ def print_orphan_snapshots(snapshots):

for snap in snapshots:
snap_table.add_row([snap])
print snap_table
print(snap_table)


def parse_args(args):
Expand Down Expand Up @@ -106,7 +109,7 @@ def parse_args(args):

parsed_args = parser.parse_args(args)
if parsed_args.mapping_key and not parsed_args.mapping_values:
print "missing mapping-values\n"
print("missing mapping-values\n")
parser.print_help()
return None

Expand Down
1 change: 1 addition & 0 deletions pytest.ini
@@ -1,3 +1,4 @@
[pytest]
rootdir = tests
addopts = --cov-report html --cov-fail-under 80 --cov . --pep8
pep8maxlinelength = 120
2 changes: 1 addition & 1 deletion tests/test_cli.py
Expand Up @@ -41,7 +41,7 @@ def test_deletion():

# create amis
images = []
for i in xrange(5):
for i in range(5):
image = ec2.create_image(
InstanceId=instance.get("InstanceId"),
Name="test-ami"
Expand Down

0 comments on commit 7580207

Please sign in to comment.