1 package edgecliutils
2
3 import (
4 "errors"
5 "fmt"
6
7 "edge-infra.dev/pkg/edge/api/graph/model"
8 "edge-infra.dev/pkg/edge/api/utils"
9 "edge-infra.dev/pkg/lib/networkvalidator"
10 )
11
12 func makeTermInput(currentTerminal *model.Terminal, lane, role, class, mac, ipaddr, gateway4addr, gateway6addr, discoverDisks, terminalDiskID, devicePath *string, prefixLen *int, dhcp4, dhcp6, includeDisk, expectEmpty *bool, family model.InetType) (*model.TerminalIDInput, error) {
13
14 termInput := &model.TerminalIDInput{
15 TerminalID: currentTerminal.TerminalID,
16 TerminalValues: &model.TerminalUpdateInput{
17 Lane: lane,
18 Disks: []*model.TerminalDiskIDInput{},
19 Interfaces: []*model.TerminalInterfaceIDInput{},
20 },
21 }
22 if role != nil {
23 rl := model.TerminalRoleType(*role)
24 termInput.TerminalValues.Role = &rl
25 }
26 if class != nil {
27 cl := model.TerminalClassType(*class)
28 termInput.TerminalValues.Class = &cl
29 }
30 if discoverDisks != nil {
31 dd := model.TerminalDiscoverDisksType(*discoverDisks)
32 termInput.TerminalValues.DiscoverDisks = &dd
33 }
34
35 termInput = mergeIntoTermInput(termInput, currentTerminal)
36
37 if terminalDiskID != nil {
38 termInput.TerminalValues.Disks = []*model.TerminalDiskIDInput{
39 {
40 TerminalDiskID: *terminalDiskID,
41 TerminalDiskValues: &model.TerminalDiskUpdateInput{
42 DevicePath: devicePath,
43 IncludeDisk: includeDisk,
44 ExpectEmpty: expectEmpty,
45 },
46 },
47 }
48 }
49
50
51
52 if mac != nil {
53 ifaceInput := &model.TerminalInterfaceIDInput{
54 TerminalInterfaceID: "",
55 TerminalInterfaceValues: &model.TerminalInterfaceUpdateInput{
56 MacAddress: mac,
57 Dhcp4: dhcp4,
58 Dhcp6: dhcp6,
59 Addresses: []*model.TerminalAddressIDInput{},
60 Gateway4: gateway4addr,
61 Gateway6: gateway6addr,
62 },
63 }
64
65 addrInput := &model.TerminalAddressIDInput{
66 TerminalAddressID: "",
67 TerminalAddressValues: &model.TerminalAddressUpdateInput{
68 IP: ipaddr,
69 PrefixLen: prefixLen,
70 Family: &family,
71 },
72 }
73
74 err := updateIfaceOfTermInput(termInput.TerminalValues, ifaceInput, currentTerminal.Interfaces, addrInput)
75 if err != nil {
76 return nil, err
77 }
78 }
79
80 return termInput, nil
81 }
82
83
84
85 func mergeIntoTermInput(newTerm *model.TerminalIDInput, currentTerminal *model.Terminal) *model.TerminalIDInput {
86 newTerm.TerminalValues.Lane = utils.AssignNotNil(currentTerminal.Lane, newTerm.TerminalValues.Lane)
87 newTerm.TerminalValues.Role = utils.AssignNotNil(¤tTerminal.Role, newTerm.TerminalValues.Role)
88 newTerm.TerminalValues.Class = utils.AssignNotNil(currentTerminal.Class, newTerm.TerminalValues.Class)
89
90
91
92
93 return newTerm
94 }
95
96
97 func updateIfaceOfTermInput(newTerm *model.TerminalUpdateInput, newIface *model.TerminalInterfaceIDInput, currentTerminalInterfaces []*model.TerminalInterface, newAddr *model.TerminalAddressIDInput) error {
98 idx, matchingIface := FindFirst(func(iface *model.TerminalInterface) bool {
99 return iface.MacAddress == *newIface.TerminalInterfaceValues.MacAddress
100 }, currentTerminalInterfaces)
101
102 if matchingIface == nil {
103 return fmt.Errorf("no matching interface found with mac address %v, cannot modify non-existent interface", *newIface.TerminalInterfaceValues.MacAddress)
104 }
105 mergedIface, err := mergeIntoTermIfaceInput(newIface, matchingIface, newAddr)
106 if err != nil {
107 return err
108 }
109 newTerm.Interfaces = SafeInsert(newTerm.Interfaces, idx, mergedIface)
110
111 return nil
112 }
113
114
115
116
117 func mergeIntoTermIfaceInput(newIface *model.TerminalInterfaceIDInput, currentIface *model.TerminalInterface, newAddr *model.TerminalAddressIDInput) (*model.TerminalInterfaceIDInput, error) {
118
119 newIface.TerminalInterfaceID = currentIface.TerminalInterfaceID
120
121 newIface.TerminalInterfaceValues.Dhcp4 = utils.AssignNotNil(¤tIface.Dhcp4, newIface.TerminalInterfaceValues.Dhcp4)
122 newIface.TerminalInterfaceValues.Dhcp6 = utils.AssignNotNil(¤tIface.Dhcp6, newIface.TerminalInterfaceValues.Dhcp6)
123 newIface.TerminalInterfaceValues.Gateway4 = utils.AssignNotNil(currentIface.Gateway4, newIface.TerminalInterfaceValues.Gateway4)
124 newIface.TerminalInterfaceValues.Gateway6 = utils.AssignNotNil(currentIface.Gateway6, newIface.TerminalInterfaceValues.Gateway6)
125 newIface.TerminalInterfaceValues.MacAddress = utils.AssignNotNil(¤tIface.MacAddress, newIface.TerminalInterfaceValues.MacAddress)
126
127 if newAddr != nil {
128 err := updateAddressOfTermIfaceInput(newIface, newAddr, currentIface.Addresses)
129 if err != nil {
130 return nil, err
131 }
132 }
133
134 err := validateTermIfaceInput(newIface)
135 if err != nil {
136 return nil, err
137 }
138
139 return newIface, nil
140 }
141
142
143
144
145
146
147
148 func updateAddressOfTermIfaceInput(newIface *model.TerminalInterfaceIDInput, newAddr *model.TerminalAddressIDInput, currentTerminalAddresses []*model.TerminalAddress) error {
149 idx, inetAddr := FindFirst(func(addr *model.TerminalAddress) bool {
150 return addr.Family == *newAddr.TerminalAddressValues.Family
151 }, currentTerminalAddresses)
152
153 if inetAddr == nil {
154 return fmt.Errorf("no %v address found for interface with ID %v, cannot modify non-existent address", *newAddr.TerminalAddressValues.Family, newIface.TerminalInterfaceID)
155 }
156
157 addr, err := mergeIntoTermAddrInput(newAddr, inetAddr)
158 if err != nil {
159 return err
160 }
161 newIface.TerminalInterfaceValues.Addresses = SafeInsert(newIface.TerminalInterfaceValues.Addresses, idx, addr)
162
163 return nil
164 }
165
166 func mergeIntoTermAddrInput(newAddress *model.TerminalAddressIDInput, currentAddress *model.TerminalAddress) (*model.TerminalAddressIDInput, error) {
167
168 newAddress.TerminalAddressID = currentAddress.TerminalAddressID
169
170 newAddress.TerminalAddressValues.IP = utils.AssignNotNil(currentAddress.IP, newAddress.TerminalAddressValues.IP)
171 newAddress.TerminalAddressValues.Family = utils.AssignNotNil(¤tAddress.Family, newAddress.TerminalAddressValues.Family)
172 newAddress.TerminalAddressValues.PrefixLen = utils.AssignNotNil(¤tAddress.PrefixLen, newAddress.TerminalAddressValues.PrefixLen)
173
174 err := validateTermAddrInput(newAddress)
175 if err != nil {
176 return nil, err
177 }
178
179 return newAddress, nil
180 }
181
182 func validateTermIfaceInput(iface *model.TerminalInterfaceIDInput) error {
183 if iface.TerminalInterfaceValues.Dhcp4 != nil && !*iface.TerminalInterfaceValues.Dhcp4 {
184
185 if iface.TerminalInterfaceValues.Gateway4 == nil {
186 return errors.New("DHCP4 is set to false - you must provide a value for gateway4")
187 } else if !networkvalidator.ValidateIP(*iface.TerminalInterfaceValues.Gateway4) {
188 return fmt.Errorf("invalid gateway4 address: %s", *iface.TerminalInterfaceValues.Gateway4)
189 }
190 }
191
192 if iface.TerminalInterfaceValues.MacAddress != nil {
193 _, err := networkvalidator.ValidateMacAddress(*iface.TerminalInterfaceValues.MacAddress)
194 if err != nil {
195 return err
196 }
197 }
198
199 return nil
200 }
201
202 func validateTermAddrInput(addr *model.TerminalAddressIDInput) error {
203 if addr.TerminalAddressID == "" {
204 return fmt.Errorf("invalid/missing terminal address ID")
205 }
206 if addr.TerminalAddressValues.IP != nil {
207 if !networkvalidator.ValidateIP(*addr.TerminalAddressValues.IP) {
208 return fmt.Errorf("invalid/missing terminal address IP")
209 }
210 if addr.TerminalAddressValues.PrefixLen != nil && !networkvalidator.ValidateCIDR(*addr.TerminalAddressValues.IP, *addr.TerminalAddressValues.PrefixLen) {
211 return fmt.Errorf("invalid/missing terminal address IP")
212 }
213 }
214 return nil
215 }
216
View as plain text