github.com/sleungcy/cli@v7.1.0+incompatible/actor/cfnetworkingaction/policy.go (about) 1 package cfnetworkingaction 2 3 import ( 4 "code.cloudfoundry.org/cfnetworking-cli-api/cfnetworking/cfnetv1" 5 "code.cloudfoundry.org/cli/actor/actionerror" 6 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" 7 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" 8 "code.cloudfoundry.org/cli/resources" 9 ) 10 11 type Policy struct { 12 SourceName string 13 DestinationName string 14 Protocol string 15 DestinationSpaceName string 16 DestinationOrgName string 17 StartPort int 18 EndPort int 19 } 20 21 func (actor Actor) AddNetworkPolicy(srcSpaceGUID, srcAppName, destSpaceGUID, destAppName, protocol string, startPort, endPort int) (Warnings, error) { 22 var allWarnings Warnings 23 24 srcApp, warnings, err := actor.CloudControllerClient.GetApplicationByNameAndSpace(srcAppName, srcSpaceGUID) 25 allWarnings = append(allWarnings, warnings...) 26 if err != nil { 27 return allWarnings, err 28 } 29 30 destApp, warnings, err := actor.CloudControllerClient.GetApplicationByNameAndSpace(destAppName, destSpaceGUID) 31 allWarnings = append(allWarnings, warnings...) 32 if err != nil { 33 return allWarnings, err 34 } 35 36 err = actor.NetworkingClient.CreatePolicies([]cfnetv1.Policy{ 37 { 38 Source: cfnetv1.PolicySource{ 39 ID: srcApp.GUID, 40 }, 41 Destination: cfnetv1.PolicyDestination{ 42 ID: destApp.GUID, 43 Protocol: cfnetv1.PolicyProtocol(protocol), 44 Ports: cfnetv1.Ports{ 45 Start: startPort, 46 End: endPort, 47 }, 48 }, 49 }, 50 }) 51 return allWarnings, err 52 } 53 54 func (actor Actor) NetworkPoliciesBySpace(spaceGUID string) ([]Policy, Warnings, error) { 55 var allWarnings Warnings 56 57 applications, warnings, err := actor.CloudControllerClient.GetApplications(ccv3.Query{ 58 Key: ccv3.SpaceGUIDFilter, 59 Values: []string{spaceGUID}, 60 }) 61 allWarnings = append(allWarnings, warnings...) 62 if err != nil { 63 return []Policy{}, allWarnings, err 64 } 65 66 policies, warnings, err := actor.getPoliciesForApplications(applications) 67 allWarnings = append(allWarnings, warnings...) 68 if err != nil { 69 return []Policy{}, allWarnings, err 70 } 71 72 return policies, allWarnings, nil 73 } 74 75 func (actor Actor) NetworkPoliciesBySpaceAndAppName(spaceGUID string, srcAppName string) ([]Policy, Warnings, error) { 76 var allWarnings Warnings 77 78 srcApp, warnings, err := actor.CloudControllerClient.GetApplicationByNameAndSpace(srcAppName, spaceGUID) 79 allWarnings = append(allWarnings, warnings...) 80 if err != nil { 81 return []Policy{}, allWarnings, err 82 } 83 84 policies, warnings, err := actor.getPoliciesForApplications([]resources.Application{srcApp}) 85 allWarnings = append(allWarnings, warnings...) 86 if err != nil { 87 return []Policy{}, allWarnings, err 88 } 89 90 return policies, allWarnings, nil 91 } 92 93 func (actor Actor) RemoveNetworkPolicy(srcSpaceGUID, srcAppName, destSpaceGUID, destAppName, protocol string, startPort, endPort int) (Warnings, error) { 94 var allWarnings Warnings 95 96 srcApp, warnings, err := actor.CloudControllerClient.GetApplicationByNameAndSpace(srcAppName, srcSpaceGUID) 97 allWarnings = append(allWarnings, warnings...) 98 if err != nil { 99 return allWarnings, err 100 } 101 102 destApp, warnings, err := actor.CloudControllerClient.GetApplicationByNameAndSpace(destAppName, destSpaceGUID) 103 allWarnings = append(allWarnings, warnings...) 104 if err != nil { 105 return allWarnings, err 106 } 107 108 policyToRemove := cfnetv1.Policy{ 109 Source: cfnetv1.PolicySource{ 110 ID: srcApp.GUID, 111 }, 112 Destination: cfnetv1.PolicyDestination{ 113 ID: destApp.GUID, 114 Protocol: cfnetv1.PolicyProtocol(protocol), 115 Ports: cfnetv1.Ports{ 116 Start: startPort, 117 End: endPort, 118 }, 119 }, 120 } 121 122 v1Policies, err := actor.NetworkingClient.ListPolicies(srcApp.GUID) 123 if err != nil { 124 return allWarnings, err 125 } 126 127 for _, v1Policy := range v1Policies { 128 if v1Policy == policyToRemove { 129 return allWarnings, actor.NetworkingClient.RemovePolicies([]cfnetv1.Policy{policyToRemove}) 130 } 131 } 132 133 return allWarnings, actionerror.PolicyDoesNotExistError{} 134 } 135 136 func filterPoliciesWithoutMatchingSourceGUIDs(v1Policies []cfnetv1.Policy, srcAppGUIDs []string) []cfnetv1.Policy { 137 srcGUIDsSet := map[string]struct{}{} 138 for _, srcGUID := range srcAppGUIDs { 139 srcGUIDsSet[srcGUID] = struct{}{} 140 } 141 142 var toReturn []cfnetv1.Policy 143 for _, policy := range v1Policies { 144 if _, ok := srcGUIDsSet[policy.Source.ID]; ok { 145 toReturn = append(toReturn, policy) 146 } 147 } 148 149 return toReturn 150 } 151 152 func uniqueSpaceGUIDs(applications []resources.Application) []string { 153 var spaceGUIDs []string 154 occurrences := map[string]struct{}{} 155 for _, app := range applications { 156 if _, ok := occurrences[app.SpaceGUID]; !ok { 157 spaceGUIDs = append(spaceGUIDs, app.SpaceGUID) 158 occurrences[app.SpaceGUID] = struct{}{} 159 } 160 } 161 return spaceGUIDs 162 } 163 164 func uniqueOrgGUIDs(spaces []resources.Space) []string { 165 var orgGUIDs []string 166 occurrences := map[string]struct{}{} 167 for _, space := range spaces { 168 orgGUID := space.Relationships[constant.RelationshipTypeOrganization].GUID 169 170 if _, ok := occurrences[orgGUID]; !ok { 171 orgGUIDs = append(orgGUIDs, orgGUID) 172 occurrences[orgGUID] = struct{}{} 173 } 174 } 175 return orgGUIDs 176 } 177 178 func uniqueDestGUIDs(policies []cfnetv1.Policy) []string { 179 var destAppGUIDs []string 180 occurrences := map[string]struct{}{} 181 for _, policy := range policies { 182 if _, ok := occurrences[policy.Destination.ID]; !ok { 183 destAppGUIDs = append(destAppGUIDs, policy.Destination.ID) 184 occurrences[policy.Destination.ID] = struct{}{} 185 } 186 } 187 return destAppGUIDs 188 } 189 190 func (actor Actor) orgNamesBySpaceGUID(spaces []resources.Space) (map[string]string, ccv3.Warnings, error) { 191 orgs, warnings, err := actor.CloudControllerClient.GetOrganizations(ccv3.Query{ 192 Key: ccv3.GUIDFilter, 193 Values: uniqueOrgGUIDs(spaces), 194 }) 195 if err != nil { 196 return nil, warnings, err 197 } 198 199 orgNamesByGUID := make(map[string]string, len(orgs)) 200 for _, org := range orgs { 201 orgNamesByGUID[org.GUID] = org.Name 202 } 203 204 orgNamesBySpaceGUID := make(map[string]string, len(spaces)) 205 for _, space := range spaces { 206 orgGUID := space.Relationships[constant.RelationshipTypeOrganization].GUID 207 orgNamesBySpaceGUID[space.GUID] = orgNamesByGUID[orgGUID] 208 } 209 210 return orgNamesBySpaceGUID, warnings, nil 211 } 212 213 func (actor Actor) getPoliciesForApplications(applications []resources.Application) ([]Policy, ccv3.Warnings, error) { 214 var allWarnings ccv3.Warnings 215 216 var srcAppGUIDs []string 217 for _, app := range applications { 218 srcAppGUIDs = append(srcAppGUIDs, app.GUID) 219 } 220 221 v1Policies, err := actor.NetworkingClient.ListPolicies(srcAppGUIDs...) 222 if err != nil { 223 return []Policy{}, allWarnings, err 224 } 225 226 // ListPolicies will return policies with the app guids in either the source or destination. 227 // It needs to be further filtered to only get policies with the app guids in the source. 228 v1Policies = filterPoliciesWithoutMatchingSourceGUIDs(v1Policies, srcAppGUIDs) 229 230 destAppGUIDs := uniqueDestGUIDs(v1Policies) 231 232 destApplications, warnings, err := actor.CloudControllerClient.GetApplications(ccv3.Query{ 233 Key: ccv3.GUIDFilter, 234 Values: destAppGUIDs, 235 }) 236 allWarnings = append(allWarnings, warnings...) 237 if err != nil { 238 return []Policy{}, allWarnings, err 239 } 240 241 applications = append(applications, destApplications...) 242 243 spaces, _, warnings, err := actor.CloudControllerClient.GetSpaces(ccv3.Query{ 244 Key: ccv3.GUIDFilter, 245 Values: uniqueSpaceGUIDs(applications), 246 }) 247 allWarnings = append(allWarnings, warnings...) 248 if err != nil { 249 return []Policy{}, allWarnings, err 250 } 251 252 spaceNamesByGUID := make(map[string]string, len(spaces)) 253 for _, destSpace := range spaces { 254 spaceNamesByGUID[destSpace.GUID] = destSpace.Name 255 } 256 257 orgNamesBySpaceGUID, warnings, err := actor.orgNamesBySpaceGUID(spaces) 258 allWarnings = append(allWarnings, warnings...) 259 if err != nil { 260 return []Policy{}, allWarnings, err 261 } 262 263 appByGUID := map[string]resources.Application{} 264 for _, app := range applications { 265 appByGUID[app.GUID] = app 266 } 267 268 var policies []Policy 269 for _, v1Policy := range v1Policies { 270 destination := appByGUID[v1Policy.Destination.ID] 271 272 policies = append(policies, Policy{ 273 SourceName: appByGUID[v1Policy.Source.ID].Name, 274 DestinationName: destination.Name, 275 Protocol: string(v1Policy.Destination.Protocol), 276 StartPort: v1Policy.Destination.Ports.Start, 277 EndPort: v1Policy.Destination.Ports.End, 278 DestinationSpaceName: spaceNamesByGUID[destination.SpaceGUID], 279 DestinationOrgName: orgNamesBySpaceGUID[destination.SpaceGUID], 280 }) 281 } 282 283 return policies, allWarnings, nil 284 }