Hello community, here is the log from the commit of package python3-ec2utilsbase for openSUSE:Factory checked in at 2018-02-06 16:49:27 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python3-ec2utilsbase (Old) and /work/SRC/openSUSE:Factory/.python3-ec2utilsbase.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python3-ec2utilsbase" Tue Feb 6 16:49:27 2018 rev:2 rq:573154 version:3.1.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python3-ec2utilsbase/python3-ec2utilsbase.changes 2017-08-24 18:49:40.928372590 +0200 +++ /work/SRC/openSUSE:Factory/.python3-ec2utilsbase.new/python3-ec2utilsbase.changes 2018-02-06 16:49:29.419124587 +0100 @@ -1,0 +2,7 @@ +Mon Feb 5 21:09:32 UTC 2018 - rjsch...@suse.com + +- Update to version 3.1.0 + + Add utilities to create artifacs in EC2 needed to prepare a + given account for image uploading + +------------------------------------------------------------------- Old: ---- ec2utilsbase-3.0.0.tar.bz2 New: ---- ec2utilsbase-3.1.0.tar.bz2 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python3-ec2utilsbase.spec ++++++ --- /var/tmp/diff_new_pack.6zXcVt/_old 2018-02-06 16:49:29.995097637 +0100 +++ /var/tmp/diff_new_pack.6zXcVt/_new 2018-02-06 16:49:29.999097449 +0100 @@ -1,7 +1,7 @@ # -# spec file for package python-ec2utilsbase +# spec file for package python3-ec2utilsbase # -# Copyright (c) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany. +# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ %define upstream_name ec2utilsbase Name: python3-ec2utilsbase -Version: 3.0.0 +Version: 3.1.0 Release: 0 Summary: Shared EC2 utils functionality License: GPL-3.0+ @@ -49,7 +49,6 @@ %install python3 setup.py install --prefix=%{_prefix} --root=%{buildroot} - %files %defattr(-,root,root,-) %doc LICENSE ++++++ ec2utilsbase-3.0.0.tar.bz2 -> ec2utilsbase-3.1.0.tar.bz2 ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ec2utilsbase-3.0.0/lib/ec2utils/base_VERSION new/ec2utilsbase-3.1.0/lib/ec2utils/base_VERSION --- old/ec2utilsbase-3.0.0/lib/ec2utils/base_VERSION 2017-08-09 17:14:33.892070075 +0200 +++ new/ec2utilsbase-3.1.0/lib/ec2utils/base_VERSION 2018-02-05 22:06:54.356844102 +0100 @@ -1 +1 @@ -3.0.0 +3.1.0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ec2utilsbase-3.0.0/lib/ec2utils/ec2setup.py new/ec2utilsbase-3.1.0/lib/ec2utils/ec2setup.py --- old/ec2utilsbase-3.0.0/lib/ec2utils/ec2setup.py 1970-01-01 01:00:00.000000000 +0100 +++ new/ec2utilsbase-3.1.0/lib/ec2utils/ec2setup.py 2018-02-05 22:06:54.364843934 +0100 @@ -0,0 +1,222 @@ +# Copyright (c) 2018 SUSE LLC, Christian Bruckmayer <cbruckma...@suse.com> +# +# This file is part of ec2utilsbase. +# +# ec2utilsbase is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# ec2utilsbase is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with ec2utilsbase. If not, see <http://www.gnu.org/licenses/>. + +import boto3 +import os +import random +import datetime + +from ec2utils.ec2UtilsExceptions import EC2ConnectionException +from ec2utils.ec2utils import EC2Utils +from tempfile import mkstemp +from tempfile import mkdtemp + + +class EC2Setup(EC2Utils): + """Class to prepare an Amazon EC2 account with all necessary resources""" + + def __init__(self, access_key, region, secret_key, session_token, verbose): + EC2Utils.__init__(self) + self.access_key = access_key + self.region = region + self.secret_key = secret_key + self.session_token = session_token + self.verbose = verbose + + self.internet_gateway_id = '' + self.key_pair_name = '' + self.route_table_id = '' + self.security_group_id = '' + self.ssh_private_key_file = '' + self.temp_dir = '' + self.vpc_subnet_id = '' + self.vpc_id = '' + + # --------------------------------------------------------------------- + def clean_up(self): + if self.key_pair_name: + self._remove_upload_key_pair() + if self.security_group_id: + self._remove_security_group() + if self.vpc_id: + self._remove_vpc() + + # --------------------------------------------------------------------- + def create_security_group(self): + if self.verbose: + print('Creating temporary security group') + group_name = 'ec2uploadimg-%s' % (random.randint(1, 100)) + group_description = 'ec2uploadimg created %s' % datetime.datetime.now() + response = self._connect().create_security_group( + GroupName=group_name, Description=group_description, + VpcId=self.vpc_id + ) + + self.security_group_id = response['GroupId'] + if self.verbose: + print('Temporary Security Group Created %s in vpc %s' + % (self.security_group_id, self.vpc_id)) + data = self._connect().authorize_security_group_ingress( + GroupId=self.security_group_id, + IpPermissions=[ + {'IpProtocol': 'tcp', + 'FromPort': 22, + 'ToPort': 22, + 'IpRanges': [{'CidrIp': '0.0.0.0/0'}]} + ]) + + if self.verbose: + print("Successfully allowed incoming SSH port 22 for security " + "group %s in %s" % (self.security_group_id, self.vpc_id)) + return self.security_group_id + + # --------------------------------------------------------------------- + def create_upload_key_pair(self, key_name='temporary_ec2_uploadkey'): + if self.verbose: + print('Creating temporary key pair') + dir_path = os.path.expanduser('~/') + if not os.access(dir_path, os.W_OK): + dir_path = mkdtemp() + self.temp_dir = dir_path + fd, location = mkstemp(prefix='temporary_ec2_uploadkey.', + suffix='.key', dir=dir_path) + self.key_pair_name = os.path.basename(location) + self.ssh_private_key_file = location + secret_key_content = self._connect().create_key_pair( + KeyName=self.key_pair_name + ) + if self.verbose: + print('Successfully created key pair: ', self.key_pair_name) + with open(location, 'w') as localfile: + localfile.write(secret_key_content['KeyMaterial']) + if self.verbose: + print('Successfully wrote secret key key file to ', location) + os.close(fd) + return self.key_pair_name, self.ssh_private_key_file + + # --------------------------------------------------------------------- + def create_vpc_subnet(self): + self._create_vpc() + self._create_internet_gateway() + self._create_route_table() + self._create_vpc_subnet() + return self.vpc_subnet_id + + # --------------------------------------------------------------------- + def _create_internet_gateway(self): + response = self._connect().create_internet_gateway() + self.internet_gateway_id = \ + response['InternetGateway']['InternetGatewayId'] + self._connect().attach_internet_gateway( + VpcId=self.vpc_id, InternetGatewayId=self.internet_gateway_id + ) + if self.verbose: + print("Successfully created internet gateway %s" % + self.internet_gateway_id) + + # --------------------------------------------------------------------- + def _create_route_table(self): + response = self._connect().create_route_table(VpcId=self.vpc_id) + self.route_table_id = response['RouteTable']['RouteTableId'] + self._connect().create_route( + DestinationCidrBlock='0.0.0.0/0', + GatewayId=self.internet_gateway_id, + RouteTableId=self.route_table_id + ) + if self.verbose: + print("Successfully created route table %s" % self.route_table_id) + + # --------------------------------------------------------------------- + def _create_vpc(self): + vpc_name = 'uploader-%s' % (random.randint(1, 100)) + response = self._connect().create_vpc(CidrBlock='192.168.0.0/16') + self.vpc_id = response['Vpc']['VpcId'] + self._connect().create_tags( + Resources=[self.vpc_id], + Tags=[{'Key': 'Name', 'Value': vpc_name}] + ) + if self.verbose: + print("Successfully created VPC with id %s" % (self.vpc_id)) + + # --------------------------------------------------------------------- + def _create_vpc_subnet(self): + response = self._connect().create_subnet( + CidrBlock='192.168.1.0/24', VpcId=self.vpc_id + ) + self.vpc_subnet_id = response['Subnet']['SubnetId'] + self._connect().associate_route_table( + SubnetId=self.vpc_subnet_id, RouteTableId=self.route_table_id + ) + self._connect().modify_subnet_attribute( + MapPublicIpOnLaunch={'Value': True}, SubnetId=self.vpc_subnet_id + ) + if self.verbose: + print("Successfully created VPC subnet with id %s" % + self.vpc_subnet_id) + + # --------------------------------------------------------------------- + def _remove_security_group(self): + response = self._connect().delete_security_group( + GroupId=self.security_group_id + ) + if self.verbose: + print('Successfully deleted security group %s' % + self.security_group_id) + + # --------------------------------------------------------------------- + def _remove_upload_key_pair(self): + if self.verbose: + print('Deleting temporary key pair ', self.key_pair_name) + secret_key = self._connect().delete_key_pair( + KeyName=self.key_pair_name) + if os.path.isfile(self.ssh_private_key_file): + os.remove(self.ssh_private_key_file) + if self.temp_dir: + os.rmdir(self.temp_dir) + if self.verbose: + print('Successfully deleted temporary key', + self.ssh_private_key_file) + + # --------------------------------------------------------------------- + def _remove_vpc(self): + self._connect().delete_route( + DestinationCidrBlock='0.0.0.0/0', RouteTableId=self.route_table_id + ) + if self.verbose: + print('Successfully deleted route from route table %s' % + self.route_table_id) + self._connect().delete_subnet(SubnetId=self.vpc_subnet_id) + if self.verbose: + print('Successfully deleted VPC subnet %s' % self.vpc_subnet_id) + self._connect().delete_route_table(RouteTableId=self.route_table_id) + if self.verbose: + print('Successfully deleted route table %s' % self.route_table_id) + self._connect().detach_internet_gateway( + InternetGatewayId=self.internet_gateway_id, VpcId=self.vpc_id + ) + if self.verbose: + print('Successfully deleted detached internet gateway %s' % + self.internet_gateway_id) + self._connect().delete_internet_gateway( + InternetGatewayId=self.internet_gateway_id + ) + if self.verbose: + print('Successfully deleted internet gateway %s' % + self.internet_gateway_id) + self._connect().delete_vpc(VpcId=self.vpc_id) + if self.verbose: + print('Successfully deleted VPC %s' % self.vpc_id) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ec2utilsbase-3.0.0/lib/ec2utils/ec2utils.py new/ec2utilsbase-3.1.0/lib/ec2utils/ec2utils.py --- old/ec2utilsbase-3.0.0/lib/ec2utils/ec2utils.py 2017-08-09 17:14:33.892070075 +0200 +++ new/ec2utilsbase-3.1.0/lib/ec2utils/ec2utils.py 2018-02-05 22:06:54.352844187 +0100 @@ -1,4 +1,4 @@ -# Copyright (c) 2015 SUSE LLC, Robert Schweikert <rjsch...@suse.com> +# Copyright (c) 2017 SUSE LLC, Robert Schweikert <rjsch...@suse.com> # # This file is part of ec2utilsbase. # @@ -19,7 +19,7 @@ import configparser import os -from .ec2UtilsExceptions import * +from ec2utils.ec2UtilsExceptions import EC2ConnectionException class EC2Utils: @@ -36,12 +36,21 @@ ec2 = None if self.region: - ec2 = boto3.client( - aws_access_key_id=self.access_key, - aws_secret_access_key=self.secret_key, - region_name=self.region, - service_name='ec2' - ) + if self.session_token: + ec2 = boto3.client( + aws_access_key_id=self.access_key, + aws_secret_access_key=self.secret_key, + aws_session_token=self.session_token, + region_name=self.region, + service_name='ec2' + ) + else: + ec2 = boto3.client( + aws_access_key_id=self.access_key, + aws_secret_access_key=self.secret_key, + region_name=self.region, + service_name='ec2' + ) else: self.region = 'UNKNOWN' @@ -56,7 +65,7 @@ """Return the list of images owned by the account used for uploading""" return self._connect().describe_images(Owners=['self'])['Images'] - + # --------------------------------------------------------------------- def _set_access_keys(): """Set the access keys for the connection""" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ec2utilsbase-3.0.0/lib/ec2utils/ec2utilsutils.py new/ec2utilsbase-3.1.0/lib/ec2utils/ec2utilsutils.py --- old/ec2utilsbase-3.0.0/lib/ec2utils/ec2utilsutils.py 2017-08-09 17:14:33.892070075 +0200 +++ new/ec2utilsbase-3.1.0/lib/ec2utils/ec2utilsutils.py 2018-02-05 22:06:54.364843934 +0100 @@ -17,11 +17,15 @@ import boto3 import configparser -import os import re import sys -from ec2utils.ec2UtilsExceptions import * +from itertools import repeat + +from ec2utils.ec2UtilsExceptions import ( + EC2AccountException, + EC2ConfigFileParseException +) # ----------------------------------------------------------------------------- @@ -72,7 +76,7 @@ """Return a list of images that match the given name.""" matching_images = [] for image in images: - if not image['Name']: + if not image.get('Name'): print(_no_name_warning(image)) continue if image_name == image['Name']: @@ -87,7 +91,7 @@ of the image name.""" matching_images = [] for image in images: - if not image['Name']: + if not image.get('Name'): print(_no_name_warning(image)) continue if image['Name'].find(image_name_fragment) != -1: @@ -103,7 +107,7 @@ matching_images = [] image_name_exp = re.compile(image_name_regex) for image in images: - if not image['Name']: + if not image.get('Name'): print(_no_name_warning(image)) continue if image_name_exp.match(image['Name']): @@ -133,9 +137,9 @@ try: parsed = config.read(configFilePath) except: - msg = 'Could not parse configuration file %s' % configFilePath - type, value, tb = sys.exc_info() - msg += '\n%s' % value.message + msg = 'Could not parse configuration file "%s"\n' % configFilePath + e_type, value, tb = sys.exc_info() + msg += format(value) raise EC2ConfigFileParseException(msg) if not parsed: @@ -205,5 +209,13 @@ def _no_name_warning(image): """Print a warning for images that have no name""" msg = 'WARNING: Found image with no name, ignoring for search results. ' - msg += 'Image ID: %s' % image.id + msg += 'Image ID: %s' % image['ImageId'] print(msg) + + +# ---------------------------------------------------------------------------- +def validate_account_numbers(share_with): + accounts = list(filter(None, share_with.split(','))) + if accounts: + return all(map(re.match, repeat('^\d{12}$'), accounts)) + return False diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/ec2utilsbase-3.0.0/setup.py new/ec2utilsbase-3.1.0/setup.py --- old/ec2utilsbase-3.0.0/setup.py 2017-08-09 17:14:33.916069638 +0200 +++ new/ec2utilsbase-3.1.0/setup.py 2018-02-05 22:06:54.368843849 +0100 @@ -1,7 +1,7 @@ #!/usr/bin/env python """Setup module for ec2utilsbase""" -# Copyright (c) 2015 SUSE LLC, Robert Schweikert <rjsch...@suse.com> +# Copyright (c) 2017 SUSE LLC # # This file is part of ec2utilsbase. # @@ -33,15 +33,31 @@ name='ec2utilsbase', description=( 'Command-line tool to upload EC2 images'), - url='https://github.com/SUSE/Enceladus', - license='GPL-3.0+', - author='Robert Schweikert', - author_email='rjsch...@suse.com', + long_description=open('README.md').read(), + url='https://github.com/SUSE/Enceladus/tree/master/ec2utils', + license='GPLv3+', + install_requires=[ 'boto3>=1.3.0' ], + author='SUSE Public Cloud Team', + author_email='public-cloud-...@susecloud.net', version=version, packages=setuptools.find_packages('lib'), package_data={'ec2utils': ['base_VERSION']}, package_dir={ '': 'lib', }, - namespace_packages = ['ec2utils'] + namespace_packages = ['ec2utils'], + classifiers=[ + 'Development Status :: 5 - Production/Stable', + 'Intended Audience :: Developers', + 'Natural Language :: English', + 'License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)', + 'Programming Language :: Python', + 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', + 'Programming Language :: Python :: Implementation :: CPython', + 'Programming Language :: Python :: Implementation :: PyPy', + ] )