Coverage for heliumcli/utils.py: 94.92%

59 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-11-22 17:35 +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("\nThis tool cannot be used without a config file.\n") 

45 

46 sys.exit(1) 

47 else: 

48 print("") 

49 

50 _save_config(config_path, get_default_settings()) 

51 

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

53 _config_cache = yaml.safe_load(lines) 

54 else: 

55 # Ensure cache is up to date 

56 updated = False 

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

58 if key not in _config_cache: 

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

60 

61 updated = True 

62 

63 if updated: 

64 _save_config(config_path, _config_cache) 

65 

66 return _config_cache 

67 

68 

69def get_ansible_dir(): 

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

71 

72 

73def get_projects_dir(): 

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

75 

76 

77def parse_hosts_file(env): 

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

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

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

81 

82 hosts = [] 

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

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

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

86 

87 return hosts 

88 

89 

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

91 needs_update = False 

92 

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

94 if line.strip() != verification: 

95 needs_update = True 

96 

97 return needs_update 

98 

99 

100def get_copyright_name(): # pragma: no cover 

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

102 data = yaml.safe_load(lines) 

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

104 

105 

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

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

108 stdin=subprocess.PIPE, stdout=subprocess.PIPE, 

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

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

111 

112 

113def get_projects(config): 

114 return config["projects"] 

115 

116 

117def sort_tags(tags): 

118 # Remove tags that don't match semantic versioning 

119 version_tags = [] 

120 

121 for git_tag in tags: 

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

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

124 if pattern.match(cleaned_tag): 

125 version_tags.append(git_tag) 

126 

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

128 

129 return version_tags