Coverage for heliumcli/utils.py: 94.92%

59 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-12-04 15:02 +0000

1import os 

2import re 

3import subprocess 

4import sys 

5from builtins import input 

6 

7import yaml 

8 

9from .settings import VERSION, get_default_settings 

10 

11__author__ = "Alex Laird" 

12__copyright__ = "Copyright 2018, Helium Edu" 

13__version__ = "1.5.0" 

14 

15_config_cache = None 

16 

17 

18def get_title(): 

19 return """\ 

20 __ ___ ___ 

21 / /_ ___ / (_)_ ______ ___ _____/ (_) 

22 / __ \/ _ \/ / / / / / __ `__ \______/ ___/ / / 

23 / / / / __/ / / /_/ / / / / / /_____/ /__/ / / 

24/_/ /_/\___/_/_/\__,_/_/ /_/ /_/ \___/_/_/ 

25 v{} 

26""".format(VERSION) 

27 

28 

29def _save_config(config_path, config): 

30 with open(config_path, "w") as config_file: 

31 yaml.safe_dump(config, config_file) 

32 

33 

34def get_config(init=False): 

35 global _config_cache 

36 

37 config_path = os.path.abspath(os.environ.get("HELIUMCLI_CONFIG_PATH", ".heliumcli.yml")) 

38 

39 if not _config_cache: 

40 if not os.path.exists(config_path): 

41 if not init: # pragma: no cover 

42 response = input("No config file found; initialize a new project [Y/n]? ") 

43 if response.lower() not in ["y", "yes", ""]: 

44 print("\nError: this tool cannot be used without a config file.\n") 

45 sys.exit(1) 

46 else: 

47 print("") 

48 

49 _save_config(config_path, get_default_settings()) 

50 

51 with open(config_path, "r") as lines: 

52 _config_cache = yaml.safe_load(lines) 

53 else: 

54 # Ensure cache is up to date 

55 updated = False 

56 for key in get_default_settings().keys(): 

57 if key not in _config_cache: 

58 _config_cache[key] = get_default_settings()[key] 

59 

60 updated = True 

61 

62 if updated: 

63 _save_config(config_path, _config_cache) 

64 

65 return _config_cache 

66 

67 

68def get_ansible_dir(): 

69 return os.path.abspath(get_config()["ansibleRelativeDir"]) 

70 

71 

72def get_projects_dir(): 

73 return os.path.abspath(get_config()["projectsRelativeDir"]) 

74 

75 

76def parse_hosts_file(env): 

77 hosts_str = subprocess.Popen(["ansible", "all", "-i", os.path.join("hosts", env), "--list-hosts"], 

78 cwd=get_ansible_dir(), stdin=subprocess.PIPE, stdout=subprocess.PIPE, 

79 bufsize=1).stdout.read().decode("utf-8") 

80 

81 hosts = [] 

82 for line in hosts_str.split("\n")[1:]: 

83 if line.strip() != "": 

84 hosts.append(["ubuntu" if env != "devbox" else "vagrant", line.strip()]) 

85 

86 return hosts 

87 

88 

89def should_update(line, verification, start_needle, end_needle=""): 

90 needs_update = False 

91 

92 if line.strip().startswith(start_needle) and line.strip().endswith(end_needle): 

93 if line.strip() != verification: 

94 needs_update = True 

95 

96 return needs_update 

97 

98 

99def get_copyright_name(): # pragma: no cover 

100 with open(os.path.join(get_ansible_dir(), "group_vars", "all.yml"), "r") as lines: 

101 data = yaml.safe_load(lines) 

102 return data[get_config()["ansibleCopyrightNameVar"]] 

103 

104 

105def get_repo_name(repo_dir, remote_name): # pragma: no cover 

106 remote_url_str = subprocess.Popen(["git", "config", "--get", "remote.{}.url".format(remote_name)], cwd=repo_dir, 

107 stdin=subprocess.PIPE, stdout=subprocess.PIPE, 

108 bufsize=1).stdout.read().decode("utf-8") 

109 return os.path.basename(remote_url_str.strip()).rstrip(".git") 

110 

111 

112def get_projects(config): 

113 return config["projects"] 

114 

115 

116def sort_tags(tags): 

117 # Remove tags that don't match semantic versioning 

118 version_tags = [] 

119 

120 for git_tag in tags: 

121 cleaned_tag = git_tag.tag.tag.lstrip("v") 

122 pattern = re.compile("^[0-9\.]*$") 

123 if pattern.match(cleaned_tag): 

124 version_tags.append(git_tag) 

125 

126 version_tags.sort(key=lambda v: list(map(int, v.tag.tag.lstrip("v").split(".")))) 

127 

128 return version_tags