Coverage for src/meshadmin/server/networks/views/rollout.py: 79%

107 statements  

« prev     ^ index     » next       coverage.py v7.6.12, created at 2025-04-10 16:08 +0200

1from django.contrib.auth.mixins import LoginRequiredMixin 

2from django.http import HttpResponseRedirect 

3from django.shortcuts import get_object_or_404, redirect 

4from django.urls import reverse_lazy 

5from django.views.generic import CreateView, DeleteView, DetailView, UpdateView, View 

6 

7from meshadmin.server.networks.mixins import NetworkPermissionMixin 

8from meshadmin.server.networks.models import ConfigRollout, Host, Network 

9 

10 

11class RolloutCreateView(LoginRequiredMixin, NetworkPermissionMixin, CreateView): 

12 model = ConfigRollout 

13 template_name = "networks/rollout/create.html" 

14 fields = ["name", "notes"] 

15 

16 def get_network(self): 

17 network_id = self.kwargs.get("network_id") 

18 if network_id: 

19 return get_object_or_404(Network, id=network_id) 

20 return None 

21 

22 def get_context_data(self, **kwargs): 

23 context = super().get_context_data(**kwargs) 

24 network = self.get_network() 

25 context["network"] = network 

26 

27 host_ids = self.request.GET.get("hosts", "").split(",") 

28 if host_ids and host_ids[0]: 

29 context["preselected_hosts"] = Host.objects.filter( 

30 id__in=host_ids, network=network 

31 ) 

32 

33 context["hosts"] = Host.objects.filter(network=network) 

34 return context 

35 

36 def form_valid(self, form): 

37 form.instance.network_id = self.kwargs["network_id"] 

38 response = super().form_valid(form) 

39 

40 selected_hosts = self.request.POST.getlist("hosts") 

41 if selected_hosts: 

42 self.object.target_hosts.set(selected_hosts) 

43 Host.objects.filter(id__in=selected_hosts).update(config_freeze=True) 

44 

45 return response 

46 

47 def get_success_url(self): 

48 return ( 

49 reverse_lazy( 

50 "networks:network-detail", kwargs={"pk": self.kwargs["network_id"]} 

51 ) 

52 + "#rollouts-section" 

53 ) 

54 

55 

56class RolloutDetailView(LoginRequiredMixin, NetworkPermissionMixin, DetailView): 

57 model = ConfigRollout 

58 template_name = "networks/rollout/detail.html" 

59 

60 def get_network(self): 

61 return self.get_object().network 

62 

63 def get_context_data(self, **kwargs): 

64 context = super().get_context_data(**kwargs) 

65 context["pending_hosts"] = self.object.target_hosts.exclude( 

66 id__in=self.object.completed_hosts.values_list("id", flat=True) 

67 ) 

68 return context 

69 

70 

71class UnfreezeHostConfigView(LoginRequiredMixin, NetworkPermissionMixin, View): 

72 def get_network(self): 

73 rollout = get_object_or_404(ConfigRollout, id=self.kwargs.get("pk")) 

74 return rollout.network 

75 

76 def post(self, request, pk): 

77 rollout = get_object_or_404(ConfigRollout, id=pk) 

78 host_id = request.POST.get("host_id") 

79 if host_id: 

80 host = get_object_or_404(Host, id=host_id) 

81 if host not in rollout.completed_hosts.all(): 

82 try: 

83 host.config_freeze = False 

84 host.save() 

85 rollout.completed_hosts.add(host) 

86 except Exception: 

87 rollout.status = "FAILED" 

88 rollout.save() 

89 else: 

90 pending_hosts = rollout.target_hosts.exclude( 

91 id__in=rollout.completed_hosts.values_list("id", flat=True) 

92 ) 

93 for host in pending_hosts: 

94 try: 

95 host.config_freeze = False 

96 host.save() 

97 rollout.completed_hosts.add(host) 

98 except Exception: 

99 rollout.status = "FAILED" 

100 rollout.save() 

101 return redirect("networks:rollout-detail", pk=pk) 

102 

103 if not rollout.target_hosts.exclude( 

104 id__in=rollout.completed_hosts.values_list("id", flat=True) 

105 ).exists(): 

106 rollout.status = "COMPLETED" 

107 rollout.save() 

108 

109 return redirect("networks:rollout-detail", pk=pk) 

110 

111 

112class RolloutUpdateView(LoginRequiredMixin, NetworkPermissionMixin, UpdateView): 

113 model = ConfigRollout 

114 template_name = "networks/rollout/edit.html" 

115 fields = ["name", "notes"] 

116 

117 def get_network(self): 

118 return self.get_object().network 

119 

120 def get_context_data(self, **kwargs): 

121 context = super().get_context_data(**kwargs) 

122 context["hosts"] = Host.objects.filter(network=self.get_network()) 

123 return context 

124 

125 def form_valid(self, form): 

126 response = super().form_valid(form) 

127 selected_hosts = self.request.POST.getlist("hosts") 

128 if selected_hosts: 

129 removed_hosts = self.object.target_hosts.exclude(id__in=selected_hosts) 

130 removed_hosts.update(config_freeze=False) 

131 self.object.target_hosts.set(selected_hosts) 

132 Host.objects.filter(id__in=selected_hosts).update(config_freeze=True) 

133 

134 return response 

135 

136 def get_success_url(self): 

137 return reverse_lazy("networks:rollout-detail", kwargs={"pk": self.object.pk}) 

138 

139 

140class RolloutDeleteView(LoginRequiredMixin, NetworkPermissionMixin, DeleteView): 

141 model = ConfigRollout 

142 template_name = "networks/rollout/delete.html" 

143 

144 def get_network(self): 

145 return self.get_object().network 

146 

147 def post(self, request, *args, **kwargs): 

148 self.object = self.get_object() 

149 self.object.target_hosts.all().update(config_freeze=False) 

150 network_id = self.object.network_id 

151 self.object.delete() 

152 return HttpResponseRedirect( 

153 reverse_lazy("networks:network-detail", kwargs={"pk": network_id}) 

154 + "#rollouts-section" 

155 )