|
@@ -80,6 +80,7 @@ oc_version:
|
|
|
# -*- -*- -*- End included fragment: doc/sdnvalidator -*- -*- -*-
|
|
|
|
|
|
# -*- -*- -*- Begin included fragment: ../../lib_utils/src/class/yedit.py -*- -*- -*-
|
|
|
+# pylint: disable=undefined-variable,missing-docstring
|
|
|
# noqa: E301,E302
|
|
|
|
|
|
|
|
@@ -274,14 +275,16 @@ class Yedit(object):
|
|
|
if self.backup and self.file_exists():
|
|
|
shutil.copy(self.filename, self.filename + '.orig')
|
|
|
|
|
|
- if hasattr(yaml, 'RoundTripDumper'):
|
|
|
- # pylint: disable=no-member
|
|
|
- if hasattr(self.yaml_dict, 'fa'):
|
|
|
- self.yaml_dict.fa.set_block_style()
|
|
|
+ # Try to set format attributes if supported
|
|
|
+ try:
|
|
|
+ self.yaml_dict.fa.set_block_style()
|
|
|
+ except AttributeError:
|
|
|
+ pass
|
|
|
|
|
|
- # pylint: disable=no-member
|
|
|
+ # Try to use RoundTripDumper if supported.
|
|
|
+ try:
|
|
|
Yedit._write(self.filename, yaml.dump(self.yaml_dict, Dumper=yaml.RoundTripDumper))
|
|
|
- else:
|
|
|
+ except AttributeError:
|
|
|
Yedit._write(self.filename, yaml.safe_dump(self.yaml_dict, default_flow_style=False))
|
|
|
|
|
|
return (True, self.yaml_dict)
|
|
@@ -322,15 +325,23 @@ class Yedit(object):
|
|
|
# check if it is yaml
|
|
|
try:
|
|
|
if content_type == 'yaml' and contents:
|
|
|
- # pylint: disable=no-member
|
|
|
- if hasattr(yaml, 'RoundTripLoader'):
|
|
|
- self.yaml_dict = yaml.load(contents, yaml.RoundTripLoader)
|
|
|
- else:
|
|
|
+ # Try to set format attributes if supported
|
|
|
+ try:
|
|
|
+ self.yaml_dict.fa.set_block_style()
|
|
|
+ except AttributeError:
|
|
|
+ pass
|
|
|
+
|
|
|
+ # Try to use RoundTripLoader if supported.
|
|
|
+ try:
|
|
|
+ self.yaml_dict = yaml.safe_load(contents, yaml.RoundTripLoader)
|
|
|
+ except AttributeError:
|
|
|
self.yaml_dict = yaml.safe_load(contents)
|
|
|
|
|
|
- # pylint: disable=no-member
|
|
|
- if hasattr(self.yaml_dict, 'fa'):
|
|
|
+ # Try to set format attributes if supported
|
|
|
+ try:
|
|
|
self.yaml_dict.fa.set_block_style()
|
|
|
+ except AttributeError:
|
|
|
+ pass
|
|
|
|
|
|
elif content_type == 'json' and contents:
|
|
|
self.yaml_dict = json.loads(contents)
|
|
@@ -360,14 +371,16 @@ class Yedit(object):
|
|
|
return (False, self.yaml_dict)
|
|
|
|
|
|
if isinstance(entry, dict):
|
|
|
- # pylint: disable=no-member,maybe-no-member
|
|
|
+ # AUDIT:maybe-no-member makes sense due to fuzzy types
|
|
|
+ # pylint: disable=maybe-no-member
|
|
|
if key_or_item in entry:
|
|
|
entry.pop(key_or_item)
|
|
|
return (True, self.yaml_dict)
|
|
|
return (False, self.yaml_dict)
|
|
|
|
|
|
elif isinstance(entry, list):
|
|
|
- # pylint: disable=no-member,maybe-no-member
|
|
|
+ # AUDIT:maybe-no-member makes sense due to fuzzy types
|
|
|
+ # pylint: disable=maybe-no-member
|
|
|
ind = None
|
|
|
try:
|
|
|
ind = entry.index(key_or_item)
|
|
@@ -435,7 +448,9 @@ class Yedit(object):
|
|
|
if not isinstance(entry, list):
|
|
|
return (False, self.yaml_dict)
|
|
|
|
|
|
- # pylint: disable=no-member,maybe-no-member
|
|
|
+ # AUDIT:maybe-no-member makes sense due to loading data from
|
|
|
+ # a serialized format.
|
|
|
+ # pylint: disable=maybe-no-member
|
|
|
entry.append(value)
|
|
|
return (True, self.yaml_dict)
|
|
|
|
|
@@ -448,7 +463,8 @@ class Yedit(object):
|
|
|
entry = None
|
|
|
|
|
|
if isinstance(entry, dict):
|
|
|
- # pylint: disable=no-member,maybe-no-member
|
|
|
+ # AUDIT:maybe-no-member makes sense due to fuzzy types
|
|
|
+ # pylint: disable=maybe-no-member
|
|
|
if not isinstance(value, dict):
|
|
|
raise YeditException('Cannot replace key, value entry in ' +
|
|
|
'dict with non-dict type. value=[%s] [%s]' % (value, type(value))) # noqa: E501
|
|
@@ -457,7 +473,8 @@ class Yedit(object):
|
|
|
return (True, self.yaml_dict)
|
|
|
|
|
|
elif isinstance(entry, list):
|
|
|
- # pylint: disable=no-member,maybe-no-member
|
|
|
+ # AUDIT:maybe-no-member makes sense due to fuzzy types
|
|
|
+ # pylint: disable=maybe-no-member
|
|
|
ind = None
|
|
|
if curr_value:
|
|
|
try:
|
|
@@ -496,19 +513,20 @@ class Yedit(object):
|
|
|
return (False, self.yaml_dict)
|
|
|
|
|
|
# deepcopy didn't work
|
|
|
- if hasattr(yaml, 'round_trip_dump'):
|
|
|
- # pylint: disable=no-member
|
|
|
+ # Try to use ruamel.yaml and fallback to pyyaml
|
|
|
+ try:
|
|
|
tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict,
|
|
|
default_flow_style=False),
|
|
|
yaml.RoundTripLoader)
|
|
|
-
|
|
|
- # pylint: disable=no-member
|
|
|
- if hasattr(self.yaml_dict, 'fa'):
|
|
|
- tmp_copy.fa.set_block_style()
|
|
|
-
|
|
|
- else:
|
|
|
+ except AttributeError:
|
|
|
tmp_copy = copy.deepcopy(self.yaml_dict)
|
|
|
|
|
|
+ # set the format attributes if available
|
|
|
+ try:
|
|
|
+ tmp_copy.fa.set_block_style()
|
|
|
+ except AttributeError:
|
|
|
+ pass
|
|
|
+
|
|
|
result = Yedit.add_entry(tmp_copy, path, value, self.separator)
|
|
|
if not result:
|
|
|
return (False, self.yaml_dict)
|
|
@@ -521,17 +539,20 @@ class Yedit(object):
|
|
|
''' create a yaml file '''
|
|
|
if not self.file_exists():
|
|
|
# deepcopy didn't work
|
|
|
- if hasattr(yaml, 'round_trip_dump'):
|
|
|
- # pylint: disable=no-member
|
|
|
- tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict, default_flow_style=False), # noqa: E501
|
|
|
+ # Try to use ruamel.yaml and fallback to pyyaml
|
|
|
+ try:
|
|
|
+ tmp_copy = yaml.load(yaml.round_trip_dump(self.yaml_dict,
|
|
|
+ default_flow_style=False),
|
|
|
yaml.RoundTripLoader)
|
|
|
-
|
|
|
- # pylint: disable=no-member
|
|
|
- if hasattr(self.yaml_dict, 'fa'):
|
|
|
- tmp_copy.fa.set_block_style()
|
|
|
- else:
|
|
|
+ except AttributeError:
|
|
|
tmp_copy = copy.deepcopy(self.yaml_dict)
|
|
|
|
|
|
+ # set the format attributes if available
|
|
|
+ try:
|
|
|
+ tmp_copy.fa.set_block_style()
|
|
|
+ except AttributeError:
|
|
|
+ pass
|
|
|
+
|
|
|
result = Yedit.add_entry(tmp_copy, path, value, self.separator)
|
|
|
if result:
|
|
|
self.yaml_dict = tmp_copy
|
|
@@ -687,6 +708,32 @@ class OpenShiftCLIError(Exception):
|
|
|
pass
|
|
|
|
|
|
|
|
|
+ADDITIONAL_PATH_LOOKUPS = ['/usr/local/bin', os.path.expanduser('~/bin')]
|
|
|
+
|
|
|
+
|
|
|
+def locate_oc_binary():
|
|
|
+ ''' Find and return oc binary file '''
|
|
|
+ # https://github.com/openshift/openshift-ansible/issues/3410
|
|
|
+ # oc can be in /usr/local/bin in some cases, but that may not
|
|
|
+ # be in $PATH due to ansible/sudo
|
|
|
+ paths = os.environ.get("PATH", os.defpath).split(os.pathsep) + ADDITIONAL_PATH_LOOKUPS
|
|
|
+
|
|
|
+ oc_binary = 'oc'
|
|
|
+
|
|
|
+ # Use shutil.which if it is available, otherwise fallback to a naive path search
|
|
|
+ try:
|
|
|
+ which_result = shutil.which(oc_binary, path=os.pathsep.join(paths))
|
|
|
+ if which_result is not None:
|
|
|
+ oc_binary = which_result
|
|
|
+ except AttributeError:
|
|
|
+ for path in paths:
|
|
|
+ if os.path.exists(os.path.join(path, oc_binary)):
|
|
|
+ oc_binary = os.path.join(path, oc_binary)
|
|
|
+ break
|
|
|
+
|
|
|
+ return oc_binary
|
|
|
+
|
|
|
+
|
|
|
# pylint: disable=too-few-public-methods
|
|
|
class OpenShiftCLI(object):
|
|
|
''' Class to wrap the command line tools '''
|
|
@@ -700,6 +747,7 @@ class OpenShiftCLI(object):
|
|
|
self.verbose = verbose
|
|
|
self.kubeconfig = Utils.create_tmpfile_copy(kubeconfig)
|
|
|
self.all_namespaces = all_namespaces
|
|
|
+ self.oc_binary = locate_oc_binary()
|
|
|
|
|
|
# Pylint allows only 5 arguments to be passed.
|
|
|
# pylint: disable=too-many-arguments
|
|
@@ -901,19 +949,18 @@ class OpenShiftCLI(object):
|
|
|
# pylint: disable=too-many-arguments,too-many-branches
|
|
|
def openshift_cmd(self, cmd, oadm=False, output=False, output_type='json', input_data=None):
|
|
|
'''Base command for oc '''
|
|
|
- cmds = []
|
|
|
+ cmds = [self.oc_binary]
|
|
|
+
|
|
|
if oadm:
|
|
|
- cmds = ['oadm']
|
|
|
- else:
|
|
|
- cmds = ['oc']
|
|
|
+ cmds.append('adm')
|
|
|
+
|
|
|
+ cmds.extend(cmd)
|
|
|
|
|
|
if self.all_namespaces:
|
|
|
cmds.extend(['--all-namespaces'])
|
|
|
elif self.namespace is not None and self.namespace.lower() not in ['none', 'emtpy']: # E501
|
|
|
cmds.extend(['-n', self.namespace])
|
|
|
|
|
|
- cmds.extend(cmd)
|
|
|
-
|
|
|
rval = {}
|
|
|
results = ''
|
|
|
err = None
|
|
@@ -921,7 +968,10 @@ class OpenShiftCLI(object):
|
|
|
if self.verbose:
|
|
|
print(' '.join(cmds))
|
|
|
|
|
|
- returncode, stdout, stderr = self._run(cmds, input_data)
|
|
|
+ try:
|
|
|
+ returncode, stdout, stderr = self._run(cmds, input_data)
|
|
|
+ except OSError as ex:
|
|
|
+ returncode, stdout, stderr = 1, '', 'Failed to execute {}: {}'.format(subprocess.list2cmdline(cmds), ex)
|
|
|
|
|
|
rval = {"returncode": returncode,
|
|
|
"results": results,
|
|
@@ -973,6 +1023,7 @@ class Utils(object):
|
|
|
tmp = Utils.create_tmpfile(prefix=rname)
|
|
|
|
|
|
if ftype == 'yaml':
|
|
|
+ # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage
|
|
|
# pylint: disable=no-member
|
|
|
if hasattr(yaml, 'RoundTripDumper'):
|
|
|
Utils._write(tmp, yaml.dump(data, Dumper=yaml.RoundTripDumper))
|
|
@@ -1060,6 +1111,7 @@ class Utils(object):
|
|
|
contents = sfd.read()
|
|
|
|
|
|
if sfile_type == 'yaml':
|
|
|
+ # AUDIT:no-member makes sense here due to ruamel.YAML/PyYAML usage
|
|
|
# pylint: disable=no-member
|
|
|
if hasattr(yaml, 'RoundTripLoader'):
|
|
|
contents = yaml.load(contents, yaml.RoundTripLoader)
|