From 1ec210867ec36c49ca903eeffd99bc59fb05f11b Mon Sep 17 00:00:00 2001
From: aviau <aviau@debian.org>
Date: Tue, 10 Jul 2018 18:17:42 -0400
Subject: [PATCH] New upstream version 5.2.0

---
 PKG-INFO                                      |  9 +-
 README.rst                                    |  7 +-
 influxdb.egg-info/PKG-INFO                    |  9 +-
 influxdb/__init__.py                          |  2 +-
 influxdb/_dataframe_client.py                 | 16 ++--
 influxdb/client.py                            | 76 ++++++++++-----
 influxdb/tests/client_test.py                 | 61 +++++++++---
 .../server_tests/client_test_with_server.py   | 94 ++++++++++++++++++-
 .../tests/server_tests/influxdb_instance.py   |  6 +-
 9 files changed, 211 insertions(+), 69 deletions(-)

diff --git a/PKG-INFO b/PKG-INFO
index 263583d..bf00696 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: influxdb
-Version: 5.1.0
+Version: 5.2.0
 Summary: InfluxDB client
 Home-page: https://github.com/influxdb/influxdb-python
 Author: UNKNOWN
@@ -47,8 +47,7 @@ Description: InfluxDB-Python
         InfluxDB pre v1.1.0 users
         -------------------------
         
-        This module is tested with InfluxDB v1.2.4, our recommended version. Though there have been v1.3 (initial TSI branch) and v1.4 releases these are not 
-        yet supported. 
+        This module is tested with InfluxDB versions: v1.2.4, v1.3.9, v1.4.2, and v1.5.4.
         
         Those users still on InfluxDB v0.8.x users may still use the legacy client by importing ``from influxdb.influxdb08 import InfluxDBClient``.
         
@@ -68,9 +67,9 @@ Description: InfluxDB-Python
         Dependencies
         ------------
         
-        The influxdb-python distribution is supported and tested on Python 2.7, 3.3, 3.4, 3.5, 3.6, PyPy and PyPy3.
+        The influxdb-python distribution is supported and tested on Python 2.7, 3.5, 3.6, PyPy and PyPy3.
         
-        **Note:** Python 3.2 is currently untested. See ``.travis.yml``.
+        **Note:** Python <3.5 are currently untested. See ``.travis.yml``.
         
         Main dependency is:
         
diff --git a/README.rst b/README.rst
index c145cfc..d4f9611 100644
--- a/README.rst
+++ b/README.rst
@@ -39,8 +39,7 @@ InfluxDB is an open-source distributed time series database, find more about Inf
 InfluxDB pre v1.1.0 users
 -------------------------
 
-This module is tested with InfluxDB v1.2.4, our recommended version. Though there have been v1.3 (initial TSI branch) and v1.4 releases these are not 
-yet supported. 
+This module is tested with InfluxDB versions: v1.2.4, v1.3.9, v1.4.2, and v1.5.4.
 
 Those users still on InfluxDB v0.8.x users may still use the legacy client by importing ``from influxdb.influxdb08 import InfluxDBClient``.
 
@@ -60,9 +59,9 @@ On Debian/Ubuntu, you can install it with this command::
 Dependencies
 ------------
 
-The influxdb-python distribution is supported and tested on Python 2.7, 3.3, 3.4, 3.5, 3.6, PyPy and PyPy3.
+The influxdb-python distribution is supported and tested on Python 2.7, 3.5, 3.6, PyPy and PyPy3.
 
-**Note:** Python 3.2 is currently untested. See ``.travis.yml``.
+**Note:** Python <3.5 are currently untested. See ``.travis.yml``.
 
 Main dependency is:
 
diff --git a/influxdb.egg-info/PKG-INFO b/influxdb.egg-info/PKG-INFO
index 263583d..bf00696 100644
--- a/influxdb.egg-info/PKG-INFO
+++ b/influxdb.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: influxdb
-Version: 5.1.0
+Version: 5.2.0
 Summary: InfluxDB client
 Home-page: https://github.com/influxdb/influxdb-python
 Author: UNKNOWN
@@ -47,8 +47,7 @@ Description: InfluxDB-Python
         InfluxDB pre v1.1.0 users
         -------------------------
         
-        This module is tested with InfluxDB v1.2.4, our recommended version. Though there have been v1.3 (initial TSI branch) and v1.4 releases these are not 
-        yet supported. 
+        This module is tested with InfluxDB versions: v1.2.4, v1.3.9, v1.4.2, and v1.5.4.
         
         Those users still on InfluxDB v0.8.x users may still use the legacy client by importing ``from influxdb.influxdb08 import InfluxDBClient``.
         
@@ -68,9 +67,9 @@ Description: InfluxDB-Python
         Dependencies
         ------------
         
-        The influxdb-python distribution is supported and tested on Python 2.7, 3.3, 3.4, 3.5, 3.6, PyPy and PyPy3.
+        The influxdb-python distribution is supported and tested on Python 2.7, 3.5, 3.6, PyPy and PyPy3.
         
-        **Note:** Python 3.2 is currently untested. See ``.travis.yml``.
+        **Note:** Python <3.5 are currently untested. See ``.travis.yml``.
         
         Main dependency is:
         
diff --git a/influxdb/__init__.py b/influxdb/__init__.py
index 374fddc..03f7458 100644
--- a/influxdb/__init__.py
+++ b/influxdb/__init__.py
@@ -18,4 +18,4 @@ __all__ = [
 ]
 
 
-__version__ = '5.1.0'
+__version__ = '5.2.0'
diff --git a/influxdb/_dataframe_client.py b/influxdb/_dataframe_client.py
index 4273ef1..646f298 100644
--- a/influxdb/_dataframe_client.py
+++ b/influxdb/_dataframe_client.py
@@ -365,16 +365,18 @@ class DataFrameClient(InfluxDBClient):
 
         # Make an array of formatted field keys and values
         field_df = dataframe[field_columns]
+        # Keep the positions where Null values are found
+        mask_null = field_df.isnull().values
 
         field_df = self._stringify_dataframe(field_df,
                                              numeric_precision,
                                              datatype='field')
 
-        def format_line(line):
-            line = line[~line.isnull()]  # drop None entries
-            return ",".join((line.index + '=' + line.values))
-
-        fields = field_df.apply(format_line, axis=1)
+        field_df = (field_df.columns.values + '=').tolist() + field_df
+        field_df[field_df.columns[1:]] = ',' + field_df[
+            field_df.columns[1:]]
+        field_df = field_df.where(~mask_null, '')  # drop Null entries
+        fields = field_df.sum(axis=1)
         del field_df
 
         # Generate line protocol string
@@ -388,9 +390,6 @@ class DataFrameClient(InfluxDBClient):
         # Prevent modification of input dataframe
         dframe = dframe.copy()
 
-        # Keep the positions where Null values are found
-        mask_null = dframe.isnull().values
-
         # Find int and string columns for field-type data
         int_columns = dframe.select_dtypes(include=['integer']).columns
         string_columns = dframe.select_dtypes(include=['object']).columns
@@ -435,7 +434,6 @@ class DataFrameClient(InfluxDBClient):
 
         dframe.columns = dframe.columns.astype(str)
 
-        dframe = dframe.where(~mask_null, None)
         return dframe
 
     def _datetime_to_epoch(self, datetime, time_precision='s'):
diff --git a/influxdb/client.py b/influxdb/client.py
index 62d5a02..8f8b14a 100644
--- a/influxdb/client.py
+++ b/influxdb/client.py
@@ -350,7 +350,8 @@ class InfluxDBClient(object):
               database=None,
               raise_errors=True,
               chunked=False,
-              chunk_size=0):
+              chunk_size=0,
+              method="GET"):
         """Send a query to InfluxDB.
 
         :param query: the actual query string
@@ -384,6 +385,9 @@ class InfluxDBClient(object):
         :param chunk_size: Size of each chunk to tell InfluxDB to use.
         :type chunk_size: int
 
+        :param method: the HTTP method for the request, defaults to GET
+        :type method: str
+
         :returns: the queried data
         :rtype: :class:`~.ResultSet`
         """
@@ -401,9 +405,12 @@ class InfluxDBClient(object):
             if chunk_size > 0:
                 params['chunk_size'] = chunk_size
 
+        if query.lower().startswith("select ") and " into " in query.lower():
+            method = "POST"
+
         response = self.request(
             url="query",
-            method='GET',
+            method=method,
             params=params,
             data=None,
             expected_response_code=expected_response_code
@@ -568,7 +575,8 @@ class InfluxDBClient(object):
         :param dbname: the name of the database to create
         :type dbname: str
         """
-        self.query("CREATE DATABASE {0}".format(quote_ident(dbname)))
+        self.query("CREATE DATABASE {0}".format(quote_ident(dbname)),
+                   method="POST")
 
     def drop_database(self, dbname):
         """Drop a database from InfluxDB.
@@ -576,7 +584,8 @@ class InfluxDBClient(object):
         :param dbname: the name of the database to drop
         :type dbname: str
         """
-        self.query("DROP DATABASE {0}".format(quote_ident(dbname)))
+        self.query("DROP DATABASE {0}".format(quote_ident(dbname)),
+                   method="POST")
 
     def get_list_measurements(self):
         """Get the list of measurements in InfluxDB.
@@ -602,10 +611,12 @@ class InfluxDBClient(object):
         :param measurement: the name of the measurement to drop
         :type measurement: str
         """
-        self.query("DROP MEASUREMENT {0}".format(quote_ident(measurement)))
+        self.query("DROP MEASUREMENT {0}".format(quote_ident(measurement)),
+                   method="POST")
 
     def create_retention_policy(self, name, duration, replication,
-                                database=None, default=False):
+                                database=None,
+                                default=False, shard_duration="0s"):
         """Create a retention policy for a database.
 
         :param name: the name of the new retention policy
@@ -624,21 +635,31 @@ class InfluxDBClient(object):
         :type database: str
         :param default: whether or not to set the policy as default
         :type default: bool
+        :param shard_duration: the shard duration of the retention policy.
+            Durations such as 1h, 90m, 12h, 7d, and 4w, are all supported and
+            mean 1 hour, 90 minutes, 12 hours, 7 day, and 4 weeks,
+            respectively. Infinite retention is not supported. As a workaround,
+            specify a "1000w" duration to achieve an extremely long shard group
+            duration. Defaults to "0s", which is interpreted by the database
+            to mean the default value given the duration.
+            The minimum shard group duration is 1 hour.
+        :type shard_duration: str
         """
         query_string = \
             "CREATE RETENTION POLICY {0} ON {1} " \
-            "DURATION {2} REPLICATION {3}".format(
+            "DURATION {2} REPLICATION {3} SHARD DURATION {4}".format(
                 quote_ident(name), quote_ident(database or self._database),
-                duration, replication)
+                duration, replication, shard_duration)
 
         if default is True:
             query_string += " DEFAULT"
 
-        self.query(query_string)
+        self.query(query_string, method="POST")
 
     def alter_retention_policy(self, name, database=None,
-                               duration=None, replication=None, default=None):
-        """Mofidy an existing retention policy for a database.
+                               duration=None, replication=None,
+                               default=None, shard_duration=None):
+        """Modify an existing retention policy for a database.
 
         :param name: the name of the retention policy to modify
         :type name: str
@@ -657,21 +678,32 @@ class InfluxDBClient(object):
         :type replication: int
         :param default: whether or not to set the modified policy as default
         :type default: bool
+        :param shard_duration: the shard duration of the retention policy.
+            Durations such as 1h, 90m, 12h, 7d, and 4w, are all supported and
+            mean 1 hour, 90 minutes, 12 hours, 7 day, and 4 weeks,
+            respectively. Infinite retention is not supported. As a workaround,
+            specify a "1000w" duration to achieve an extremely long shard group
+            duration.
+            The minimum shard group duration is 1 hour.
+        :type shard_duration: str
 
         .. note:: at least one of duration, replication, or default flag
             should be set. Otherwise the operation will fail.
         """
         query_string = (
             "ALTER RETENTION POLICY {0} ON {1}"
-        ).format(quote_ident(name), quote_ident(database or self._database))
+        ).format(quote_ident(name),
+                 quote_ident(database or self._database), shard_duration)
         if duration:
             query_string += " DURATION {0}".format(duration)
+        if shard_duration:
+            query_string += " SHARD DURATION {0}".format(shard_duration)
         if replication:
             query_string += " REPLICATION {0}".format(replication)
         if default is True:
             query_string += " DEFAULT"
 
-        self.query(query_string)
+        self.query(query_string, method="POST")
 
     def drop_retention_policy(self, name, database=None):
         """Drop an existing retention policy for a database.
@@ -685,7 +717,7 @@ class InfluxDBClient(object):
         query_string = (
             "DROP RETENTION POLICY {0} ON {1}"
         ).format(quote_ident(name), quote_ident(database or self._database))
-        self.query(query_string)
+        self.query(query_string, method="POST")
 
     def get_list_retention_policies(self, database=None):
         """Get the list of retention policies for a database.
@@ -751,7 +783,7 @@ class InfluxDBClient(object):
             quote_ident(username), quote_literal(password))
         if admin:
             text += ' WITH ALL PRIVILEGES'
-        self.query(text)
+        self.query(text, method="POST")
 
     def drop_user(self, username):
         """Drop a user from InfluxDB.
@@ -759,8 +791,8 @@ class InfluxDBClient(object):
         :param username: the username to drop
         :type username: str
         """
-        text = "DROP USER {0}".format(quote_ident(username))
-        self.query(text)
+        text = "DROP USER {0}".format(quote_ident(username), method="POST")
+        self.query(text, method="POST")
 
     def set_user_password(self, username, password):
         """Change the password of an existing user.
@@ -796,7 +828,7 @@ class InfluxDBClient(object):
             tag_eq_list = ["{0}={1}".format(quote_ident(k), quote_literal(v))
                            for k, v in tags.items()]
             query_str += ' WHERE ' + ' AND '.join(tag_eq_list)
-        self.query(query_str, database=database)
+        self.query(query_str, database=database, method="POST")
 
     def grant_admin_privileges(self, username):
         """Grant cluster administration privileges to a user.
@@ -808,7 +840,7 @@ class InfluxDBClient(object):
             and manage users.
         """
         text = "GRANT ALL PRIVILEGES TO {0}".format(quote_ident(username))
-        self.query(text)
+        self.query(text, method="POST")
 
     def revoke_admin_privileges(self, username):
         """Revoke cluster administration privileges from a user.
@@ -820,7 +852,7 @@ class InfluxDBClient(object):
             and manage users.
         """
         text = "REVOKE ALL PRIVILEGES FROM {0}".format(quote_ident(username))
-        self.query(text)
+        self.query(text, method="POST")
 
     def grant_privilege(self, privilege, database, username):
         """Grant a privilege on a database to a user.
@@ -836,7 +868,7 @@ class InfluxDBClient(object):
         text = "GRANT {0} ON {1} TO {2}".format(privilege,
                                                 quote_ident(database),
                                                 quote_ident(username))
-        self.query(text)
+        self.query(text, method="POST")
 
     def revoke_privilege(self, privilege, database, username):
         """Revoke a privilege on a database from a user.
@@ -852,7 +884,7 @@ class InfluxDBClient(object):
         text = "REVOKE {0} ON {1} FROM {2}".format(privilege,
                                                    quote_ident(database),
                                                    quote_ident(username))
-        self.query(text)
+        self.query(text, method="POST")
 
     def get_list_privileges(self, username):
         """Get the list of all privileges granted to given user.
diff --git a/influxdb/tests/client_test.py b/influxdb/tests/client_test.py
index efdfb77..e27eef1 100644
--- a/influxdb/tests/client_test.py
+++ b/influxdb/tests/client_test.py
@@ -439,6 +439,29 @@ class TestInfluxDBClient(unittest.TestCase):
                 [{'value': 0.64, 'time': '2009-11-10T23:00:00Z'}]
             )
 
+    def test_select_into_post(self):
+        """Test SELECT.*INTO is POSTed."""
+        example_response = (
+            '{"results": [{"series": [{"measurement": "sdfsdfsdf", '
+            '"columns": ["time", "value"], "values": '
+            '[["2009-11-10T23:00:00Z", 0.64]]}]}, {"series": '
+            '[{"measurement": "cpu_load_short", "columns": ["time", "value"], '
+            '"values": [["2009-11-10T23:00:00Z", 0.64]]}]}]}'
+        )
+
+        with requests_mock.Mocker() as m:
+            m.register_uri(
+                requests_mock.POST,
+                "http://localhost:8086/query",
+                text=example_response
+            )
+            rs = self.cli.query('select * INTO newmeas from foo')
+
+            self.assertListEqual(
+                list(rs[0].get_points()),
+                [{'value': 0.64, 'time': '2009-11-10T23:00:00Z'}]
+            )
+
     @unittest.skip('Not implemented for 0.9')
     def test_query_chunked(self):
         """Test chunked query for TestInfluxDBClient object."""
@@ -495,7 +518,7 @@ class TestInfluxDBClient(unittest.TestCase):
         """Test create database for TestInfluxDBClient object."""
         with requests_mock.Mocker() as m:
             m.register_uri(
-                requests_mock.GET,
+                requests_mock.POST,
                 "http://localhost:8086/query",
                 text='{"results":[{}]}'
             )
@@ -509,7 +532,7 @@ class TestInfluxDBClient(unittest.TestCase):
         """Test create db w/numeric name for TestInfluxDBClient object."""
         with requests_mock.Mocker() as m:
             m.register_uri(
-                requests_mock.GET,
+                requests_mock.POST,
                 "http://localhost:8086/query",
                 text='{"results":[{}]}'
             )
@@ -529,7 +552,7 @@ class TestInfluxDBClient(unittest.TestCase):
         """Test drop database for TestInfluxDBClient object."""
         with requests_mock.Mocker() as m:
             m.register_uri(
-                requests_mock.GET,
+                requests_mock.POST,
                 "http://localhost:8086/query",
                 text='{"results":[{}]}'
             )
@@ -543,7 +566,7 @@ class TestInfluxDBClient(unittest.TestCase):
         """Test drop measurement for TestInfluxDBClient object."""
         with requests_mock.Mocker() as m:
             m.register_uri(
-                requests_mock.GET,
+                requests_mock.POST,
                 "http://localhost:8086/query",
                 text='{"results":[{}]}'
             )
@@ -557,7 +580,7 @@ class TestInfluxDBClient(unittest.TestCase):
         """Test drop numeric db for TestInfluxDBClient object."""
         with requests_mock.Mocker() as m:
             m.register_uri(
-                requests_mock.GET,
+                requests_mock.POST,
                 "http://localhost:8086/query",
                 text='{"results":[{}]}'
             )
@@ -615,7 +638,7 @@ class TestInfluxDBClient(unittest.TestCase):
 
         with requests_mock.Mocker() as m:
             m.register_uri(
-                requests_mock.GET,
+                requests_mock.POST,
                 "http://localhost:8086/query",
                 text=example_response
             )
@@ -626,7 +649,7 @@ class TestInfluxDBClient(unittest.TestCase):
             self.assertEqual(
                 m.last_request.qs['q'][0],
                 'create retention policy "somename" on '
-                '"db" duration 1d replication 4 default'
+                '"db" duration 1d replication 4 shard duration 0s default'
             )
 
     def test_create_retention_policy(self):
@@ -635,7 +658,7 @@ class TestInfluxDBClient(unittest.TestCase):
 
         with requests_mock.Mocker() as m:
             m.register_uri(
-                requests_mock.GET,
+                requests_mock.POST,
                 "http://localhost:8086/query",
                 text=example_response
             )
@@ -646,7 +669,7 @@ class TestInfluxDBClient(unittest.TestCase):
             self.assertEqual(
                 m.last_request.qs['q'][0],
                 'create retention policy "somename" on '
-                '"db" duration 1d replication 4'
+                '"db" duration 1d replication 4 shard duration 0s'
             )
 
     def test_alter_retention_policy(self):
@@ -655,7 +678,7 @@ class TestInfluxDBClient(unittest.TestCase):
 
         with requests_mock.Mocker() as m:
             m.register_uri(
-                requests_mock.GET,
+                requests_mock.POST,
                 "http://localhost:8086/query",
                 text=example_response
             )
@@ -674,6 +697,14 @@ class TestInfluxDBClient(unittest.TestCase):
                 'alter retention policy "somename" on "db" replication 4'
             )
 
+            # Test alter shard duration
+            self.cli.alter_retention_policy('somename', 'db',
+                                            shard_duration='1h')
+            self.assertEqual(
+                m.last_request.qs['q'][0],
+                'alter retention policy "somename" on "db" shard duration 1h'
+            )
+
             # Test alter default
             self.cli.alter_retention_policy('somename', 'db',
                                             default=True)
@@ -695,7 +726,7 @@ class TestInfluxDBClient(unittest.TestCase):
 
         with requests_mock.Mocker() as m:
             m.register_uri(
-                requests_mock.GET,
+                requests_mock.POST,
                 "http://localhost:8086/query",
                 text=example_response
             )
@@ -879,7 +910,7 @@ class TestInfluxDBClient(unittest.TestCase):
 
         with requests_mock.Mocker() as m:
             m.register_uri(
-                requests_mock.GET,
+                requests_mock.POST,
                 "http://localhost:8086/query",
                 text=example_response
             )
@@ -903,7 +934,7 @@ class TestInfluxDBClient(unittest.TestCase):
 
         with requests_mock.Mocker() as m:
             m.register_uri(
-                requests_mock.GET,
+                requests_mock.POST,
                 "http://localhost:8086/query",
                 text=example_response
             )
@@ -927,7 +958,7 @@ class TestInfluxDBClient(unittest.TestCase):
 
         with requests_mock.Mocker() as m:
             m.register_uri(
-                requests_mock.GET,
+                requests_mock.POST,
                 "http://localhost:8086/query",
                 text=example_response
             )
@@ -951,7 +982,7 @@ class TestInfluxDBClient(unittest.TestCase):
 
         with requests_mock.Mocker() as m:
             m.register_uri(
-                requests_mock.GET,
+                requests_mock.POST,
                 "http://localhost:8086/query",
                 text=example_response
             )
diff --git a/influxdb/tests/server_tests/client_test_with_server.py b/influxdb/tests/server_tests/client_test_with_server.py
index 701f72a..2f8a209 100644
--- a/influxdb/tests/server_tests/client_test_with_server.py
+++ b/influxdb/tests/server_tests/client_test_with_server.py
@@ -211,7 +211,7 @@ class SimpleTests(SingleTestCaseWithServerMixin, unittest.TestCase):
         self.assertEqual(users, [])
 
     def test_drop_user_nonexisting(self):
-        """Test dropping a nonexistant user."""
+        """Test dropping a nonexistent user."""
         with self.assertRaises(InfluxDBClientError) as ctx:
             self.cli.drop_user('test')
         self.assertIn('user not found',
@@ -383,6 +383,24 @@ class CommonTests(ManyTestCasesWithServerMixin, unittest.TestCase):
             ]]
         )
 
+    def test_select_into_as_post(self):
+        """Test SELECT INTO is POSTed."""
+        self.assertIs(True, self.cli.write_points(dummy_points))
+        time.sleep(1)
+        rsp = self.cli.query('SELECT * INTO "newmeas" FROM "memory"')
+        rsp = self.cli.query('SELECT * FROM "newmeas"')
+        lrsp = list(rsp)
+
+        self.assertEqual(
+            lrsp,
+            [[
+                {'value': 33,
+                 'time': '2009-11-10T23:01:35Z',
+                 "host": "server01",
+                 "region": "us-west"}
+            ]]
+        )
+
     @unittest.skip("Broken as of 0.9.0")
     def test_write_multiple_points_different_series_DF(self):
         """Test write multiple points using dataframe to different series."""
@@ -526,13 +544,57 @@ class CommonTests(ManyTestCasesWithServerMixin, unittest.TestCase):
             rsp
         )
 
+        self.cli.drop_retention_policy('somename', 'db')
+        # recreate the RP
+        self.cli.create_retention_policy('somename', '1w', 1,
+                                         shard_duration='1h')
+
+        rsp = self.cli.get_list_retention_policies()
+        self.assertEqual(
+            [
+                {'duration': '0s',
+                 'default': True,
+                 'replicaN': 1,
+                 'shardGroupDuration': u'168h0m0s',
+                 'name': 'autogen'},
+                {'duration': '168h0m0s',
+                 'default': False,
+                 'replicaN': 1,
+                 'shardGroupDuration': u'1h0m0s',
+                 'name': 'somename'}
+            ],
+            rsp
+        )
+
+        self.cli.drop_retention_policy('somename', 'db')
+        # recreate the RP
+        self.cli.create_retention_policy('somename', '1w', 1)
+
+        rsp = self.cli.get_list_retention_policies()
+        self.assertEqual(
+            [
+                {'duration': '0s',
+                 'default': True,
+                 'replicaN': 1,
+                 'shardGroupDuration': u'168h0m0s',
+                 'name': 'autogen'},
+                {'duration': '168h0m0s',
+                 'default': False,
+                 'replicaN': 1,
+                 'shardGroupDuration': u'24h0m0s',
+                 'name': 'somename'}
+            ],
+            rsp
+        )
+
     def test_alter_retention_policy(self):
         """Test alter a retention policy, not default."""
         self.cli.create_retention_policy('somename', '1d', 1)
 
         # Test alter duration
         self.cli.alter_retention_policy('somename', 'db',
-                                        duration='4d')
+                                        duration='4d',
+                                        shard_duration='2h')
         # NB: altering retention policy doesn't change shard group duration
         rsp = self.cli.get_list_retention_policies()
         self.assertEqual(
@@ -545,7 +607,7 @@ class CommonTests(ManyTestCasesWithServerMixin, unittest.TestCase):
                 {'duration': '96h0m0s',
                  'default': False,
                  'replicaN': 1,
-                 'shardGroupDuration': u'1h0m0s',
+                 'shardGroupDuration': u'2h0m0s',
                  'name': 'somename'}
             ],
             rsp
@@ -554,6 +616,7 @@ class CommonTests(ManyTestCasesWithServerMixin, unittest.TestCase):
         # Test alter replication
         self.cli.alter_retention_policy('somename', 'db',
                                         replication=4)
+
         # NB: altering retention policy doesn't change shard group duration
         rsp = self.cli.get_list_retention_policies()
         self.assertEqual(
@@ -566,7 +629,7 @@ class CommonTests(ManyTestCasesWithServerMixin, unittest.TestCase):
                 {'duration': '96h0m0s',
                  'default': False,
                  'replicaN': 4,
-                 'shardGroupDuration': u'1h0m0s',
+                 'shardGroupDuration': u'2h0m0s',
                  'name': 'somename'}
             ],
             rsp
@@ -587,7 +650,28 @@ class CommonTests(ManyTestCasesWithServerMixin, unittest.TestCase):
                 {'duration': '96h0m0s',
                  'default': True,
                  'replicaN': 4,
-                 'shardGroupDuration': u'1h0m0s',
+                 'shardGroupDuration': u'2h0m0s',
+                 'name': 'somename'}
+            ],
+            rsp
+        )
+
+        # Test alter shard_duration
+        self.cli.alter_retention_policy('somename', 'db',
+                                        shard_duration='4h')
+
+        rsp = self.cli.get_list_retention_policies()
+        self.assertEqual(
+            [
+                {'duration': '0s',
+                 'default': False,
+                 'replicaN': 1,
+                 'shardGroupDuration': u'168h0m0s',
+                 'name': 'autogen'},
+                {'duration': '96h0m0s',
+                 'default': True,
+                 'replicaN': 4,
+                 'shardGroupDuration': u'4h0m0s',
                  'name': 'somename'}
             ],
             rsp
diff --git a/influxdb/tests/server_tests/influxdb_instance.py b/influxdb/tests/server_tests/influxdb_instance.py
index 21e20fd..1dcd756 100644
--- a/influxdb/tests/server_tests/influxdb_instance.py
+++ b/influxdb/tests/server_tests/influxdb_instance.py
@@ -80,7 +80,7 @@ class InfluxDbInstance(object):
         # find a couple free ports :
         free_ports = get_free_ports(4)
         ports = {}
-        for service in 'http', 'admin', 'meta', 'udp':
+        for service in 'http', 'global', 'meta', 'udp':
             ports[service + '_port'] = free_ports.pop()
         if not udp_enabled:
             ports['udp_port'] = -1
@@ -113,7 +113,7 @@ class InfluxDbInstance(object):
             "%s > Started influxdb bin in %r with ports %s and %s.." % (
                 datetime.datetime.now(),
                 self.temp_dir_base,
-                self.admin_port,
+                self.global_port,
                 self.http_port
             )
         )
@@ -126,7 +126,7 @@ class InfluxDbInstance(object):
         try:
             while time.time() < timeout:
                 if (is_port_open(self.http_port) and
-                        is_port_open(self.admin_port)):
+                        is_port_open(self.global_port)):
                     # it's hard to check if a UDP port is open..
                     if udp_enabled:
                         # so let's just sleep 0.5 sec in this case
-- 
GitLab