def test_routing_rules_key_prefix(self): x = pretty_print_xml # This rule redirects requests for docs/* to documentation/* rules = RoutingRules() condition = Condition(key_prefix='docs/') redirect = Redirect(replace_key_prefix='documents/') rules.add_rule(RoutingRule(condition, redirect)) config = WebsiteConfiguration(suffix='index.html', routing_rules=rules) xml = config.to_xml() expected_xml = """<?xml version="1.0" encoding="UTF-8"?> <WebsiteConfiguration xmlns='http://s3.amazonaws.com/doc/2006-03-01/'> <IndexDocument> <Suffix>index.html</Suffix> </IndexDocument> <RoutingRules> <RoutingRule> <Condition> <KeyPrefixEquals>docs/</KeyPrefixEquals> </Condition> <Redirect> <ReplaceKeyPrefixWith>documents/</ReplaceKeyPrefixWith> </Redirect> </RoutingRule> </RoutingRules> </WebsiteConfiguration> """ self.assertEqual(x(expected_xml), x(xml))
def test_routing_rules_to_host_on_404(self): x = pretty_print_xml # Another example from the docs: # Redirect requests to a specific host in the event of a 404. # Also, the redirect inserts a report-404/. For example, # if you request a page ExamplePage.html and it results # in a 404, the request is routed to a page report-404/ExamplePage.html rules = RoutingRules() condition = Condition(http_error_code=404) redirect = Redirect(hostname='example.com', replace_key_prefix='report-404/') rules.add_rule(RoutingRule(condition, redirect)) config = WebsiteConfiguration(suffix='index.html', routing_rules=rules) xml = config.to_xml() expected_xml = """<?xml version="1.0" encoding="UTF-8"?> <WebsiteConfiguration xmlns='http://s3.amazonaws.com/doc/2006-03-01/'> <IndexDocument> <Suffix>index.html</Suffix> </IndexDocument> <RoutingRules> <RoutingRule> <Condition> <HttpErrorCodeReturnedEquals>404</HttpErrorCodeReturnedEquals> </Condition> <Redirect> <HostName>example.com</HostName> <ReplaceKeyPrefixWith>report-404/</ReplaceKeyPrefixWith> </Redirect> </RoutingRule> </RoutingRules> </WebsiteConfiguration> """ self.assertEqual(x(expected_xml), x(xml))
def test_builders(self): x = pretty_print_xml # This is a more declarative way to create rules. # First the long way. rules = RoutingRules() condition = Condition(http_error_code=404) redirect = Redirect(hostname='example.com', replace_key_prefix='report-404/') rules.add_rule(RoutingRule(condition, redirect)) xml = rules.to_xml() # Then the more concise way. rules2 = RoutingRules().add_rule( RoutingRule.when(http_error_code=404).then_redirect( hostname='example.com', replace_key_prefix='report-404/')) xml2 = rules2.to_xml() self.assertEqual(x(xml), x(xml2))
def parse_routing_rules(routing_config, hostname): """ Parse routing rule description. The configuration is a dictionary. The top-level keys are common prefixes for the rules in them. Each top-level key maps to a dictionary that maps the rest of a prefix to the redirection target. A redirection target is a dictionary of keyword arguments to ``boto.s3.website.Redirect``. If no hostname is provided in the redirection target, then the passed hostname is used, and the common prefix is prepended to the redirection target. :param routing_config: ``dict`` containing the routing configuration. :param bytes hostname: The hostname the bucket is hosted at. :return: Parsed routing rules. :rtype: ``boto.s3.website.RoutingRules`` """ rules = [] for prefix, relative_redirects in routing_config.items(): for postfix, destination in relative_redirects.items(): destination.setdefault('http_redirect_code', '302') destination['protocol'] = 'https' if 'hostname' not in destination.keys(): destination['hostname'] = hostname for key in ('replace_key', 'replace_key_prefix'): if key in destination: destination[key] = prefix + destination[key] rules.append(RoutingRule.when( key_prefix=prefix+postfix, ).then_redirect(**destination)) # Sort the rules in reverse order of prefix to match, so that # long-match wins. return RoutingRules( sorted(rules, key=lambda rule: rule.condition.key_prefix, reverse=True) )
# Check bucket exists try: bucket = connection.get_bucket(name) except S3ResponseError, e: module.fail_json(msg=e.message) # Check bucket is configured as website try: website_config = bucket.get_website_configuration_obj() except S3ResponseError, e: module.fail_json(msg=e.message) current_redirect_rules = website_config.routing_rules # Create routing rules object routing_rules_obj = RoutingRules() # Create redirect rule rule = RoutingRule.when(key_prefix=key_prefix, http_error_code=http_error_code).then_redirect(hostname, protocol, replace_key_with, replace_key_prefix_with, http_redirect_code) appended = False for existing_rule in current_redirect_rules: # Match based on http_error_code and prefix if rule.condition.http_error_code == existing_rule.condition.http_error_code and rule.condition.key_prefix == existing_rule.condition.key_prefix: if rule.to_xml() == existing_rule.to_xml(): # append the already existing rule (no change) routing_rules_obj.add_rule(rule) appended = True else: # replace the existing rule routing_rules_obj.add_rule(rule)
def site_config(self, site): with hook('site config %s' % self.name, self, site): setup_aws_access_key(site) from boto import connect_s3 from boto.s3.bucket import Bucket from boto.s3.key import Key for bucket_config in self.settings['buckets']: # Connect and make sure the bucket exists print bold(u'Configuring bucket %s...' % bucket_config['name']) connection = connect_s3() try: bucket = connection.get_bucket(bucket_config['name']) except: bucket = connection.create_bucket(bucket_config['name']) # Set the bucket policy if bucket_config.has_key('policy'): bucket.set_policy(bucket_config['policy']) # Setup CORS, array of rules # http://boto.readthedocs.org/en/latest/ref/s3.html#boto.s3.cors.CORSConfiguration if bucket_config.has_key( 'cors') and bucket_config['cors'] is None: # If explicity set to None, then remove the cors policy bucket.delete_cors() else: if not bucket_config.has_key('cors'): # If not specified, use the default GET policy bucket_config['cors'] = (DEFAULT_CORS_RULE, ) from boto.s3.cors import CORSConfiguration cors_config = CORSConfiguration() for rule in bucket_config['cors']: cors_config.add_rule(**rule) bucket.set_cors(cors_config) # Setup the lifecycle, array of rules # http://boto.readthedocs.org/en/latest/ref/s3.html#boto.s3.lifecycle.Lifecycle if bucket_config.has_key('lifecycle'): from boto.s3.lifecycle import Lifecycle lifecycle_config = Lifecycle() for rule in bucket_config['lifecycle']: lifecycle_config.add_rule(**rule) bucket.configure_lifecycle(lifecycle_config) else: bucket.delete_lifecycle_configuration() # Setup the bucket website hosting {suffix, error_key, routing_rules, redirect_all_requests_to} # http://boto.readthedocs.org/en/latest/ref/s3.html # https://github.com/boto/boto/blob/develop/boto/s3/website.py if bucket_config.has_key('website'): # Expand the routing rules, array of {condition, redirect} if bucket_config['website'].has_key('routing_rules'): from boto.s3.website import RoutingRules, RoutingRule routing_rules = RoutingRules() for rule in bucket_config['website']['routing_rules']: routing_rules.add_rule(RoutingRule(**rule)) bucket_config['website'][ 'routing_rules'] = routing_rules # Expand the redirect, redirect_all_requests_to is {hostname, protocol} if bucket_config['website'].has_key( 'redirect_all_requests_to'): from boto.s3.website import RedirectLocation bucket_config['website'][ 'redirect_all_requests_to'] = RedirectLocation( **bucket_config['website'] ['redirect_all_requests_to']) bucket.configure_website(**bucket_config['website']) else: bucket.delete_website_configuration()