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