Skip to content

Commit 2ff7e23

Browse files
authored
Fix reading RQD_TAGS value from config file. (#916)
1 parent a61cc48 commit 2ff7e23

File tree

2 files changed

+155
-3
lines changed

2 files changed

+155
-3
lines changed

rqd/rqd/rqconstants.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,13 @@
128128
if os.path.isfile(CONFIG_FILE):
129129
# Hostname can come from here: rqutil.getHostname()
130130
__section = "Override"
131-
import configparser
132-
config = configparser.RawConfigParser()
131+
import six
132+
from six.moves import configparser
133+
if six.PY2:
134+
ConfigParser = configparser.SafeConfigParser
135+
else:
136+
ConfigParser = configparser.RawConfigParser
137+
config = ConfigParser()
133138
logging.info('Loading config {}'.format(CONFIG_FILE))
134139
config.read(CONFIG_FILE)
135140

@@ -162,7 +167,7 @@
162167
if config.has_option(__section, "RQD_BECOME_JOB_USER"):
163168
RQD_BECOME_JOB_USER = config.getboolean(__section, "RQD_BECOME_JOB_USER")
164169
if config.has_option(__section, "RQD_TAGS"):
165-
RQD_TAGS = config.getint(__section, "RQD_TAGS")
170+
RQD_TAGS = config.get(__section, "RQD_TAGS")
166171
if config.has_option(__section, "DEFAULT_FACILITY"):
167172
DEFAULT_FACILITY = config.get(__section, "DEFAULT_FACILITY")
168173
if config.has_option(__section, "LAUNCH_FRAME_USER_GID"):

rqd/tests/rqconstants_tests.py

Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
#!/usr/bin/env python
2+
3+
# Copyright Contributors to the OpenCue Project
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
18+
from __future__ import print_function
19+
from __future__ import division
20+
from __future__ import absolute_import
21+
22+
import os.path
23+
import shutil
24+
import tempfile
25+
import unittest
26+
import uuid
27+
28+
import mock
29+
import pyfakefs.fake_filesystem_unittest
30+
31+
import six
32+
33+
import rqd.rqconstants
34+
import rqd.rqcore
35+
import rqd.rqmachine
36+
import rqd.rqnimby
37+
import rqd.rqutil
38+
import rqd.compiled_proto.report_pb2
39+
40+
from .rqmachine_tests import (
41+
CPUINFO,
42+
CUDAINFO,
43+
LOADAVG_LOW_USAGE,
44+
MEMINFO_MODERATE_USAGE,
45+
PROC_STAT,
46+
)
47+
48+
49+
if not six.PY2:
50+
import importlib
51+
52+
reload = importlib.reload
53+
54+
55+
class MockConfig(object):
56+
def __init__(self, tempdir, content):
57+
config = os.path.join(tempdir, str(uuid.uuid4()))
58+
self.patcher = mock.patch("sys.argv", ["rqd", "-c", config])
59+
60+
with open(config, "w") as f:
61+
print(content, file=f)
62+
63+
def __enter__(self):
64+
self.patcher.start()
65+
reload(rqd.rqconstants)
66+
return self
67+
68+
def __exit__(self, exc_type, exc_value, traceback):
69+
self.patcher.stop()
70+
71+
def __call__(self, func):
72+
def decorator(*args, **kwargs):
73+
with self:
74+
return func(*args, **kwargs)
75+
76+
return decorator
77+
78+
79+
@mock.patch("subprocess.getoutput", new=mock.MagicMock(return_value=CUDAINFO))
80+
@mock.patch.object(
81+
rqd.rqutil.Memoize, "isCached", new=mock.MagicMock(return_value=False)
82+
)
83+
@mock.patch("platform.system", new=mock.MagicMock(return_value="Linux"))
84+
@mock.patch("os.statvfs", new=mock.MagicMock())
85+
@mock.patch(
86+
"rqd.rqutil.getHostname", new=mock.MagicMock(return_value="arbitrary-hostname")
87+
)
88+
class RqConstantTests(pyfakefs.fake_filesystem_unittest.TestCase):
89+
90+
tempdir = tempfile.mkdtemp()
91+
92+
def setUp(self):
93+
self.setUpPyfakefs()
94+
self.fs.add_real_directory(self.tempdir)
95+
self.fs.create_file("/proc/cpuinfo", contents=CPUINFO)
96+
self.loadavg = self.fs.create_file("/proc/loadavg", contents=LOADAVG_LOW_USAGE)
97+
self.procStat = self.fs.create_file("/proc/stat", contents=PROC_STAT)
98+
self.meminfo = self.fs.create_file(
99+
"/proc/meminfo", contents=MEMINFO_MODERATE_USAGE
100+
)
101+
102+
def tearDown(self):
103+
shutil.rmtree(self.tempdir)
104+
105+
def makeRqMachine(self):
106+
rqCore = mock.MagicMock(spec=rqd.rqcore.RqCore)
107+
nimby = mock.MagicMock(spec=rqd.rqnimby.Nimby)
108+
rqCore.nimby = nimby
109+
nimby.active = False
110+
nimby.locked = False
111+
coreDetail = rqd.compiled_proto.report_pb2.CoreDetail(total_cores=2)
112+
machine = rqd.rqmachine.Machine(rqCore, coreDetail)
113+
114+
machine.renderHost = machine.__dict__["_Machine__renderHost"]
115+
116+
return machine
117+
118+
@MockConfig(
119+
tempdir,
120+
"""
121+
[Override]
122+
DEFAULT_FACILITY = test_facility
123+
""",
124+
)
125+
def test_facility(self):
126+
self.assertEqual(rqd.rqconstants.DEFAULT_FACILITY, "test_facility")
127+
128+
machine = self.makeRqMachine()
129+
self.assertEqual(machine.renderHost.facility, "test_facility")
130+
131+
@MockConfig(
132+
tempdir,
133+
"""
134+
[Override]
135+
RQD_TAGS = test_tag1 test_tag2 test_tag3
136+
""",
137+
)
138+
def test_tags(self):
139+
self.assertEqual(rqd.rqconstants.RQD_TAGS, "test_tag1 test_tag2 test_tag3")
140+
141+
machine = self.makeRqMachine()
142+
self.assertEqual(machine.renderHost.facility, "cloud")
143+
self.assertTrue(
144+
set(["test_tag1", "test_tag2", "test_tag3"]).issubset(
145+
machine.renderHost.tags
146+
)
147+
)

0 commit comments

Comments
 (0)