~free.ekanayaka/landscape-client/jaunty-updates-1.4.4-0ubuntu0.9.04

« back to all changes in this revision

Viewing changes to landscape/tests/test_configuration.py

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2009-03-18 20:42:05 UTC
  • Revision ID: james.westby@ubuntu.com-20090318204205-v17ejhu5urdsrm7j
Tags: 1.0.28-0ubuntu1
New upstream release. (LP: #343954)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
import os
2
2
from getpass import getpass
 
3
from ConfigParser import ConfigParser
3
4
 
4
5
from dbus import DBusException
5
6
 
 
7
import pycurl
 
8
 
6
9
from twisted.internet.defer import Deferred, succeed, fail
7
10
from twisted.internet import reactor
8
11
 
 
12
from landscape.lib.fetch import HTTPCodeError
9
13
from landscape.configuration import (
10
14
    print_text, LandscapeSetupScript, LandscapeSetupConfiguration,
11
15
    register, setup, main, setup_init_script_and_start_client,
12
 
    stop_client_and_disable_init_script, ConfigurationError)
 
16
    stop_client_and_disable_init_script, ConfigurationError,
 
17
    fetch_import_url, ImportOptionError)
13
18
from landscape.broker.registration import InvalidCredentialsError
14
19
from landscape.sysvconfig import SysVConfig, ProcessError
15
20
from landscape.tests.helpers import (LandscapeTest, LandscapeIsolatedTest,
16
21
                                     RemoteBrokerHelper, EnvironSaverHelper)
17
22
from landscape.tests.mocker import ARGS, KWARGS, ANY, MATCH, CONTAINS, expect
18
23
 
 
24
 
19
25
def get_config(self, args):
20
 
    if "--config" not in args:
 
26
    if "--config" not in args and "-c" not in args:
21
27
        filename = self.makeFile("""
22
28
[client]
23
29
url = https://landscape.canonical.com/message-system
24
30
""")
25
31
        args.extend(["--config", filename])
26
 
    config = LandscapeSetupConfiguration()
 
32
    config = LandscapeSetupConfiguration(fetch_import_url)
27
33
    config.load(args)
28
34
    return config
29
35
 
86
92
        self.config_filename = self.makeFile()
87
93
        class MyLandscapeSetupConfiguration(LandscapeSetupConfiguration):
88
94
            default_config_filenames = [self.config_filename]
89
 
        self.config = MyLandscapeSetupConfiguration()
 
95
        self.config = MyLandscapeSetupConfiguration(None)
90
96
        self.script = LandscapeSetupScript(self.config)
91
97
 
92
98
    def test_show_help(self):
919
925
        self.mocker.result(1000)
920
926
        self.mocker.replay()
921
927
        sys_exit = self.assertRaises(SystemExit,
922
 
                                      main, ["-c", self.make_working_config()])
 
928
                                     main, ["-c", self.make_working_config()])
923
929
        self.assertIn("landscape-config must be run as root", str(sys_exit))
924
930
 
 
931
    def test_import_from_file(self):
 
932
        sysvconfig_mock = self.mocker.patch(SysVConfig)
 
933
        sysvconfig_mock.set_start_on_boot(True)
 
934
        sysvconfig_mock.restart_landscape()
 
935
        self.mocker.result(True)
 
936
        self.mocker.replay()
 
937
 
 
938
        configuration = (
 
939
            "[client]\n"
 
940
            "computer_title = New Title\n"
 
941
            "account_name = New Name\n"
 
942
            "registration_password = New Password\n"
 
943
            "http_proxy = http://new.proxy\n"
 
944
            "https_proxy = https://new.proxy\n"
 
945
            "url = http://new.url\n")
 
946
 
 
947
        import_filename = self.makeFile(configuration, basename="import_config")
 
948
        config_filename = self.makeFile("", basename="final_config")
 
949
 
 
950
        config = self.get_config(["--config", config_filename, "--silent",
 
951
                                  "--import", import_filename])
 
952
        setup(config)
 
953
 
 
954
        options = ConfigParser()
 
955
        options.read(config_filename)
 
956
 
 
957
        self.assertEquals(dict(options.items("client")),
 
958
                          {"computer_title": "New Title",
 
959
                           "account_name": "New Name",
 
960
                           "registration_password": "New Password",
 
961
                           "http_proxy": "http://new.proxy",
 
962
                           "https_proxy": "https://new.proxy",
 
963
                           "url": "http://new.url"})
 
964
 
 
965
    def test_import_from_empty_file(self):
 
966
        self.mocker.replay()
 
967
 
 
968
        config_filename = self.makeFile("", basename="final_config")
 
969
        import_filename = self.makeFile("", basename="import_config")
 
970
 
 
971
        # Use a command line option as well to test the precedence.
 
972
        try:
 
973
            self.get_config(["--config", config_filename, "--silent",
 
974
                             "--import", import_filename])
 
975
        except ImportOptionError, error:
 
976
            self.assertEquals(str(error), 
 
977
                              "Nothing to import at %s." % import_filename)
 
978
        else:
 
979
            self.fail("ImportOptionError not raised")
 
980
 
 
981
    def test_import_from_non_existent_file(self):
 
982
        self.mocker.replay()
 
983
 
 
984
        config_filename = self.makeFile("", basename="final_config")
 
985
        import_filename = self.makeFile(basename="import_config")
 
986
 
 
987
        # Use a command line option as well to test the precedence.
 
988
        try:
 
989
            self.get_config(["--config", config_filename, "--silent",
 
990
                             "--import", import_filename])
 
991
        except ImportOptionError, error:
 
992
            self.assertEquals(str(error), 
 
993
                              "File %s doesn't exist." % import_filename)
 
994
        else:
 
995
            self.fail("ImportOptionError not raised")
 
996
 
 
997
    def test_import_from_file_with_empty_client_section(self):
 
998
        self.mocker.replay()
 
999
 
 
1000
        old_configuration = "[client]\n"
 
1001
 
 
1002
        config_filename = self.makeFile("", old_configuration,
 
1003
                                        basename="final_config")
 
1004
        import_filename = self.makeFile("", basename="import_config")
 
1005
 
 
1006
        # Use a command line option as well to test the precedence.
 
1007
        try:
 
1008
            self.get_config(["--config", config_filename, "--silent",
 
1009
                             "--import", import_filename])
 
1010
        except ImportOptionError, error:
 
1011
            self.assertEquals(str(error), 
 
1012
                              "Nothing to import at %s." % import_filename)
 
1013
        else:
 
1014
            self.fail("ImportOptionError not raised")
 
1015
 
 
1016
    def test_import_from_bogus_file(self):
 
1017
        self.mocker.replay()
 
1018
 
 
1019
        config_filename = self.makeFile("", basename="final_config")
 
1020
        import_filename = self.makeFile("<strong>BOGUS!</strong>",
 
1021
                                        basename="import_config")
 
1022
 
 
1023
        # Use a command line option as well to test the precedence.
 
1024
        try:
 
1025
            self.get_config(["--config", config_filename, "--silent",
 
1026
                             "--import", import_filename])
 
1027
        except ImportOptionError, error:
 
1028
            self.assertIn("File contains no section headers.", str(error))
 
1029
        else:
 
1030
            self.fail("ImportOptionError not raised")
 
1031
 
 
1032
    def test_import_from_file_preserves_old_options(self):
 
1033
        sysvconfig_mock = self.mocker.patch(SysVConfig)
 
1034
        sysvconfig_mock.set_start_on_boot(True)
 
1035
        sysvconfig_mock.restart_landscape()
 
1036
        self.mocker.result(True)
 
1037
        self.mocker.replay()
 
1038
 
 
1039
        old_configuration = (
 
1040
            "[client]\n"
 
1041
            "computer_title = Old Title\n"
 
1042
            "account_name = Old Name\n"
 
1043
            "registration_password = Old Password\n"
 
1044
            "http_proxy = http://old.proxy\n"
 
1045
            "https_proxy = https://old.proxy\n"
 
1046
            "url = http://old.url\n")
 
1047
 
 
1048
        new_configuration = (
 
1049
            "[client]\n"
 
1050
            "account_name = New Name\n"
 
1051
            "registration_password = New Password\n"
 
1052
            "url = http://new.url\n")
 
1053
 
 
1054
        config_filename = self.makeFile(old_configuration,
 
1055
                                        basename="final_config")
 
1056
        import_filename = self.makeFile(new_configuration,
 
1057
                                        basename="import_config")
 
1058
 
 
1059
        # Use a command line option as well to test the precedence.
 
1060
        config = self.get_config(["--config", config_filename, "--silent",
 
1061
                                  "--import", import_filename,
 
1062
                                  "-p", "Command Line Password"])
 
1063
        setup(config)
 
1064
 
 
1065
        options = ConfigParser()
 
1066
        options.read(config_filename)
 
1067
 
 
1068
        self.assertEquals(dict(options.items("client")),
 
1069
                          {"computer_title": "Old Title",
 
1070
                           "account_name": "New Name",
 
1071
                           "registration_password": "Command Line Password",
 
1072
                           "http_proxy": "http://old.proxy",
 
1073
                           "https_proxy": "https://old.proxy",
 
1074
                           "url": "http://new.url"})
 
1075
 
 
1076
    def test_import_from_file_may_reset_old_options(self):
 
1077
        """
 
1078
        This test ensures that setting an empty option in an imported
 
1079
        configuration file will actually set the local value to empty
 
1080
        too, rather than being ignored.
 
1081
        """
 
1082
        sysvconfig_mock = self.mocker.patch(SysVConfig)
 
1083
        sysvconfig_mock.set_start_on_boot(True)
 
1084
        sysvconfig_mock.restart_landscape()
 
1085
        self.mocker.result(True)
 
1086
        self.mocker.replay()
 
1087
 
 
1088
        old_configuration = (
 
1089
            "[client]\n"
 
1090
            "computer_title = Old Title\n"
 
1091
            "account_name = Old Name\n"
 
1092
            "registration_password = Old Password\n"
 
1093
            "url = http://old.url\n")
 
1094
 
 
1095
        new_configuration = (
 
1096
            "[client]\n"
 
1097
            "registration_password =\n")
 
1098
 
 
1099
        config_filename = self.makeFile(old_configuration,
 
1100
                                        basename="final_config")
 
1101
        import_filename = self.makeFile(new_configuration,
 
1102
                                        basename="import_config")
 
1103
 
 
1104
        config = self.get_config(["--config", config_filename, "--silent",
 
1105
                                  "--import", import_filename])
 
1106
        setup(config)
 
1107
 
 
1108
        options = ConfigParser()
 
1109
        options.read(config_filename)
 
1110
 
 
1111
        self.assertEquals(dict(options.items("client")),
 
1112
                          {"computer_title": "Old Title",
 
1113
                           "account_name": "Old Name",
 
1114
                           "registration_password": "", # <==
 
1115
                           "url": "http://old.url"})
 
1116
 
 
1117
    def test_import_from_url(self):
 
1118
        sysvconfig_mock = self.mocker.patch(SysVConfig)
 
1119
        sysvconfig_mock.set_start_on_boot(True)
 
1120
        sysvconfig_mock.restart_landscape()
 
1121
        self.mocker.result(True)
 
1122
 
 
1123
        configuration = (
 
1124
            "[client]\n"
 
1125
            "computer_title = New Title\n"
 
1126
            "account_name = New Name\n"
 
1127
            "registration_password = New Password\n"
 
1128
            "http_proxy = http://new.proxy\n"
 
1129
            "https_proxy = https://new.proxy\n"
 
1130
            "url = http://new.url\n")
 
1131
 
 
1132
        fetch_mock = self.mocker.replace("landscape.lib.fetch.fetch")
 
1133
        fetch_mock("https://config.url")
 
1134
        self.mocker.result(configuration)
 
1135
 
 
1136
        print_text_mock = self.mocker.replace(print_text)
 
1137
        print_text_mock("Fetching configuration from https://config.url...")
 
1138
 
 
1139
        self.mocker.replay()
 
1140
 
 
1141
        config_filename = self.makeFile("", basename="final_config")
 
1142
 
 
1143
        config = self.get_config(["--config", config_filename, "--silent",
 
1144
                                  "--import", "https://config.url"])
 
1145
        setup(config)
 
1146
 
 
1147
        options = ConfigParser()
 
1148
        options.read(config_filename)
 
1149
 
 
1150
        self.assertEquals(dict(options.items("client")),
 
1151
                          {"computer_title": "New Title",
 
1152
                           "account_name": "New Name",
 
1153
                           "registration_password": "New Password",
 
1154
                           "http_proxy": "http://new.proxy",
 
1155
                           "https_proxy": "https://new.proxy",
 
1156
                           "url": "http://new.url"})
 
1157
 
 
1158
    def test_import_from_url_with_http_code_fetch_error(self):
 
1159
        fetch_mock = self.mocker.replace("landscape.lib.fetch.fetch")
 
1160
        fetch_mock("https://config.url")
 
1161
        self.mocker.throw(HTTPCodeError(501, ""))
 
1162
 
 
1163
        print_text_mock = self.mocker.replace(print_text)
 
1164
        print_text_mock("Fetching configuration from https://config.url...")
 
1165
 
 
1166
        self.mocker.replay()
 
1167
 
 
1168
        config_filename = self.makeFile("", basename="final_config")
 
1169
 
 
1170
        try:
 
1171
            self.get_config(["--config", config_filename, "--silent",
 
1172
                             "--import", "https://config.url"])
 
1173
        except ImportOptionError, error:
 
1174
            self.assertEquals(str(error), 
 
1175
                              "Couldn't download configuration from "
 
1176
                              "https://config.url: Server "
 
1177
                              "returned HTTP code 501")
 
1178
        else:
 
1179
            self.fail("ImportOptionError not raised")
 
1180
 
 
1181
    def test_import_from_url_with_pycurl_error(self):
 
1182
        fetch_mock = self.mocker.replace("landscape.lib.fetch.fetch")
 
1183
        fetch_mock("https://config.url")
 
1184
        self.mocker.throw(pycurl.error(60, "pycurl message"))
 
1185
 
 
1186
        print_text_mock = self.mocker.replace(print_text)
 
1187
        print_text_mock("Fetching configuration from https://config.url...")
 
1188
 
 
1189
        self.mocker.replay()
 
1190
 
 
1191
        config_filename = self.makeFile("", basename="final_config")
 
1192
 
 
1193
        try:
 
1194
            self.get_config(["--config", config_filename, "--silent",
 
1195
                             "--import", "https://config.url"])
 
1196
        except ImportOptionError, error:
 
1197
            self.assertEquals(str(error), 
 
1198
                              "Couldn't download configuration from "
 
1199
                              "https://config.url: pycurl message")
 
1200
        else:
 
1201
            self.fail("ImportOptionError not raised")
 
1202
 
 
1203
    def test_import_from_url_with_empty_content(self):
 
1204
        fetch_mock = self.mocker.replace("landscape.lib.fetch.fetch")
 
1205
        fetch_mock("https://config.url")
 
1206
        self.mocker.result("")
 
1207
 
 
1208
        print_text_mock = self.mocker.replace(print_text)
 
1209
        print_text_mock("Fetching configuration from https://config.url...")
 
1210
 
 
1211
        self.mocker.replay()
 
1212
 
 
1213
        # Use a command line option as well to test the precedence.
 
1214
        try:
 
1215
            self.get_config(["--silent", "--import", "https://config.url"])
 
1216
        except ImportOptionError, error:
 
1217
            self.assertEquals(str(error), 
 
1218
                              "Nothing to import at https://config.url.")
 
1219
        else:
 
1220
            self.fail("ImportOptionError not raised")
 
1221
 
 
1222
    def test_import_from_url_with_bogus_content(self):
 
1223
        fetch_mock = self.mocker.replace("landscape.lib.fetch.fetch")
 
1224
        fetch_mock("https://config.url")
 
1225
        self.mocker.result("<strong>BOGUS!</strong>")
 
1226
 
 
1227
        print_text_mock = self.mocker.replace(print_text)
 
1228
        print_text_mock("Fetching configuration from https://config.url...")
 
1229
 
 
1230
        self.mocker.replay()
 
1231
 
 
1232
        # Use a command line option as well to test the precedence.
 
1233
        try:
 
1234
            self.get_config(["--silent", "--import", "https://config.url"])
 
1235
        except ImportOptionError, error:
 
1236
            self.assertIn("File contains no section headers.", str(error))
 
1237
        else:
 
1238
            self.fail("ImportOptionError not raised")
 
1239
 
 
1240
    def test_import_error_is_handled_nicely_by_main(self):
 
1241
        fetch_mock = self.mocker.replace("landscape.lib.fetch.fetch")
 
1242
        fetch_mock("https://config.url")
 
1243
        self.mocker.throw(HTTPCodeError(404, ""))
 
1244
 
 
1245
        print_text_mock = self.mocker.replace(print_text)
 
1246
        print_text_mock("Fetching configuration from https://config.url...")
 
1247
        print_text_mock(CONTAINS("Server returned HTTP code 404"), error=True)
 
1248
 
 
1249
        self.mocker.replay()
 
1250
 
 
1251
        system_exit = self.assertRaises(
 
1252
            SystemExit, main, ["--import", "https://config.url"])
 
1253
        self.assertEquals(system_exit.code, 1)
 
1254
 
 
1255
    def test_base64_ssl_public_key_is_exported_to_file(self):
 
1256
        sysvconfig_mock = self.mocker.patch(SysVConfig)
 
1257
        sysvconfig_mock.set_start_on_boot(True)
 
1258
        sysvconfig_mock.restart_landscape()
 
1259
        self.mocker.result(True)
 
1260
 
 
1261
        config_filename = self.makeFile("")
 
1262
        key_filename = config_filename + ".ssl_public_key"
 
1263
 
 
1264
        print_text_mock = self.mocker.replace(print_text)
 
1265
        print_text_mock("Writing SSL public key to %s..." % key_filename)
 
1266
 
 
1267
        self.mocker.replay()
 
1268
 
 
1269
        config = self.get_config(["--silent", "-c", config_filename,
 
1270
                                  "-u", "url", "-a", "account", "-t", "title",
 
1271
                                  "--ssl-public-key", "base64:SGkgdGhlcmUh"])
 
1272
        setup(config)
 
1273
 
 
1274
        self.assertTrue(os.path.isfile(key_filename))
 
1275
        self.assertEquals(open(key_filename).read(), "Hi there!")
 
1276
 
 
1277
        options = ConfigParser()
 
1278
        options.read(config_filename)
 
1279
        self.assertEquals(options.get("client", "ssl_public_key"),
 
1280
                          key_filename)
 
1281
 
 
1282
    def test_normal_ssl_public_key_is_not_exported_to_file(self):
 
1283
        sysvconfig_mock = self.mocker.patch(SysVConfig)
 
1284
        sysvconfig_mock.set_start_on_boot(True)
 
1285
        sysvconfig_mock.restart_landscape()
 
1286
        self.mocker.result(True)
 
1287
        self.mocker.replay()
 
1288
 
 
1289
        config_filename = self.makeFile("")
 
1290
 
 
1291
        config = self.get_config(["--silent", "-c", config_filename,
 
1292
                                  "-u", "url", "-a", "account", "-t", "title",
 
1293
                                  "--ssl-public-key", "/some/filename"])
 
1294
        setup(config)
 
1295
 
 
1296
        key_filename = config_filename + ".ssl_public_key"
 
1297
        self.assertFalse(os.path.isfile(key_filename))
 
1298
 
 
1299
        options = ConfigParser()
 
1300
        options.read(config_filename)
 
1301
        self.assertEquals(options.get("client", "ssl_public_key"),
 
1302
                          "/some/filename")
 
1303
 
 
1304
    # We test them individually since they must work individually.
 
1305
    def test_import_from_url_honors_http_proxy(self):
 
1306
        self.ensure_import_from_url_honors_proxy_options("http_proxy")
 
1307
 
 
1308
    def test_import_from_url_honors_https_proxy(self):
 
1309
        self.ensure_import_from_url_honors_proxy_options("https_proxy")
 
1310
 
 
1311
    def ensure_import_from_url_honors_proxy_options(self, proxy_option):
 
1312
        def check_proxy(url):
 
1313
            self.assertEquals(os.environ.get(proxy_option), "http://proxy")
 
1314
 
 
1315
        fetch_mock = self.mocker.replace("landscape.lib.fetch.fetch")
 
1316
        fetch_mock("https://config.url")
 
1317
        self.mocker.call(check_proxy)
 
1318
 
 
1319
        # Doesn't matter.  We just want to check the context around it.
 
1320
        self.mocker.result("")
 
1321
 
 
1322
        print_text_mock = self.mocker.replace(print_text)
 
1323
        print_text_mock("Fetching configuration from https://config.url...")
 
1324
 
 
1325
        self.mocker.replay()
 
1326
 
 
1327
        config_filename = self.makeFile("", basename="final_config")
 
1328
 
 
1329
        try:
 
1330
            self.get_config(["--config", config_filename, "--silent",
 
1331
                             "--" + proxy_option.replace("_", "-"),
 
1332
                             "http://proxy",
 
1333
                             "--import", "https://config.url"])
 
1334
        except ImportOptionError:
 
1335
            pass # The returned content is empty.  We don't really
 
1336
                 # care for this test.  Mocker will ensure the tests
 
1337
                 # we care about are done.
 
1338
 
925
1339
 
926
1340
class RegisterFunctionTest(LandscapeIsolatedTest):
927
1341
 
1219
1633
 
1220
1634
    def setUp(self):
1221
1635
        super(RegisterFunctionNoServiceTest, self).setUp()
1222
 
        self.configuration = LandscapeSetupConfiguration()
 
1636
        self.configuration = LandscapeSetupConfiguration(None)
1223
1637
        # Let's not mess about with the system bus
1224
1638
        self.configuration.load_command_line(["--bus", "session"])
1225
1639