Repository: softlayer/softlayer-python

Issue:
Unexpected Error occured when writing SL settings to "/home/vagrant/.softlayer"
Here is the Error:

### Environment Information
Operating System:
softlayer-python version (`slcli --version`):


Discussion:

Patch:
diff --git a/SoftLayer/CLI/config/setup.py b/SoftLayer/CLI/config/setup.py
index cd5a24c1..54aa1c79 100644
--- a/SoftLayer/CLI/config/setup.py
+++ b/SoftLayer/CLI/config/setup.py
@@ -5,7 +5,6 @@
 import click
 
 import SoftLayer
-from SoftLayer import auth
 from SoftLayer.CLI import config
 from SoftLayer.CLI import environment
 from SoftLayer.CLI import exceptions
@@ -22,7 +21,6 @@ def get_api_key(client, username, secret):
     # Try to use a client with username/api key
     if len(secret) == 64:
         try:
-            client.auth = auth.BasicAuthentication(username, secret)
             client['Account'].getCurrentUser()
             return secret
         except SoftLayer.SoftLayerAPIError as ex:
@@ -32,12 +30,10 @@ def get_api_key(client, username, secret):
         # Try to use a client with username/password
         client.authenticate_with_password(username, secret)
 
-        user_record = client['Account'].getCurrentUser(
-            mask='id, apiAuthenticationKeys')
+        user_record = client['Account'].getCurrentUser(mask='id, apiAuthenticationKeys')
         api_keys = user_record['apiAuthenticationKeys']
         if len(api_keys) == 0:
-            return client['User_Customer'].addApiAuthenticationKey(
-                id=user_record['id'])
+            return client['User_Customer'].addApiAuthenticationKey(id=user_record['id'])
         return api_keys[0]['authenticationKey']
 
 
@@ -47,9 +43,8 @@ def cli(env):
     """Edit configuration."""
 
     username, secret, endpoint_url, timeout = get_user_input(env)
-
-    env.client.transport.transport.endpoint_url = endpoint_url
-    api_key = get_api_key(env.client, username, secret)
+    new_client = SoftLayer.Client(username=username, api_key=secret, endpoint_url=endpoint_url, timeout=timeout)
+    api_key = get_api_key(new_client, username, secret)
 
     path = '~/.softlayer'
     if env.config_file:
@@ -103,17 +98,20 @@ def get_user_input(env):
     secret = env.getpass('API Key or Password', default=defaults['api_key'])
 
     # Ask for which endpoint they want to use
+    endpoint = defaults.get('endpoint_url', 'public')
     endpoint_type = env.input(
-        'Endpoint (public|private|custom)', default='public')
+        'Endpoint (public|private|custom)', default=endpoint)
     endpoint_type = endpoint_type.lower()
 
-    if endpoint_type == 'custom':
-        endpoint_url = env.input('Endpoint URL',
-                                 default=defaults['endpoint_url'])
+    if endpoint_type == 'public':
+        endpoint_url = SoftLayer.API_PUBLIC_ENDPOINT
     elif endpoint_type == 'private':
         endpoint_url = SoftLayer.API_PRIVATE_ENDPOINT
     else:
-        endpoint_url = SoftLayer.API_PUBLIC_ENDPOINT
+        if endpoint_type == 'custom':
+            endpoint_url = env.input('Endpoint URL', default=endpoint)
+        else:
+            endpoint_url = endpoint_type
 
     # Ask for timeout
     timeout = env.input('Timeout', default=defaults['timeout'] or 0)
diff --git a/SoftLayer/CLI/order/item_list.py b/SoftLayer/CLI/order/item_list.py
index 74f8fd4e..92f83cea 100644
--- a/SoftLayer/CLI/order/item_list.py
+++ b/SoftLayer/CLI/order/item_list.py
@@ -7,7 +7,7 @@
 from SoftLayer.managers import ordering
 from SoftLayer.utils import lookup
 
-COLUMNS = ['category', 'keyName', 'description']
+COLUMNS = ['category', 'keyName', 'description', 'priceId']
 
 
 @click.command()
@@ -60,7 +60,7 @@ def cli(env, package_keyname, keyword, category):
     categories = sorted_items.keys()
     for catname in sorted(categories):
         for item in sorted_items[catname]:
-            table.add_row([catname, item['keyName'], item['description']])
+            table.add_row([catname, item['keyName'], item['description'], get_price(item)])
     env.fout(table)
 
 
@@ -75,3 +75,12 @@ def sort_items(items):
         sorted_items[category].append(item)
 
     return sorted_items
+
+
+def get_price(item):
+    """Given an SoftLayer_Product_Item, returns its default price id"""
+
+    for price in item.get('prices', []):
+        if not price.get('locationGroupId'):
+            return price.get('id')
+    return 0
diff --git a/SoftLayer/managers/file.py b/SoftLayer/managers/file.py
index b6d16053..e0a25032 100644
--- a/SoftLayer/managers/file.py
+++ b/SoftLayer/managers/file.py
@@ -482,9 +482,6 @@ def cancel_file_volume(self, volume_id, reason='No longer needed', immediate=Fal
         file_volume = self.get_file_volume_details(
             volume_id,
             mask='mask[id,billingItem[id,hourlyFlag]]')
-
-        if 'billingItem' not in file_volume:
-            raise exceptions.SoftLayerError('The volume has already been canceled')
         billing_item_id = file_volume['billingItem']['id']
 
         if utils.lookup(file_volume, 'billingItem', 'hourlyFlag'):
diff --git a/SoftLayer/managers/ordering.py b/SoftLayer/managers/ordering.py
index c0eca1dc..fbc56b65 100644
--- a/SoftLayer/managers/ordering.py
+++ b/SoftLayer/managers/ordering.py
@@ -16,7 +16,7 @@
                    itemCategory[id, name, categoryCode]
                 '''
 
-ITEM_MASK = '''id, keyName, description, itemCategory, categories'''
+ITEM_MASK = '''id, keyName, description, itemCategory, categories, prices'''
 
 PACKAGE_MASK = '''id, name, keyName, isActive, type'''
 


Test patch:
diff --git a/tests/CLI/modules/config_tests.py b/tests/CLI/modules/config_tests.py
index 5c21b1da..4fe9cf86 100644
--- a/tests/CLI/modules/config_tests.py
+++ b/tests/CLI/modules/config_tests.py
@@ -51,10 +51,12 @@ def set_up(self):
         transport = testing.MockableTransport(SoftLayer.FixtureTransport())
         self.env.client = SoftLayer.BaseClient(transport=transport)
 
+    @mock.patch('SoftLayer.Client')
     @mock.patch('SoftLayer.CLI.formatting.confirm')
     @mock.patch('SoftLayer.CLI.environment.Environment.getpass')
     @mock.patch('SoftLayer.CLI.environment.Environment.input')
-    def test_setup(self, mocked_input, getpass, confirm_mock):
+    def test_setup(self, mocked_input, getpass, confirm_mock, client):
+        client.return_value = self.env.client
         if(sys.platform.startswith("win")):
             self.skipTest("Test doesn't work in Windows")
         with tempfile.NamedTemporaryFile() as config_file:
@@ -62,19 +64,16 @@ def test_setup(self, mocked_input, getpass, confirm_mock):
             getpass.return_value = 'A' * 64
             mocked_input.side_effect = ['user', 'public', 0]
 
-            result = self.run_command(['--config=%s' % config_file.name,
-                                       'config', 'setup'])
+            result = self.run_command(['--config=%s' % config_file.name, 'config', 'setup'])
 
             self.assert_no_fail(result)
-            self.assertTrue('Configuration Updated Successfully'
-                            in result.output)
+            self.assertTrue('Configuration Updated Successfully' in result.output)
             contents = config_file.read().decode("utf-8")
+
             self.assertTrue('[softlayer]' in contents)
             self.assertTrue('username = user' in contents)
-            self.assertTrue('api_key = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'
-                            'AAAAAAAAAAAAAAAAAAAAAAAAAAAAA' in contents)
-            self.assertTrue('endpoint_url = %s' % consts.API_PUBLIC_ENDPOINT
-                            in contents)
+            self.assertTrue('api_key = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA' in contents)
+            self.assertTrue('endpoint_url = %s' % consts.API_PUBLIC_ENDPOINT in contents)
 
     @mock.patch('SoftLayer.CLI.formatting.confirm')
     @mock.patch('SoftLayer.CLI.environment.Environment.getpass')
@@ -115,6 +114,17 @@ def test_get_user_input_custom(self, mocked_input, getpass):
 
         self.assertEqual(endpoint_url, 'custom-endpoint')
 
+    @mock.patch('SoftLayer.CLI.environment.Environment.getpass')
+    @mock.patch('SoftLayer.CLI.environment.Environment.input')
+    def test_github_1074(self, mocked_input, getpass):
+        """Tests to make sure directly using an endpoint works"""
+        getpass.return_value = 'A' * 64
+        mocked_input.side_effect = ['user', 'test-endpoint', 0]
+
+        _, _, endpoint_url, _ = config.get_user_input(self.env)
+
+        self.assertEqual(endpoint_url, 'test-endpoint')
+
     @mock.patch('SoftLayer.CLI.environment.Environment.getpass')
     @mock.patch('SoftLayer.CLI.environment.Environment.input')
     def test_get_user_input_default(self, mocked_input, getpass):
diff --git a/tests/CLI/modules/file_tests.py b/tests/CLI/modules/file_tests.py
index 465e9ec0..9bc56320 100644
--- a/tests/CLI/modules/file_tests.py
+++ b/tests/CLI/modules/file_tests.py
@@ -4,7 +4,6 @@
 
     :license: MIT, see LICENSE for more details.
 """
-from SoftLayer import exceptions
 from SoftLayer import testing
 
 import json
@@ -95,31 +94,6 @@ def test_volume_cancel(self):
         self.assert_called_with('SoftLayer_Billing_Item', 'cancelItem',
                                 args=(False, True, None))
 
-    def test_volume_cancel_with_billing_item(self):
-        result = self.run_command([
-            '--really', 'file', 'volume-cancel', '1234'])
-
-        self.assert_no_fail(result)
-        self.assertEqual('File volume with id 1234 has been marked'
-                         ' for cancellation\n', result.output)
-        self.assert_called_with('SoftLayer_Network_Storage', 'getObject')
-
-    def test_volume_cancel_without_billing_item(self):
-        p_mock = self.set_mock('SoftLayer_Network_Storage', 'getObject')
-        p_mock.return_value = {
-            "accountId": 1234,
-            "capacityGb": 20,
-            "createDate": "2015-04-29T06:55:55-07:00",
-            "id": 11111,
-            "nasType": "NAS",
-            "username": "SL01SEV307608_1"
-        }
-
-        result = self.run_command([
-            '--really', 'file', 'volume-cancel', '1234'])
-
-        self.assertIsInstance(result.exception, exceptions.SoftLayerError)
-
     def test_volume_detail(self):
         result = self.run_command(['file', 'volume-detail', '1234'])
 
diff --git a/tests/CLI/modules/order_tests.py b/tests/CLI/modules/order_tests.py
index 6b16e501..c35d6d38 100644
--- a/tests/CLI/modules/order_tests.py
+++ b/tests/CLI/modules/order_tests.py
@@ -38,13 +38,9 @@ def test_item_list(self):
 
         self.assert_no_fail(result)
         self.assert_called_with('SoftLayer_Product_Package', 'getItems')
-        expected_results = [{'category': 'testing',
-                             'keyName': 'item1',
-                             'description': 'description1'},
-                            {'category': 'testing',
-                             'keyName': 'item2',
-                             'description': 'description2'}]
-        self.assertEqual(expected_results, json.loads(result.output))
+        self.assertIn('description2', result.output)
+        self.assertIn('testing', result.output)
+        self.assertIn('item2', result.output)
 
     def test_package_list(self):
         p_mock = self.set_mock('SoftLayer_Product_Package', 'getAllObjects')