1from __future__ import print_function
2import os
3import urlparse
4import boto
5import boto.connection
6import boto.jsonresponse
7import boto.exception
8from boto.roboto import awsqueryrequest
9
10class NoCredentialsError(boto.exception.BotoClientError):
11
12    def __init__(self):
13        s = 'Unable to find credentials'
14        super(NoCredentialsError, self).__init__(s)
15
16class AWSQueryService(boto.connection.AWSQueryConnection):
17
18    Name = ''
19    Description = ''
20    APIVersion = ''
21    Authentication = 'sign-v2'
22    Path = '/'
23    Port = 443
24    Provider = 'aws'
25    EnvURL = 'AWS_URL'
26
27    Regions = []
28
29    def __init__(self, **args):
30        self.args = args
31        self.check_for_credential_file()
32        self.check_for_env_url()
33        if 'host' not in self.args:
34            if self.Regions:
35                region_name = self.args.get('region_name',
36                                            self.Regions[0]['name'])
37                for region in self.Regions:
38                    if region['name'] == region_name:
39                        self.args['host'] = region['endpoint']
40        if 'path' not in self.args:
41            self.args['path'] = self.Path
42        if 'port' not in self.args:
43            self.args['port'] = self.Port
44        try:
45            super(AWSQueryService, self).__init__(**self.args)
46            self.aws_response = None
47        except boto.exception.NoAuthHandlerFound:
48            raise NoCredentialsError()
49
50    def check_for_credential_file(self):
51        """
52        Checks for the existence of an AWS credential file.
53        If the environment variable AWS_CREDENTIAL_FILE is
54        set and points to a file, that file will be read and
55        will be searched credentials.
56        Note that if credentials have been explicitelypassed
57        into the class constructor, those values always take
58        precedence.
59        """
60        if 'AWS_CREDENTIAL_FILE' in os.environ:
61            path = os.environ['AWS_CREDENTIAL_FILE']
62            path = os.path.expanduser(path)
63            path = os.path.expandvars(path)
64            if os.path.isfile(path):
65                fp = open(path)
66                lines = fp.readlines()
67                fp.close()
68                for line in lines:
69                    if line[0] != '#':
70                        if '=' in line:
71                            name, value = line.split('=', 1)
72                            if name.strip() == 'AWSAccessKeyId':
73                                if 'aws_access_key_id' not in self.args:
74                                    value = value.strip()
75                                    self.args['aws_access_key_id'] = value
76                            elif name.strip() == 'AWSSecretKey':
77                                if 'aws_secret_access_key' not in self.args:
78                                    value = value.strip()
79                                    self.args['aws_secret_access_key'] = value
80            else:
81                print('Warning: unable to read AWS_CREDENTIAL_FILE')
82
83    def check_for_env_url(self):
84        """
85        First checks to see if a url argument was explicitly passed
86        in.  If so, that will be used.  If not, it checks for the
87        existence of the environment variable specified in ENV_URL.
88        If this is set, it should contain a fully qualified URL to the
89        service you want to use.
90        Note that any values passed explicitly to the class constructor
91        will take precedence.
92        """
93        url = self.args.get('url', None)
94        if url:
95            del self.args['url']
96        if not url and self.EnvURL in os.environ:
97            url = os.environ[self.EnvURL]
98        if url:
99            rslt = urlparse.urlparse(url)
100            if 'is_secure' not in self.args:
101                if rslt.scheme == 'https':
102                    self.args['is_secure'] = True
103                else:
104                    self.args['is_secure'] = False
105
106            host = rslt.netloc
107            port = None
108            l = host.split(':')
109            if len(l) > 1:
110                host = l[0]
111                port = int(l[1])
112            if 'host' not in self.args:
113                self.args['host'] = host
114            if port and 'port' not in self.args:
115                self.args['port'] = port
116
117            if rslt.path and 'path' not in self.args:
118                self.args['path'] = rslt.path
119
120    def _required_auth_capability(self):
121        return [self.Authentication]
122
123