diff --git a/actor/actionerror/route_policy_not_found_error.go b/actor/actionerror/route_policy_not_found_error.go new file mode 100644 index 00000000000..31410af83be --- /dev/null +++ b/actor/actionerror/route_policy_not_found_error.go @@ -0,0 +1,11 @@ +package actionerror + +import "fmt" + +type RoutePolicyNotFoundError struct { + Source string +} + +func (e RoutePolicyNotFoundError) Error() string { + return fmt.Sprintf("Route policy with source '%s' not found.", e.Source) +} diff --git a/actor/v7action/cloud_controller_client.go b/actor/v7action/cloud_controller_client.go index c0dc6b8c641..eeced084370 100644 --- a/actor/v7action/cloud_controller_client.go +++ b/actor/v7action/cloud_controller_client.go @@ -20,6 +20,7 @@ type CloudControllerClient interface { CancelDeployment(deploymentGUID string) (ccv3.Warnings, error) ContinueDeployment(deploymentGUID string) (ccv3.Warnings, error) CopyPackage(sourcePackageGUID string, targetAppGUID string) (resources.Package, ccv3.Warnings, error) + CreateRoutePolicy(routePolicy resources.RoutePolicy) (resources.RoutePolicy, ccv3.Warnings, error) CreateApplication(app resources.Application) (resources.Application, ccv3.Warnings, error) CreateApplicationDeployment(dep resources.Deployment) (string, ccv3.Warnings, error) CreateApplicationProcessScale(appGUID string, process resources.Process) (resources.Process, ccv3.Warnings, error) @@ -42,6 +43,7 @@ type CloudControllerClient interface { CreateSpace(space resources.Space) (resources.Space, ccv3.Warnings, error) CreateSpaceQuota(spaceQuota resources.SpaceQuota) (resources.SpaceQuota, ccv3.Warnings, error) CreateUser(userGUID string) (resources.User, ccv3.Warnings, error) + DeleteRoutePolicy(guid string) (ccv3.JobURL, ccv3.Warnings, error) DeleteApplication(guid string) (ccv3.JobURL, ccv3.Warnings, error) DeleteApplicationProcessInstance(appGUID string, processType string, instanceIndex int) (ccv3.Warnings, error) DeleteBuildpack(buildpackGUID string) (ccv3.JobURL, ccv3.Warnings, error) @@ -63,6 +65,7 @@ type CloudControllerClient interface { DeleteUser(userGUID string) (ccv3.JobURL, ccv3.Warnings, error) DownloadDroplet(dropletGUID string) ([]byte, ccv3.Warnings, error) EntitleIsolationSegmentToOrganizations(isoGUID string, orgGUIDs []string) (resources.RelationshipList, ccv3.Warnings, error) + GetRoutePolicies(query ...ccv3.Query) ([]resources.RoutePolicy, ccv3.IncludedResources, ccv3.Warnings, error) GetApplicationByNameAndSpace(appName string, spaceGUID string) (resources.Application, ccv3.Warnings, error) GetApplicationDropletCurrent(appGUID string) (resources.Droplet, ccv3.Warnings, error) GetApplicationEnvironment(appGUID string) (ccv3.Environment, ccv3.Warnings, error) diff --git a/actor/v7action/domain.go b/actor/v7action/domain.go index 21cabe6abc5..f7307da5ade 100644 --- a/actor/v7action/domain.go +++ b/actor/v7action/domain.go @@ -24,7 +24,7 @@ func (actor Actor) CheckRoute(domainName string, hostname string, path string, p return matches, allWarnings, err } -func (actor Actor) CreateSharedDomain(domainName string, internal bool, routerGroupName string) (Warnings, error) { +func (actor Actor) CreateSharedDomain(domainName string, internal bool, routerGroupName string, enforceAccessRules bool, accessRulesScope string) (Warnings, error) { allWarnings := Warnings{} routerGroupGUID := "" @@ -37,17 +37,25 @@ func (actor Actor) CreateSharedDomain(domainName string, internal bool, routerGr routerGroupGUID = routerGroup.GUID } - _, warnings, err := actor.CloudControllerClient.CreateDomain(resources.Domain{ + domain := resources.Domain{ Name: domainName, Internal: types.NullBool{IsSet: true, Value: internal}, RouterGroup: routerGroupGUID, - }) + } + + // Set enforce_route_policies if specified + if enforceAccessRules { + domain.EnforceRoutePolicies = types.NullBool{IsSet: true, Value: true} + domain.RoutePoliciesScope = accessRulesScope + } + + _, warnings, err := actor.CloudControllerClient.CreateDomain(domain) allWarnings = append(allWarnings, Warnings(warnings)...) return allWarnings, err } -func (actor Actor) CreatePrivateDomain(domainName string, orgName string) (Warnings, error) { +func (actor Actor) CreatePrivateDomain(domainName string, orgName string, enforceAccessRules bool, accessRulesScope string) (Warnings, error) { allWarnings := Warnings{} organization, warnings, err := actor.GetOrganizationByName(orgName) allWarnings = append(allWarnings, warnings...) @@ -55,10 +63,19 @@ func (actor Actor) CreatePrivateDomain(domainName string, orgName string) (Warni if err != nil { return allWarnings, err } - _, apiWarnings, err := actor.CloudControllerClient.CreateDomain(resources.Domain{ + + domain := resources.Domain{ Name: domainName, OrganizationGUID: organization.GUID, - }) + } + + // Set enforce_route_policies if specified + if enforceAccessRules { + domain.EnforceRoutePolicies = types.NullBool{IsSet: true, Value: true} + domain.RoutePoliciesScope = accessRulesScope + } + + _, apiWarnings, err := actor.CloudControllerClient.CreateDomain(domain) actorWarnings := Warnings(apiWarnings) allWarnings = append(allWarnings, actorWarnings...) diff --git a/actor/v7action/domain_test.go b/actor/v7action/domain_test.go index 68050c6cefb..db30783af06 100644 --- a/actor/v7action/domain_test.go +++ b/actor/v7action/domain_test.go @@ -118,7 +118,7 @@ var _ = Describe("Domain Actions", func() { ) JustBeforeEach(func() { - warnings, executeErr = actor.CreateSharedDomain("the-domain-name", true, routerGroup) + warnings, executeErr = actor.CreateSharedDomain("the-domain-name", true, routerGroup, false, "") }) BeforeEach(func() { @@ -191,7 +191,7 @@ var _ = Describe("Domain Actions", func() { }) It("delegates to the cloud controller client", func() { - warnings, executeErr := actor.CreatePrivateDomain("private-domain-name", "org-name") + warnings, executeErr := actor.CreatePrivateDomain("private-domain-name", "org-name", false, "") Expect(executeErr).To(MatchError("create-error")) Expect(warnings).To(ConsistOf("get-orgs-warning", "create-warning-1", "create-warning-2")) diff --git a/actor/v7action/route_policy.go b/actor/v7action/route_policy.go new file mode 100644 index 00000000000..07068fb9745 --- /dev/null +++ b/actor/v7action/route_policy.go @@ -0,0 +1,382 @@ +package v7action + +import ( + "code.cloudfoundry.org/cli/v9/actor/actionerror" + "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3" + "code.cloudfoundry.org/cli/v9/resources" +) + +func (actor Actor) AddRoutePolicy(domainName, source, hostname, path string) (Warnings, error) { + allWarnings := Warnings{} + + // Get the domain to ensure it exists and supports route policies + domain, warnings, err := actor.GetDomainByName(domainName) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + // Find the route + routes, routeWarnings, err := actor.GetRoutesByDomain(domain.GUID, hostname, path) + allWarnings = append(allWarnings, routeWarnings...) + if err != nil { + return allWarnings, err + } + + if len(routes) == 0 { + return allWarnings, actionerror.RouteNotFoundError{ + Host: hostname, + DomainName: domainName, + Path: path, + } + } + + route := routes[0] + + // Create the route policy + routePolicy := resources.RoutePolicy{ + Source: source, + RouteGUID: route.GUID, + } + + _, apiWarnings, err := actor.CloudControllerClient.CreateRoutePolicy(routePolicy) + allWarnings = append(allWarnings, Warnings(apiWarnings)...) + + return allWarnings, err +} + +func (actor Actor) GetRoutePoliciesByRoute(domainName, hostname, path string) ([]resources.RoutePolicy, Warnings, error) { + allWarnings := Warnings{} + + // Get the domain + domain, warnings, err := actor.GetDomainByName(domainName) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return nil, allWarnings, err + } + + // Find the route + routes, routeWarnings, err := actor.GetRoutesByDomain(domain.GUID, hostname, path) + allWarnings = append(allWarnings, routeWarnings...) + if err != nil { + return nil, allWarnings, err + } + + if len(routes) == 0 { + return nil, allWarnings, actionerror.RouteNotFoundError{ + Host: hostname, + DomainName: domainName, + Path: path, + } + } + + route := routes[0] + + // Get route policies for this route + routePolicies, _, apiWarnings, err := actor.CloudControllerClient.GetRoutePolicies( + ccv3.Query{Key: ccv3.RouteGUIDFilter, Values: []string{route.GUID}}, + ) + allWarnings = append(allWarnings, Warnings(apiWarnings)...) + + var policies []resources.RoutePolicy + for _, policy := range routePolicies { + policies = append(policies, resources.RoutePolicy(policy)) + } + + return policies, allWarnings, err +} + +func (actor Actor) DeleteRoutePolicyBySource(domainName, source, hostname, path string) (Warnings, error) { + allWarnings := Warnings{} + + // Get the domain + domain, warnings, err := actor.GetDomainByName(domainName) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return allWarnings, err + } + + // Find the route + routes, routeWarnings, err := actor.GetRoutesByDomain(domain.GUID, hostname, path) + allWarnings = append(allWarnings, routeWarnings...) + if err != nil { + return allWarnings, err + } + + if len(routes) == 0 { + return allWarnings, actionerror.RouteNotFoundError{ + Host: hostname, + DomainName: domainName, + Path: path, + } + } + + route := routes[0] + + // Get route policies for this route to find the one with matching source + routePolicies, _, apiWarnings, err := actor.CloudControllerClient.GetRoutePolicies( + ccv3.Query{Key: ccv3.RouteGUIDFilter, Values: []string{route.GUID}}, + ) + allWarnings = append(allWarnings, Warnings(apiWarnings)...) + if err != nil { + return allWarnings, err + } + + // Find the policy with matching source + var policyGUID string + for _, policy := range routePolicies { + if policy.Source == source { + policyGUID = policy.GUID + break + } + } + + if policyGUID == "" { + return allWarnings, actionerror.RoutePolicyNotFoundError{Source: source} + } + + // Delete the route policy + _, deleteWarnings, err := actor.CloudControllerClient.DeleteRoutePolicy(policyGUID) + allWarnings = append(allWarnings, Warnings(deleteWarnings)...) + + return allWarnings, err +} + +// GetRoutesByDomain gets routes for a domain with optional hostname and path filters +func (actor Actor) GetRoutesByDomain(domainGUID, hostname, path string) ([]resources.Route, Warnings, error) { + queries := []ccv3.Query{ + {Key: ccv3.DomainGUIDFilter, Values: []string{domainGUID}}, + } + + if hostname != "" { + queries = append(queries, ccv3.Query{Key: ccv3.HostsFilter, Values: []string{hostname}}) + } + + if path != "" { + queries = append(queries, ccv3.Query{Key: ccv3.PathsFilter, Values: []string{path}}) + } + + ccv3Routes, warnings, err := actor.CloudControllerClient.GetRoutes(queries...) + if err != nil { + return nil, Warnings(warnings), err + } + + var routes []resources.Route + for _, route := range ccv3Routes { + routes = append(routes, resources.Route(route)) + } + + return routes, Warnings(warnings), nil +} + +// RoutePolicyWithRoute combines a route policy with its associated route information +type RoutePolicyWithRoute struct { + resources.RoutePolicy + Route resources.Route + DomainName string + ScopeType string // "app", "space", "org", or "any" + SourceName string // Resolved source name (app/space/org) or empty string +} + +// GetRoutePoliciesForSpace gets all route policies for routes in a space with optional filters +func (actor Actor) GetRoutePoliciesForSpace( + spaceGUID string, + domainName string, + hostname string, + path string, + labelSelector string, +) ([]RoutePolicyWithRoute, Warnings, error) { + allWarnings := Warnings{} + + // Build query for route policies filtered by space, with included routes + queries := []ccv3.Query{ + {Key: ccv3.SpaceGUIDFilter, Values: []string{spaceGUID}}, + {Key: ccv3.Include, Values: []string{"route"}}, + } + + // Add label selector if provided + if labelSelector != "" { + queries = append(queries, ccv3.Query{Key: ccv3.LabelSelectorFilter, Values: []string{labelSelector}}) + } + + // Fetch route policies directly by space GUID with included routes (single API call) + routePolicies, includedResources, apiWarnings, err := actor.CloudControllerClient.GetRoutePolicies(queries...) + allWarnings = append(allWarnings, Warnings(apiWarnings)...) + if err != nil { + return nil, allWarnings, err + } + + if len(routePolicies) == 0 { + // No route policies found - return empty list, not an error + return []RoutePolicyWithRoute{}, allWarnings, nil + } + + // Build route lookup map from included resources + routeByGUID := make(map[string]resources.Route) + for _, route := range includedResources.Routes { + routeByGUID[route.GUID] = route + } + + // Apply optional filters to the included routes + if domainName != "" { + domain, warnings, err := actor.GetDomainByName(domainName) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return nil, allWarnings, err + } + // Filter routes by domain GUID + filteredRoutes := make(map[string]resources.Route) + for guid, route := range routeByGUID { + if route.DomainGUID == domain.GUID { + filteredRoutes[guid] = route + } + } + routeByGUID = filteredRoutes + } + + if hostname != "" { + // Filter routes by hostname + filteredRoutes := make(map[string]resources.Route) + for guid, route := range routeByGUID { + if route.Host == hostname { + filteredRoutes[guid] = route + } + } + routeByGUID = filteredRoutes + } + + if path != "" { + // Filter routes by path + filteredRoutes := make(map[string]resources.Route) + for guid, route := range routeByGUID { + if route.Path == path { + filteredRoutes[guid] = route + } + } + routeByGUID = filteredRoutes + } + + // Build domain name cache + domainCache := make(map[string]string) + for _, route := range routeByGUID { + if _, exists := domainCache[route.DomainGUID]; !exists { + domain, warnings, err := actor.GetDomain(route.DomainGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + // If we can't get the domain, use the GUID as fallback + domainCache[route.DomainGUID] = route.DomainGUID + } else { + domainCache[route.DomainGUID] = domain.Name + } + } + } + + // Build results with route information and resolved sources + // Only include route policies whose routes match the filters + var results []RoutePolicyWithRoute + for _, policy := range routePolicies { + route, exists := routeByGUID[policy.RouteGUID] + if !exists { + // Skip policies for routes that don't match the optional filters + continue + } + + scopeType, sourceName, warnings, err := actor.resolveRoutePolicySource(policy.Source) + allWarnings = append(allWarnings, warnings...) + if err != nil { + // If we can't resolve the source, sourceName is already empty string + // scopeType is still set correctly + } + + results = append(results, RoutePolicyWithRoute{ + RoutePolicy: resources.RoutePolicy(policy), + Route: route, + DomainName: domainCache[route.DomainGUID], + ScopeType: scopeType, + SourceName: sourceName, + }) + } + + return results, allWarnings, nil +} + +// resolveRoutePolicySource resolves a source to scope type and human-readable source name +func (actor Actor) resolveRoutePolicySource(source string) (scopeType string, sourceName string, warnings Warnings, err error) { + allWarnings := Warnings{} + + // Parse source format: cf:app:, cf:space:, cf:org:, or cf:any + if source == "cf:any" { + return "any", "", nil, nil + } + + // Split source into parts + // Expected format: cf:type:guid + const prefix = "cf:" + if len(source) < len(prefix) { + return "unknown", "", nil, nil + } + + sourceBody := source[len(prefix):] + parts := splitSource(sourceBody) + if len(parts) < 2 { + return "unknown", "", nil, nil + } + + sourceType := parts[0] + guid := parts[1] + + switch sourceType { + case "app": + apps, apiWarnings, err := actor.CloudControllerClient.GetApplications( + ccv3.Query{Key: ccv3.GUIDFilter, Values: []string{guid}}, + ) + allWarnings = append(allWarnings, Warnings(apiWarnings)...) + if err != nil || len(apps) == 0 { + return "app", "", allWarnings, err + } + return "app", apps[0].Name, allWarnings, nil + + case "space": + spaces, _, apiWarnings, err := actor.CloudControllerClient.GetSpaces( + ccv3.Query{Key: ccv3.GUIDFilter, Values: []string{guid}}, + ) + allWarnings = append(allWarnings, Warnings(apiWarnings)...) + if err != nil || len(spaces) == 0 { + return "space", "", allWarnings, err + } + return "space", spaces[0].Name, allWarnings, nil + + case "org": + orgs, apiWarnings, err := actor.CloudControllerClient.GetOrganizations( + ccv3.Query{Key: ccv3.GUIDFilter, Values: []string{guid}}, + ) + allWarnings = append(allWarnings, Warnings(apiWarnings)...) + if err != nil || len(orgs) == 0 { + return "org", "", allWarnings, err + } + return "org", orgs[0].Name, allWarnings, nil + + default: + return "unknown", "", nil, nil + } +} + +// splitSource splits a source body by colon, handling the case where +// the source might be "type:guid" format +func splitSource(s string) []string { + var parts []string + current := "" + for _, char := range s { + if char == ':' && len(parts) == 0 { + // First colon - split here + parts = append(parts, current) + current = "" + } else { + current += string(char) + } + } + if current != "" { + parts = append(parts, current) + } + return parts +} diff --git a/actor/v7action/v7actionfakes/fake_cloud_controller_client.go b/actor/v7action/v7actionfakes/fake_cloud_controller_client.go index dbdca54b57b..f8e3eaa7fd0 100644 --- a/actor/v7action/v7actionfakes/fake_cloud_controller_client.go +++ b/actor/v7action/v7actionfakes/fake_cloud_controller_client.go @@ -333,6 +333,21 @@ type FakeCloudControllerClient struct { result2 ccv3.Warnings result3 error } + CreateRoutePolicyStub func(resources.RoutePolicy) (resources.RoutePolicy, ccv3.Warnings, error) + createRoutePolicyMutex sync.RWMutex + createRoutePolicyArgsForCall []struct { + arg1 resources.RoutePolicy + } + createRoutePolicyReturns struct { + result1 resources.RoutePolicy + result2 ccv3.Warnings + result3 error + } + createRoutePolicyReturnsOnCall map[int]struct { + result1 resources.RoutePolicy + result2 ccv3.Warnings + result3 error + } CreateSecurityGroupStub func(resources.SecurityGroup) (resources.SecurityGroup, ccv3.Warnings, error) createSecurityGroupMutex sync.RWMutex createSecurityGroupArgsForCall []struct { @@ -615,6 +630,21 @@ type FakeCloudControllerClient struct { result2 ccv3.Warnings result3 error } + DeleteRoutePolicyStub func(string) (ccv3.JobURL, ccv3.Warnings, error) + deleteRoutePolicyMutex sync.RWMutex + deleteRoutePolicyArgsForCall []struct { + arg1 string + } + deleteRoutePolicyReturns struct { + result1 ccv3.JobURL + result2 ccv3.Warnings + result3 error + } + deleteRoutePolicyReturnsOnCall map[int]struct { + result1 ccv3.JobURL + result2 ccv3.Warnings + result3 error + } DeleteSecurityGroupStub func(string) (ccv3.JobURL, ccv3.Warnings, error) deleteSecurityGroupMutex sync.RWMutex deleteSecurityGroupArgsForCall []struct { @@ -1495,6 +1525,23 @@ type FakeCloudControllerClient struct { result2 ccv3.Warnings result3 error } + GetRoutePoliciesStub func(...ccv3.Query) ([]resources.RoutePolicy, ccv3.IncludedResources, ccv3.Warnings, error) + getRoutePoliciesMutex sync.RWMutex + getRoutePoliciesArgsForCall []struct { + arg1 []ccv3.Query + } + getRoutePoliciesReturns struct { + result1 []resources.RoutePolicy + result2 ccv3.IncludedResources + result3 ccv3.Warnings + result4 error + } + getRoutePoliciesReturnsOnCall map[int]struct { + result1 []resources.RoutePolicy + result2 ccv3.IncludedResources + result3 ccv3.Warnings + result4 error + } GetRoutesStub func(...ccv3.Query) ([]resources.Route, ccv3.Warnings, error) getRoutesMutex sync.RWMutex getRoutesArgsForCall []struct { @@ -4254,6 +4301,73 @@ func (fake *FakeCloudControllerClient) CreateRouteBindingReturnsOnCall(i int, re }{result1, result2, result3} } +func (fake *FakeCloudControllerClient) CreateRoutePolicy(arg1 resources.RoutePolicy) (resources.RoutePolicy, ccv3.Warnings, error) { + fake.createRoutePolicyMutex.Lock() + ret, specificReturn := fake.createRoutePolicyReturnsOnCall[len(fake.createRoutePolicyArgsForCall)] + fake.createRoutePolicyArgsForCall = append(fake.createRoutePolicyArgsForCall, struct { + arg1 resources.RoutePolicy + }{arg1}) + stub := fake.CreateRoutePolicyStub + fakeReturns := fake.createRoutePolicyReturns + fake.recordInvocation("CreateRoutePolicy", []interface{}{arg1}) + fake.createRoutePolicyMutex.Unlock() + if stub != nil { + return stub(arg1) + } + if specificReturn { + return ret.result1, ret.result2, ret.result3 + } + return fakeReturns.result1, fakeReturns.result2, fakeReturns.result3 +} + +func (fake *FakeCloudControllerClient) CreateRoutePolicyCallCount() int { + fake.createRoutePolicyMutex.RLock() + defer fake.createRoutePolicyMutex.RUnlock() + return len(fake.createRoutePolicyArgsForCall) +} + +func (fake *FakeCloudControllerClient) CreateRoutePolicyCalls(stub func(resources.RoutePolicy) (resources.RoutePolicy, ccv3.Warnings, error)) { + fake.createRoutePolicyMutex.Lock() + defer fake.createRoutePolicyMutex.Unlock() + fake.CreateRoutePolicyStub = stub +} + +func (fake *FakeCloudControllerClient) CreateRoutePolicyArgsForCall(i int) resources.RoutePolicy { + fake.createRoutePolicyMutex.RLock() + defer fake.createRoutePolicyMutex.RUnlock() + argsForCall := fake.createRoutePolicyArgsForCall[i] + return argsForCall.arg1 +} + +func (fake *FakeCloudControllerClient) CreateRoutePolicyReturns(result1 resources.RoutePolicy, result2 ccv3.Warnings, result3 error) { + fake.createRoutePolicyMutex.Lock() + defer fake.createRoutePolicyMutex.Unlock() + fake.CreateRoutePolicyStub = nil + fake.createRoutePolicyReturns = struct { + result1 resources.RoutePolicy + result2 ccv3.Warnings + result3 error + }{result1, result2, result3} +} + +func (fake *FakeCloudControllerClient) CreateRoutePolicyReturnsOnCall(i int, result1 resources.RoutePolicy, result2 ccv3.Warnings, result3 error) { + fake.createRoutePolicyMutex.Lock() + defer fake.createRoutePolicyMutex.Unlock() + fake.CreateRoutePolicyStub = nil + if fake.createRoutePolicyReturnsOnCall == nil { + fake.createRoutePolicyReturnsOnCall = make(map[int]struct { + result1 resources.RoutePolicy + result2 ccv3.Warnings + result3 error + }) + } + fake.createRoutePolicyReturnsOnCall[i] = struct { + result1 resources.RoutePolicy + result2 ccv3.Warnings + result3 error + }{result1, result2, result3} +} + func (fake *FakeCloudControllerClient) CreateSecurityGroup(arg1 resources.SecurityGroup) (resources.SecurityGroup, ccv3.Warnings, error) { fake.createSecurityGroupMutex.Lock() ret, specificReturn := fake.createSecurityGroupReturnsOnCall[len(fake.createSecurityGroupArgsForCall)] @@ -5521,6 +5635,73 @@ func (fake *FakeCloudControllerClient) DeleteRouteBindingReturnsOnCall(i int, re }{result1, result2, result3} } +func (fake *FakeCloudControllerClient) DeleteRoutePolicy(arg1 string) (ccv3.JobURL, ccv3.Warnings, error) { + fake.deleteRoutePolicyMutex.Lock() + ret, specificReturn := fake.deleteRoutePolicyReturnsOnCall[len(fake.deleteRoutePolicyArgsForCall)] + fake.deleteRoutePolicyArgsForCall = append(fake.deleteRoutePolicyArgsForCall, struct { + arg1 string + }{arg1}) + stub := fake.DeleteRoutePolicyStub + fakeReturns := fake.deleteRoutePolicyReturns + fake.recordInvocation("DeleteRoutePolicy", []interface{}{arg1}) + fake.deleteRoutePolicyMutex.Unlock() + if stub != nil { + return stub(arg1) + } + if specificReturn { + return ret.result1, ret.result2, ret.result3 + } + return fakeReturns.result1, fakeReturns.result2, fakeReturns.result3 +} + +func (fake *FakeCloudControllerClient) DeleteRoutePolicyCallCount() int { + fake.deleteRoutePolicyMutex.RLock() + defer fake.deleteRoutePolicyMutex.RUnlock() + return len(fake.deleteRoutePolicyArgsForCall) +} + +func (fake *FakeCloudControllerClient) DeleteRoutePolicyCalls(stub func(string) (ccv3.JobURL, ccv3.Warnings, error)) { + fake.deleteRoutePolicyMutex.Lock() + defer fake.deleteRoutePolicyMutex.Unlock() + fake.DeleteRoutePolicyStub = stub +} + +func (fake *FakeCloudControllerClient) DeleteRoutePolicyArgsForCall(i int) string { + fake.deleteRoutePolicyMutex.RLock() + defer fake.deleteRoutePolicyMutex.RUnlock() + argsForCall := fake.deleteRoutePolicyArgsForCall[i] + return argsForCall.arg1 +} + +func (fake *FakeCloudControllerClient) DeleteRoutePolicyReturns(result1 ccv3.JobURL, result2 ccv3.Warnings, result3 error) { + fake.deleteRoutePolicyMutex.Lock() + defer fake.deleteRoutePolicyMutex.Unlock() + fake.DeleteRoutePolicyStub = nil + fake.deleteRoutePolicyReturns = struct { + result1 ccv3.JobURL + result2 ccv3.Warnings + result3 error + }{result1, result2, result3} +} + +func (fake *FakeCloudControllerClient) DeleteRoutePolicyReturnsOnCall(i int, result1 ccv3.JobURL, result2 ccv3.Warnings, result3 error) { + fake.deleteRoutePolicyMutex.Lock() + defer fake.deleteRoutePolicyMutex.Unlock() + fake.DeleteRoutePolicyStub = nil + if fake.deleteRoutePolicyReturnsOnCall == nil { + fake.deleteRoutePolicyReturnsOnCall = make(map[int]struct { + result1 ccv3.JobURL + result2 ccv3.Warnings + result3 error + }) + } + fake.deleteRoutePolicyReturnsOnCall[i] = struct { + result1 ccv3.JobURL + result2 ccv3.Warnings + result3 error + }{result1, result2, result3} +} + func (fake *FakeCloudControllerClient) DeleteSecurityGroup(arg1 string) (ccv3.JobURL, ccv3.Warnings, error) { fake.deleteSecurityGroupMutex.Lock() ret, specificReturn := fake.deleteSecurityGroupReturnsOnCall[len(fake.deleteSecurityGroupArgsForCall)] @@ -9402,6 +9583,76 @@ func (fake *FakeCloudControllerClient) GetRouteDestinationsReturnsOnCall(i int, }{result1, result2, result3} } +func (fake *FakeCloudControllerClient) GetRoutePolicies(arg1 ...ccv3.Query) ([]resources.RoutePolicy, ccv3.IncludedResources, ccv3.Warnings, error) { + fake.getRoutePoliciesMutex.Lock() + ret, specificReturn := fake.getRoutePoliciesReturnsOnCall[len(fake.getRoutePoliciesArgsForCall)] + fake.getRoutePoliciesArgsForCall = append(fake.getRoutePoliciesArgsForCall, struct { + arg1 []ccv3.Query + }{arg1}) + stub := fake.GetRoutePoliciesStub + fakeReturns := fake.getRoutePoliciesReturns + fake.recordInvocation("GetRoutePolicies", []interface{}{arg1}) + fake.getRoutePoliciesMutex.Unlock() + if stub != nil { + return stub(arg1...) + } + if specificReturn { + return ret.result1, ret.result2, ret.result3, ret.result4 + } + return fakeReturns.result1, fakeReturns.result2, fakeReturns.result3, fakeReturns.result4 +} + +func (fake *FakeCloudControllerClient) GetRoutePoliciesCallCount() int { + fake.getRoutePoliciesMutex.RLock() + defer fake.getRoutePoliciesMutex.RUnlock() + return len(fake.getRoutePoliciesArgsForCall) +} + +func (fake *FakeCloudControllerClient) GetRoutePoliciesCalls(stub func(...ccv3.Query) ([]resources.RoutePolicy, ccv3.IncludedResources, ccv3.Warnings, error)) { + fake.getRoutePoliciesMutex.Lock() + defer fake.getRoutePoliciesMutex.Unlock() + fake.GetRoutePoliciesStub = stub +} + +func (fake *FakeCloudControllerClient) GetRoutePoliciesArgsForCall(i int) []ccv3.Query { + fake.getRoutePoliciesMutex.RLock() + defer fake.getRoutePoliciesMutex.RUnlock() + argsForCall := fake.getRoutePoliciesArgsForCall[i] + return argsForCall.arg1 +} + +func (fake *FakeCloudControllerClient) GetRoutePoliciesReturns(result1 []resources.RoutePolicy, result2 ccv3.IncludedResources, result3 ccv3.Warnings, result4 error) { + fake.getRoutePoliciesMutex.Lock() + defer fake.getRoutePoliciesMutex.Unlock() + fake.GetRoutePoliciesStub = nil + fake.getRoutePoliciesReturns = struct { + result1 []resources.RoutePolicy + result2 ccv3.IncludedResources + result3 ccv3.Warnings + result4 error + }{result1, result2, result3, result4} +} + +func (fake *FakeCloudControllerClient) GetRoutePoliciesReturnsOnCall(i int, result1 []resources.RoutePolicy, result2 ccv3.IncludedResources, result3 ccv3.Warnings, result4 error) { + fake.getRoutePoliciesMutex.Lock() + defer fake.getRoutePoliciesMutex.Unlock() + fake.GetRoutePoliciesStub = nil + if fake.getRoutePoliciesReturnsOnCall == nil { + fake.getRoutePoliciesReturnsOnCall = make(map[int]struct { + result1 []resources.RoutePolicy + result2 ccv3.IncludedResources + result3 ccv3.Warnings + result4 error + }) + } + fake.getRoutePoliciesReturnsOnCall[i] = struct { + result1 []resources.RoutePolicy + result2 ccv3.IncludedResources + result3 ccv3.Warnings + result4 error + }{result1, result2, result3, result4} +} + func (fake *FakeCloudControllerClient) GetRoutes(arg1 ...ccv3.Query) ([]resources.Route, ccv3.Warnings, error) { fake.getRoutesMutex.Lock() ret, specificReturn := fake.getRoutesReturnsOnCall[len(fake.getRoutesArgsForCall)] diff --git a/actor/v7action/v7actionfakes/fake_config.go b/actor/v7action/v7actionfakes/fake_config.go index cd46ebbbfc5..73a32a8baeb 100644 --- a/actor/v7action/v7actionfakes/fake_config.go +++ b/actor/v7action/v7actionfakes/fake_config.go @@ -1134,48 +1134,6 @@ func (fake *FakeConfig) UnsetOrganizationAndSpaceInformationCalls(stub func()) { func (fake *FakeConfig) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.aPIVersionMutex.RLock() - defer fake.aPIVersionMutex.RUnlock() - fake.accessTokenMutex.RLock() - defer fake.accessTokenMutex.RUnlock() - fake.currentUserMutex.RLock() - defer fake.currentUserMutex.RUnlock() - fake.dialTimeoutMutex.RLock() - defer fake.dialTimeoutMutex.RUnlock() - fake.isCFOnK8sMutex.RLock() - defer fake.isCFOnK8sMutex.RUnlock() - fake.pollingIntervalMutex.RLock() - defer fake.pollingIntervalMutex.RUnlock() - fake.refreshTokenMutex.RLock() - defer fake.refreshTokenMutex.RUnlock() - fake.sSHOAuthClientMutex.RLock() - defer fake.sSHOAuthClientMutex.RUnlock() - fake.setAccessTokenMutex.RLock() - defer fake.setAccessTokenMutex.RUnlock() - fake.setKubernetesAuthInfoMutex.RLock() - defer fake.setKubernetesAuthInfoMutex.RUnlock() - fake.setRefreshTokenMutex.RLock() - defer fake.setRefreshTokenMutex.RUnlock() - fake.setTargetInformationMutex.RLock() - defer fake.setTargetInformationMutex.RUnlock() - fake.setTokenInformationMutex.RLock() - defer fake.setTokenInformationMutex.RUnlock() - fake.setUAAClientCredentialsMutex.RLock() - defer fake.setUAAClientCredentialsMutex.RUnlock() - fake.setUAAGrantTypeMutex.RLock() - defer fake.setUAAGrantTypeMutex.RUnlock() - fake.skipSSLValidationMutex.RLock() - defer fake.skipSSLValidationMutex.RUnlock() - fake.stagingTimeoutMutex.RLock() - defer fake.stagingTimeoutMutex.RUnlock() - fake.startupTimeoutMutex.RLock() - defer fake.startupTimeoutMutex.RUnlock() - fake.targetMutex.RLock() - defer fake.targetMutex.RUnlock() - fake.uAAGrantTypeMutex.RLock() - defer fake.uAAGrantTypeMutex.RUnlock() - fake.unsetOrganizationAndSpaceInformationMutex.RLock() - defer fake.unsetOrganizationAndSpaceInformationMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/actor/v7action/v7actionfakes/fake_downloader.go b/actor/v7action/v7actionfakes/fake_downloader.go index 4545618272a..d77a875d875 100644 --- a/actor/v7action/v7actionfakes/fake_downloader.go +++ b/actor/v7action/v7actionfakes/fake_downloader.go @@ -94,8 +94,6 @@ func (fake *FakeDownloader) DownloadReturnsOnCall(i int, result1 string, result2 func (fake *FakeDownloader) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.downloadMutex.RLock() - defer fake.downloadMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/actor/v7action/v7actionfakes/fake_kubernetes_config_getter.go b/actor/v7action/v7actionfakes/fake_kubernetes_config_getter.go index 7102e140b63..4336bf2e2e8 100644 --- a/actor/v7action/v7actionfakes/fake_kubernetes_config_getter.go +++ b/actor/v7action/v7actionfakes/fake_kubernetes_config_getter.go @@ -84,8 +84,6 @@ func (fake *FakeKubernetesConfigGetter) GetReturnsOnCall(i int, result1 *api.Con func (fake *FakeKubernetesConfigGetter) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.getMutex.RLock() - defer fake.getMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/actor/v7action/v7actionfakes/fake_manifest_parser.go b/actor/v7action/v7actionfakes/fake_manifest_parser.go index 6d93fd4df35..73bf7ac4f52 100644 --- a/actor/v7action/v7actionfakes/fake_manifest_parser.go +++ b/actor/v7action/v7actionfakes/fake_manifest_parser.go @@ -155,10 +155,6 @@ func (fake *FakeManifestParser) RawAppManifestReturnsOnCall(i int, result1 []byt func (fake *FakeManifestParser) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.appNamesMutex.RLock() - defer fake.appNamesMutex.RUnlock() - fake.rawAppManifestMutex.RLock() - defer fake.rawAppManifestMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/actor/v7action/v7actionfakes/fake_routing_client.go b/actor/v7action/v7actionfakes/fake_routing_client.go index d7be3997593..73b5f6fafb3 100644 --- a/actor/v7action/v7actionfakes/fake_routing_client.go +++ b/actor/v7action/v7actionfakes/fake_routing_client.go @@ -161,10 +161,6 @@ func (fake *FakeRoutingClient) GetRouterGroupsReturnsOnCall(i int, result1 []rou func (fake *FakeRoutingClient) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.getRouterGroupByNameMutex.RLock() - defer fake.getRouterGroupByNameMutex.RUnlock() - fake.getRouterGroupsMutex.RLock() - defer fake.getRouterGroupsMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/actor/v7action/v7actionfakes/fake_shared_actor.go b/actor/v7action/v7actionfakes/fake_shared_actor.go index 1601a0e3e99..1c60d5b4bec 100644 --- a/actor/v7action/v7actionfakes/fake_shared_actor.go +++ b/actor/v7action/v7actionfakes/fake_shared_actor.go @@ -338,14 +338,6 @@ func (fake *FakeSharedActor) ZipDirectoryResourcesReturnsOnCall(i int, result1 s func (fake *FakeSharedActor) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.gatherArchiveResourcesMutex.RLock() - defer fake.gatherArchiveResourcesMutex.RUnlock() - fake.gatherDirectoryResourcesMutex.RLock() - defer fake.gatherDirectoryResourcesMutex.RUnlock() - fake.zipArchiveResourcesMutex.RLock() - defer fake.zipArchiveResourcesMutex.RUnlock() - fake.zipDirectoryResourcesMutex.RLock() - defer fake.zipDirectoryResourcesMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/actor/v7action/v7actionfakes/fake_simple_progress_bar.go b/actor/v7action/v7actionfakes/fake_simple_progress_bar.go index 0e2b05b6486..19d9442f101 100644 --- a/actor/v7action/v7actionfakes/fake_simple_progress_bar.go +++ b/actor/v7action/v7actionfakes/fake_simple_progress_bar.go @@ -126,10 +126,6 @@ func (fake *FakeSimpleProgressBar) TerminateCalls(stub func()) { func (fake *FakeSimpleProgressBar) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.initializeMutex.RLock() - defer fake.initializeMutex.RUnlock() - fake.terminateMutex.RLock() - defer fake.terminateMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/actor/v7action/v7actionfakes/fake_sshactor.go b/actor/v7action/v7actionfakes/fake_sshactor.go index f849722dd78..24cf1c167be 100644 --- a/actor/v7action/v7actionfakes/fake_sshactor.go +++ b/actor/v7action/v7actionfakes/fake_sshactor.go @@ -88,8 +88,6 @@ func (fake *FakeSSHActor) ExecuteSecureShellReturnsOnCall(i int, result1 error) func (fake *FakeSSHActor) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.executeSecureShellMutex.RLock() - defer fake.executeSecureShellMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/actor/v7action/v7actionfakes/fake_uaaclient.go b/actor/v7action/v7actionfakes/fake_uaaclient.go index 517b7ec9afa..ae1e07303ac 100644 --- a/actor/v7action/v7actionfakes/fake_uaaclient.go +++ b/actor/v7action/v7actionfakes/fake_uaaclient.go @@ -852,28 +852,6 @@ func (fake *FakeUAAClient) ValidateClientUserReturnsOnCall(i int, result1 error) func (fake *FakeUAAClient) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.authenticateMutex.RLock() - defer fake.authenticateMutex.RUnlock() - fake.createUserMutex.RLock() - defer fake.createUserMutex.RUnlock() - fake.deleteUserMutex.RLock() - defer fake.deleteUserMutex.RUnlock() - fake.getAPIVersionMutex.RLock() - defer fake.getAPIVersionMutex.RUnlock() - fake.getLoginPromptsMutex.RLock() - defer fake.getLoginPromptsMutex.RUnlock() - fake.getSSHPasscodeMutex.RLock() - defer fake.getSSHPasscodeMutex.RUnlock() - fake.listUsersMutex.RLock() - defer fake.listUsersMutex.RUnlock() - fake.refreshAccessTokenMutex.RLock() - defer fake.refreshAccessTokenMutex.RUnlock() - fake.revokeMutex.RLock() - defer fake.revokeMutex.RUnlock() - fake.updatePasswordMutex.RLock() - defer fake.updatePasswordMutex.RUnlock() - fake.validateClientUserMutex.RLock() - defer fake.validateClientUserMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/actor/v7action/v7actionfakes/fake_who_am_ier.go b/actor/v7action/v7actionfakes/fake_who_am_ier.go index 78dfee83e99..46640859a22 100644 --- a/actor/v7action/v7actionfakes/fake_who_am_ier.go +++ b/actor/v7action/v7actionfakes/fake_who_am_ier.go @@ -90,8 +90,6 @@ func (fake *FakeWhoAmIer) WhoAmIReturnsOnCall(i int, result1 resources.K8sUser, func (fake *FakeWhoAmIer) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.whoAmIMutex.RLock() - defer fake.whoAmIMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/actor/v7pushaction/create_deployment_for_push_plan_test.go b/actor/v7pushaction/create_deployment_for_push_plan_test.go index beded0358b5..04bdbd5ddb6 100644 --- a/actor/v7pushaction/create_deployment_for_push_plan_test.go +++ b/actor/v7pushaction/create_deployment_for_push_plan_test.go @@ -8,7 +8,7 @@ import ( "code.cloudfoundry.org/cli/v9/actor/v7pushaction/v7pushactionfakes" "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" "code.cloudfoundry.org/cli/v9/resources" - "code.cloudfoundry.org/cli/v9/types" + "code.cloudfoundry.org/cli/v9/types" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) diff --git a/actor/v7pushaction/handle_disk_override.go b/actor/v7pushaction/handle_disk_override.go index 33b46727511..e4dd2088450 100644 --- a/actor/v7pushaction/handle_disk_override.go +++ b/actor/v7pushaction/handle_disk_override.go @@ -1,7 +1,7 @@ package v7pushaction import ( - "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" "code.cloudfoundry.org/cli/v9/command/translatableerror" "code.cloudfoundry.org/cli/v9/util/manifestparser" ) diff --git a/actor/v7pushaction/handle_disk_override_test.go b/actor/v7pushaction/handle_disk_override_test.go index 3781e44e0e4..ab552bcae8e 100644 --- a/actor/v7pushaction/handle_disk_override_test.go +++ b/actor/v7pushaction/handle_disk_override_test.go @@ -1,7 +1,7 @@ package v7pushaction_test import ( - "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" "code.cloudfoundry.org/cli/v9/command/translatableerror" "code.cloudfoundry.org/cli/v9/util/manifestparser" diff --git a/actor/v7pushaction/handle_instances_override.go b/actor/v7pushaction/handle_instances_override.go index a6322a9882a..60cc4f104fe 100644 --- a/actor/v7pushaction/handle_instances_override.go +++ b/actor/v7pushaction/handle_instances_override.go @@ -1,7 +1,7 @@ package v7pushaction import ( - "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" "code.cloudfoundry.org/cli/v9/command/translatableerror" "code.cloudfoundry.org/cli/v9/util/manifestparser" ) diff --git a/actor/v7pushaction/handle_instances_override_test.go b/actor/v7pushaction/handle_instances_override_test.go index 4808558af41..40b7f3c5d56 100644 --- a/actor/v7pushaction/handle_instances_override_test.go +++ b/actor/v7pushaction/handle_instances_override_test.go @@ -1,7 +1,7 @@ package v7pushaction_test import ( - "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" "code.cloudfoundry.org/cli/v9/command/translatableerror" "code.cloudfoundry.org/cli/v9/types" "code.cloudfoundry.org/cli/v9/util/manifestparser" diff --git a/actor/v7pushaction/handle_log_rate_limit_override.go b/actor/v7pushaction/handle_log_rate_limit_override.go index 13b1e9dbf8e..218db034cc2 100644 --- a/actor/v7pushaction/handle_log_rate_limit_override.go +++ b/actor/v7pushaction/handle_log_rate_limit_override.go @@ -1,7 +1,7 @@ package v7pushaction import ( - "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" "code.cloudfoundry.org/cli/v9/command/translatableerror" "code.cloudfoundry.org/cli/v9/util/manifestparser" ) diff --git a/actor/v7pushaction/handle_log_rate_limit_override_test.go b/actor/v7pushaction/handle_log_rate_limit_override_test.go index 679d740a90e..0281b7648bc 100644 --- a/actor/v7pushaction/handle_log_rate_limit_override_test.go +++ b/actor/v7pushaction/handle_log_rate_limit_override_test.go @@ -1,7 +1,7 @@ package v7pushaction_test import ( - "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" "code.cloudfoundry.org/cli/v9/command/translatableerror" "code.cloudfoundry.org/cli/v9/util/manifestparser" diff --git a/actor/v7pushaction/handle_memory_override.go b/actor/v7pushaction/handle_memory_override.go index e5ab16ca549..4460687c66c 100644 --- a/actor/v7pushaction/handle_memory_override.go +++ b/actor/v7pushaction/handle_memory_override.go @@ -1,7 +1,7 @@ package v7pushaction import ( - "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" "code.cloudfoundry.org/cli/v9/command/translatableerror" "code.cloudfoundry.org/cli/v9/util/manifestparser" ) diff --git a/actor/v7pushaction/handle_memory_override_test.go b/actor/v7pushaction/handle_memory_override_test.go index 1ef70722757..602396fbae9 100644 --- a/actor/v7pushaction/handle_memory_override_test.go +++ b/actor/v7pushaction/handle_memory_override_test.go @@ -1,7 +1,7 @@ package v7pushaction_test import ( - "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" "code.cloudfoundry.org/cli/v9/command/translatableerror" "code.cloudfoundry.org/cli/v9/util/manifestparser" diff --git a/actor/v7pushaction/setup_deployment_information_for_push_plan.go b/actor/v7pushaction/setup_deployment_information_for_push_plan.go index 82900aa99a1..328b0dd28c0 100644 --- a/actor/v7pushaction/setup_deployment_information_for_push_plan.go +++ b/actor/v7pushaction/setup_deployment_information_for_push_plan.go @@ -1,7 +1,7 @@ package v7pushaction import ( - "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" + "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" "code.cloudfoundry.org/cli/v9/cf/errors" "code.cloudfoundry.org/cli/v9/command/flag" "code.cloudfoundry.org/cli/v9/types" diff --git a/actor/v7pushaction/setup_deployment_information_for_push_plan_test.go b/actor/v7pushaction/setup_deployment_information_for_push_plan_test.go index b07bdade816..c170366535c 100644 --- a/actor/v7pushaction/setup_deployment_information_for_push_plan_test.go +++ b/actor/v7pushaction/setup_deployment_information_for_push_plan_test.go @@ -2,8 +2,8 @@ package v7pushaction_test import ( "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" - "code.cloudfoundry.org/cli/v9/cf/errors" - "code.cloudfoundry.org/cli/v9/types" + "code.cloudfoundry.org/cli/v9/cf/errors" + "code.cloudfoundry.org/cli/v9/types" . "code.cloudfoundry.org/cli/v9/actor/v7pushaction" diff --git a/api/cfnetworking/cfnetv1/client.go b/api/cfnetworking/cfnetv1/client.go index 1c301716184..5068b41e75d 100644 --- a/api/cfnetworking/cfnetv1/client.go +++ b/api/cfnetworking/cfnetv1/client.go @@ -6,7 +6,7 @@ // For more information on the CF Networking API see // https://github.com/cloudfoundry-incubator/cf-networking-release/blob/develop/docs/API.md // -// Method Naming Conventions +// # Method Naming Conventions // // The client takes a '' // approach to method names. If the and @@ -15,38 +15,40 @@ // method name. // // For Example: -// Method Name: GetApplication -// Endpoint: /v2/applications/:guid -// Action Name: Get -// Top Level Endpoint: applications -// Return Value: Application -// -// Method Name: GetServiceInstances -// Endpoint: /v2/service_instances -// Action Name: Get -// Top Level Endpoint: service_instances -// Return Value: []ServiceInstance -// -// Method Name: GetSpaceServiceInstances -// Endpoint: /v2/spaces/:guid/service_instances -// Action Name: Get -// Top Level Endpoint: spaces -// Return Value: []ServiceInstance +// +// Method Name: GetApplication +// Endpoint: /v2/applications/:guid +// Action Name: Get +// Top Level Endpoint: applications +// Return Value: Application +// +// Method Name: GetServiceInstances +// Endpoint: /v2/service_instances +// Action Name: Get +// Top Level Endpoint: service_instances +// Return Value: []ServiceInstance +// +// Method Name: GetSpaceServiceInstances +// Endpoint: /v2/spaces/:guid/service_instances +// Action Name: Get +// Top Level Endpoint: spaces +// Return Value: []ServiceInstance // // Use the following table to determine which HTTP Command equates to which // Action Name: -// HTTP Command -> Action Name -// POST -> Create -// GET -> Get -// PUT -> Update -// DELETE -> Delete // -// Method Locations +// HTTP Command -> Action Name +// POST -> Create +// GET -> Get +// PUT -> Update +// DELETE -> Delete +// +// # Method Locations // // Methods exist in the same file as their return type, regardless of which // endpoint they use. // -// Error Handling +// # Error Handling // // All error handling that requires parsing the error_code/code returned back // from the Cloud Controller should be placed in the errorWrapper. Everything @@ -55,7 +57,7 @@ // exist in the cloudcontroller's errors.go. Errors related to the individaul // operation should exist at the top of that operation's file. // -// No inline-relations-depth And summary Endpoints +// # No inline-relations-depth And summary Endpoints // // This package will not use ever use 'inline-relations-depth' or the // '/summary' endpoints for any operations. These requests can be extremely @@ -65,72 +67,72 @@ package cfnetv1 import ( - "fmt" - "runtime" - "time" + "fmt" + "runtime" + "time" - "code.cloudfoundry.org/cli/v9/api/cfnetworking" - "code.cloudfoundry.org/cli/v9/api/cfnetworking/cfnetv1/internal" + "code.cloudfoundry.org/cli/v9/api/cfnetworking" + "code.cloudfoundry.org/cli/v9/api/cfnetworking/cfnetv1/internal" - "github.com/tedsuo/rata" + "github.com/tedsuo/rata" ) // Client is a client that can be used to talk to a CF Networking API. type Client struct { - connection cfnetworking.Connection - router *rata.RequestGenerator - url string - userAgent string + connection cfnetworking.Connection + router *rata.RequestGenerator + url string + userAgent string } // Config allows the Client to be configured type Config struct { - // AppName is the name of the application/process using the client. - AppName string + // AppName is the name of the application/process using the client. + AppName string - // AppVersion is the version of the application/process using the client. - AppVersion string + // AppVersion is the version of the application/process using the client. + AppVersion string - // DialTimeout is the DNS timeout used to make all requests to the Cloud - // Controller. - DialTimeout time.Duration + // DialTimeout is the DNS timeout used to make all requests to the Cloud + // Controller. + DialTimeout time.Duration - // SkipSSLValidation controls whether a client verifies the server's - // certificate chain and host name. If SkipSSLValidation is true, TLS accepts - // any certificate presented by the server and any host name in that - // certificate for *all* client requests going forward. - // - // In this mode, TLS is susceptible to man-in-the-middle attacks. This should - // be used only for testing. - SkipSSLValidation bool + // SkipSSLValidation controls whether a client verifies the server's + // certificate chain and host name. If SkipSSLValidation is true, TLS accepts + // any certificate presented by the server and any host name in that + // certificate for *all* client requests going forward. + // + // In this mode, TLS is susceptible to man-in-the-middle attacks. This should + // be used only for testing. + SkipSSLValidation bool - // URL is a fully qualified URL to the CF Networking API. - URL string + // URL is a fully qualified URL to the CF Networking API. + URL string - // Wrappers that apply to the client connection. - Wrappers []ConnectionWrapper + // Wrappers that apply to the client connection. + Wrappers []ConnectionWrapper } // NewClient returns a new CF Networking client. func NewClient(config Config) *Client { - userAgent := fmt.Sprintf("%s/%s (%s; %s %s)", config.AppName, config.AppVersion, runtime.Version(), runtime.GOARCH, runtime.GOOS) + userAgent := fmt.Sprintf("%s/%s (%s; %s %s)", config.AppName, config.AppVersion, runtime.Version(), runtime.GOARCH, runtime.GOOS) - connection := cfnetworking.NewConnection(cfnetworking.Config{ - DialTimeout: config.DialTimeout, - SkipSSLValidation: config.SkipSSLValidation, - }) + connection := cfnetworking.NewConnection(cfnetworking.Config{ + DialTimeout: config.DialTimeout, + SkipSSLValidation: config.SkipSSLValidation, + }) - wrappedConnection := cfnetworking.NewErrorWrapper().Wrap(connection) - for _, wrapper := range config.Wrappers { - wrappedConnection = wrapper.Wrap(wrappedConnection) - } + wrappedConnection := cfnetworking.NewErrorWrapper().Wrap(connection) + for _, wrapper := range config.Wrappers { + wrappedConnection = wrapper.Wrap(wrappedConnection) + } - client := &Client{ - connection: wrappedConnection, - router: rata.NewRequestGenerator(config.URL, internal.Routes), - url: config.URL, - userAgent: userAgent, - } + client := &Client{ + connection: wrappedConnection, + router: rata.NewRequestGenerator(config.URL, internal.Routes), + url: config.URL, + userAgent: userAgent, + } - return client + return client } diff --git a/api/cfnetworking/errors.go b/api/cfnetworking/errors.go index 7abd7877c64..fd5fcaacc56 100644 --- a/api/cfnetworking/errors.go +++ b/api/cfnetworking/errors.go @@ -1,64 +1,64 @@ package cfnetworking import ( - "encoding/json" - "net/http" + "encoding/json" + "net/http" - "code.cloudfoundry.org/cli/v9/api/cfnetworking/networkerror" + "code.cloudfoundry.org/cli/v9/api/cfnetworking/networkerror" ) // errorWrapper is the wrapper that converts responses with 4xx and 5xx status // codes to an error. type errorWrapper struct { - connection Connection + connection Connection } func NewErrorWrapper() *errorWrapper { - return new(errorWrapper) + return new(errorWrapper) } // Wrap wraps a Cloud Controller connection in this error handling wrapper. func (e *errorWrapper) Wrap(innerconnection Connection) Connection { - e.connection = innerconnection - return e + e.connection = innerconnection + return e } // Make converts RawHTTPStatusError, which represents responses with 4xx and // 5xx status codes, to specific errors. func (e *errorWrapper) Make(request *Request, passedResponse *Response) error { - err := e.connection.Make(request, passedResponse) + err := e.connection.Make(request, passedResponse) - if rawHTTPStatusErr, ok := err.(networkerror.RawHTTPStatusError); ok { - return convert(rawHTTPStatusErr) - } - return err + if rawHTTPStatusErr, ok := err.(networkerror.RawHTTPStatusError); ok { + return convert(rawHTTPStatusErr) + } + return err } func convert(rawHTTPStatusErr networkerror.RawHTTPStatusError) error { - // Try to unmarshal the raw error into a CC error. If unmarshaling fails, - // return the raw error. - var errorResponse networkerror.ErrorResponse - err := json.Unmarshal(rawHTTPStatusErr.RawResponse, &errorResponse) - if err != nil { - return rawHTTPStatusErr - } + // Try to unmarshal the raw error into a CC error. If unmarshaling fails, + // return the raw error. + var errorResponse networkerror.ErrorResponse + err := json.Unmarshal(rawHTTPStatusErr.RawResponse, &errorResponse) + if err != nil { + return rawHTTPStatusErr + } - switch rawHTTPStatusErr.StatusCode { - case http.StatusBadRequest: // 400 - return networkerror.BadRequestError(errorResponse) - case http.StatusUnauthorized: // 401 - return networkerror.UnauthorizedError(errorResponse) - case http.StatusForbidden: // 403 - return networkerror.ForbiddenError(errorResponse) - case http.StatusNotAcceptable: // 406 - return networkerror.NotAcceptableError(errorResponse) - case http.StatusConflict: // 409 - return networkerror.ConflictError(errorResponse) - default: - return networkerror.UnexpectedResponseError{ - ErrorResponse: errorResponse, - RequestIDs: rawHTTPStatusErr.RequestIDs, - ResponseCode: rawHTTPStatusErr.StatusCode, - } - } + switch rawHTTPStatusErr.StatusCode { + case http.StatusBadRequest: // 400 + return networkerror.BadRequestError(errorResponse) + case http.StatusUnauthorized: // 401 + return networkerror.UnauthorizedError(errorResponse) + case http.StatusForbidden: // 403 + return networkerror.ForbiddenError(errorResponse) + case http.StatusNotAcceptable: // 406 + return networkerror.NotAcceptableError(errorResponse) + case http.StatusConflict: // 409 + return networkerror.ConflictError(errorResponse) + default: + return networkerror.UnexpectedResponseError{ + ErrorResponse: errorResponse, + RequestIDs: rawHTTPStatusErr.RequestIDs, + ResponseCode: rawHTTPStatusErr.StatusCode, + } + } } diff --git a/api/cfnetworking/wrapper/retry_request.go b/api/cfnetworking/wrapper/retry_request.go index 600a79825d5..eb4300ecf09 100644 --- a/api/cfnetworking/wrapper/retry_request.go +++ b/api/cfnetworking/wrapper/retry_request.go @@ -1,54 +1,54 @@ package wrapper import ( - "net/http" + "net/http" - "code.cloudfoundry.org/cli/v9/api/cfnetworking" + "code.cloudfoundry.org/cli/v9/api/cfnetworking" ) // RetryRequest is a wrapper that retries failed requests if they contain a 5XX // status code. type RetryRequest struct { - maxRetries int - connection cfnetworking.Connection + maxRetries int + connection cfnetworking.Connection } // NewRetryRequest returns a pointer to a RetryRequest wrapper. func NewRetryRequest(maxRetries int) *RetryRequest { - return &RetryRequest{ - maxRetries: maxRetries, - } + return &RetryRequest{ + maxRetries: maxRetries, + } } // Wrap sets the connection in the RetryRequest and returns itself. func (retry *RetryRequest) Wrap(innerconnection cfnetworking.Connection) cfnetworking.Connection { - retry.connection = innerconnection - return retry + retry.connection = innerconnection + return retry } // Make retries the request if it comes back with certain status codes. func (retry *RetryRequest) Make(request *cfnetworking.Request, passedResponse *cfnetworking.Response) error { - var err error - - for i := 0; i < retry.maxRetries+1; i += 1 { - err = retry.connection.Make(request, passedResponse) - if err == nil { - return nil - } - - if passedResponse.HTTPResponse != nil && - (passedResponse.HTTPResponse.StatusCode == http.StatusBadGateway || - passedResponse.HTTPResponse.StatusCode == http.StatusServiceUnavailable || - passedResponse.HTTPResponse.StatusCode == http.StatusGatewayTimeout || - (passedResponse.HTTPResponse.StatusCode >= 400 && passedResponse.HTTPResponse.StatusCode < 500)) { - break - } - - // Reset the request body prior to the next retry - resetErr := request.ResetBody() - if resetErr != nil { - return resetErr - } - } - return err + var err error + + for i := 0; i < retry.maxRetries+1; i += 1 { + err = retry.connection.Make(request, passedResponse) + if err == nil { + return nil + } + + if passedResponse.HTTPResponse != nil && + (passedResponse.HTTPResponse.StatusCode == http.StatusBadGateway || + passedResponse.HTTPResponse.StatusCode == http.StatusServiceUnavailable || + passedResponse.HTTPResponse.StatusCode == http.StatusGatewayTimeout || + (passedResponse.HTTPResponse.StatusCode >= 400 && passedResponse.HTTPResponse.StatusCode < 500)) { + break + } + + // Reset the request body prior to the next retry + resetErr := request.ResetBody() + if resetErr != nil { + return resetErr + } + } + return err } diff --git a/api/cloudcontroller/ccv3/deployment_test.go b/api/cloudcontroller/ccv3/deployment_test.go index 3dea39c59a3..f725d62763f 100644 --- a/api/cloudcontroller/ccv3/deployment_test.go +++ b/api/cloudcontroller/ccv3/deployment_test.go @@ -7,7 +7,7 @@ import ( "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccerror" "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" "code.cloudfoundry.org/cli/v9/resources" - "code.cloudfoundry.org/cli/v9/types" + "code.cloudfoundry.org/cli/v9/types" . "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3" . "github.com/onsi/ginkgo/v2" diff --git a/api/cloudcontroller/ccv3/included_resources.go b/api/cloudcontroller/ccv3/included_resources.go index 6827248eae1..89af94c2540 100644 --- a/api/cloudcontroller/ccv3/included_resources.go +++ b/api/cloudcontroller/ccv3/included_resources.go @@ -11,6 +11,7 @@ type IncludedResources struct { ServiceBrokers []resources.ServiceBroker `json:"service_brokers,omitempty"` ServicePlans []resources.ServicePlan `json:"service_plans,omitempty"` Apps []resources.Application `json:"apps,omitempty"` + Routes []resources.Route `json:"routes,omitempty"` } func (i *IncludedResources) Merge(resources IncludedResources) { @@ -22,4 +23,5 @@ func (i *IncludedResources) Merge(resources IncludedResources) { i.ServiceInstances = append(i.ServiceInstances, resources.ServiceInstances...) i.ServiceOfferings = append(i.ServiceOfferings, resources.ServiceOfferings...) i.ServicePlans = append(i.ServicePlans, resources.ServicePlans...) + i.Routes = append(i.Routes, resources.Routes...) } diff --git a/api/cloudcontroller/ccv3/info.go b/api/cloudcontroller/ccv3/info.go index d1db6b3eafa..380acc1817d 100644 --- a/api/cloudcontroller/ccv3/info.go +++ b/api/cloudcontroller/ccv3/info.go @@ -4,7 +4,7 @@ import ( "net/http" "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccerror" - "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/internal" ) type Info struct { diff --git a/api/cloudcontroller/ccv3/internal/api_routes.go b/api/cloudcontroller/ccv3/internal/api_routes.go index d1f7ffd9fe6..8700d9e6088 100644 --- a/api/cloudcontroller/ccv3/internal/api_routes.go +++ b/api/cloudcontroller/ccv3/internal/api_routes.go @@ -9,6 +9,7 @@ import "net/http" // If the request returns a single entity by GUID, use the singular (for example // /v3/organizations/:organization_guid is GetOrganization). const ( + DeleteRoutePolicyRequest = "DeleteRoutePolicyRequest" DeleteApplicationProcessInstanceRequest = "DeleteApplicationProcessInstance" DeleteApplicationRequest = "DeleteApplication" DeleteBuildpackRequest = "DeleteBuildpack" @@ -35,6 +36,8 @@ const ( DeleteSpaceRequest = "DeleteSpace" DeleteSpaceQuotaFromSpaceRequest = "DeleteSpaceQuotaFromSpace" DeleteUserRequest = "DeleteUser" + GetRoutePolicyRequest = "GetRoutePolicyRequest" + GetRoutePoliciesRequest = "GetRoutePoliciesRequest" GetApplicationDropletCurrentRequest = "GetApplicationDropletCurrent" GetApplicationEnvRequest = "GetApplicationEnv" GetApplicationFeaturesRequest = "GetApplicationFeatures" @@ -134,6 +137,7 @@ const ( PatchSpaceQuotaRequest = "PatchSpaceQuota" PatchStackRequest = "PatchStack" PatchMoveRouteRequest = "PatchMoveRouteRequest" + PostRoutePolicyRequest = "PostRoutePolicyRequest" PostApplicationActionApplyManifest = "PostApplicationActionApplyM" PostApplicationActionRestartRequest = "PostApplicationActionRestart" PostApplicationActionStartRequest = "PostApplicationActionStart" @@ -186,6 +190,10 @@ const ( // APIRoutes is a list of routes used by the router to construct request URLs. var APIRoutes = map[string]Route{ + GetRoutePoliciesRequest: {Path: "/v3/route_policies", Method: http.MethodGet}, + PostRoutePolicyRequest: {Path: "/v3/route_policies", Method: http.MethodPost}, + GetRoutePolicyRequest: {Path: "/v3/route_policies/:route_policy_guid", Method: http.MethodGet}, + DeleteRoutePolicyRequest: {Path: "/v3/route_policies/:route_policy_guid", Method: http.MethodDelete}, GetApplicationsRequest: {Path: "/v3/apps", Method: http.MethodGet}, PostApplicationRequest: {Path: "/v3/apps", Method: http.MethodPost}, DeleteApplicationRequest: {Path: "/v3/apps/:app_guid", Method: http.MethodDelete}, diff --git a/api/cloudcontroller/ccv3/query.go b/api/cloudcontroller/ccv3/query.go index 99b04abad9b..fdc7a43f1ff 100644 --- a/api/cloudcontroller/ccv3/query.go +++ b/api/cloudcontroller/ccv3/query.go @@ -29,6 +29,10 @@ const ( SequenceIDFilter QueryKey = "sequence_ids" // RouteGUIDFilter is a query parameter for listing objects by Route GUID. RouteGUIDFilter QueryKey = "route_guids" + // SourcesFilter is a query parameter for listing route policies by source. + SourcesFilter QueryKey = "sources" + // SourceGuidsFilter is a query parameter for listing route policies by source GUID. + SourceGuidsFilter QueryKey = "source_guids" // ServiceInstanceGUIDFilter is a query parameter for listing objects by Service Instance GUID. ServiceInstanceGUIDFilter QueryKey = "service_instance_guids" // SpaceGUIDFilter is a query parameter for listing objects by Space GUID. diff --git a/api/cloudcontroller/ccv3/route_policy.go b/api/cloudcontroller/ccv3/route_policy.go new file mode 100644 index 00000000000..1b0b555a0ab --- /dev/null +++ b/api/cloudcontroller/ccv3/route_policy.go @@ -0,0 +1,59 @@ +package ccv3 + +import ( + "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/internal" + "code.cloudfoundry.org/cli/v9/resources" +) + +// CreateRoutePolicy creates a route policy for a route +func (client *Client) CreateRoutePolicy(routePolicy resources.RoutePolicy) (resources.RoutePolicy, Warnings, error) { + var responseBody resources.RoutePolicy + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.PostRoutePolicyRequest, + RequestBody: routePolicy, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// GetRoutePolicies lists route policies +func (client *Client) GetRoutePolicies(query ...Query) ([]resources.RoutePolicy, IncludedResources, Warnings, error) { + var routePolicies []resources.RoutePolicy + + includedResources, warnings, err := client.MakeListRequest(RequestParams{ + RequestName: internal.GetRoutePoliciesRequest, + Query: query, + ResponseBody: resources.RoutePolicy{}, + AppendToList: func(item interface{}) error { + routePolicies = append(routePolicies, item.(resources.RoutePolicy)) + return nil + }, + }) + + return routePolicies, includedResources, warnings, err +} + +// GetRoutePolicy gets a single route policy by GUID +func (client *Client) GetRoutePolicy(guid string) (resources.RoutePolicy, Warnings, error) { + var responseBody resources.RoutePolicy + + _, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.GetRoutePolicyRequest, + URIParams: internal.Params{"route_policy_guid": guid}, + ResponseBody: &responseBody, + }) + + return responseBody, warnings, err +} + +// DeleteRoutePolicy deletes a route policy +func (client *Client) DeleteRoutePolicy(guid string) (JobURL, Warnings, error) { + jobURLString, warnings, err := client.MakeRequest(RequestParams{ + RequestName: internal.DeleteRoutePolicyRequest, + URIParams: internal.Params{"route_policy_guid": guid}, + }) + + return JobURL(jobURLString), warnings, err +} diff --git a/cf/actors/push.go b/cf/actors/push.go index b51322b084f..36a093e2ce5 100644 --- a/cf/actors/push.go +++ b/cf/actors/push.go @@ -7,9 +7,9 @@ import ( "path/filepath" "runtime" - "errors" + "errors" - "code.cloudfoundry.org/cli/v9/cf/api/applicationbits" + "code.cloudfoundry.org/cli/v9/cf/api/applicationbits" "code.cloudfoundry.org/cli/v9/cf/api/resources" "code.cloudfoundry.org/cli/v9/cf/appfiles" . "code.cloudfoundry.org/cli/v9/cf/i18n" diff --git a/cf/cli b/cf/cli new file mode 100755 index 00000000000..0a804bcceee Binary files /dev/null and b/cf/cli differ diff --git a/cf/net/warnings_collector.go b/cf/net/warnings_collector.go index 5b164e0b39b..6b2991f7c48 100644 --- a/cf/net/warnings_collector.go +++ b/cf/net/warnings_collector.go @@ -4,9 +4,9 @@ import ( "os" "strings" - "errors" + "errors" - "code.cloudfoundry.org/cli/v9/cf/terminal" + "code.cloudfoundry.org/cli/v9/cf/terminal" ) const DeprecatedEndpointWarning = "Endpoint deprecated" diff --git a/command/common/command_list_v7.go b/command/common/command_list_v7.go index fcc833a94d3..1070a5b8e1b 100644 --- a/command/common/command_list_v7.go +++ b/command/common/command_list_v7.go @@ -15,6 +15,8 @@ type commandList struct { V3Push v7.PushCommand `command:"v3-push" description:"Push a new app or sync changes to an existing app" hidden:"true"` + RoutePolicies v7.RoutePoliciesCommand `command:"route-policies" description:"List all route policies in the target space"` + AddRoutePolicy v7.AddRoutePolicyCommand `command:"add-route-policy" description:"Add a route policy to allow specific apps, spaces, or orgs to access a route"` API v7.APICommand `command:"api" description:"Set or view target api url"` AddNetworkPolicy v7.AddNetworkPolicyCommand `command:"add-network-policy" description:"Create policy to allow direct network traffic from one app to another"` AddPluginRepo plugin.AddPluginRepoCommand `command:"add-plugin-repo" description:"Add a new plugin repository"` @@ -113,6 +115,7 @@ type commandList struct { PurgeServiceOffering v7.PurgeServiceOfferingCommand `command:"purge-service-offering" description:"Recursively remove a service offering and child objects from Cloud Foundry database without making requests to a service broker"` Push v7.PushCommand `command:"push" alias:"p" description:"Push a new app or sync changes to an existing app"` RemoveNetworkPolicy v7.RemoveNetworkPolicyCommand `command:"remove-network-policy" description:"Remove network traffic policy of an app"` + RemoveRoutePolicy v7.RemoveRoutePolicyCommand `command:"remove-route-policy" description:"Remove a route policy from a route"` RemovePluginRepo plugin.RemovePluginRepoCommand `command:"remove-plugin-repo" description:"Remove a plugin repository"` Rename v7.RenameCommand `command:"rename" description:"Rename an app"` RenameOrg v7.RenameOrgCommand `command:"rename-org" description:"Rename an org"` diff --git a/command/common/internal/help_all_display.go b/command/common/internal/help_all_display.go index 8166edc0ba2..b6bcd70f140 100644 --- a/command/common/internal/help_all_display.go +++ b/command/common/internal/help_all_display.go @@ -72,6 +72,7 @@ var HelpCategoryList = []HelpCategory{ {"update-destination"}, {"share-route", "unshare-route"}, {"move-route"}, + {"route-policies", "add-route-policy", "remove-route-policy"}, }, }, { diff --git a/command/flag/arguments.go b/command/flag/arguments.go index 9e3d60263f8..23ee422eace 100644 --- a/command/flag/arguments.go +++ b/command/flag/arguments.go @@ -413,3 +413,15 @@ type TaskArgs struct { AppName string `positional-arg-name:"APP_NAME" required:"true" description:"The application name"` TaskID int `positional-arg-name:"TASK_ID" required:"true" description:"The Task ID for the application"` } + +type AddRoutePolicyArgs struct { + Domain string `positional-arg-name:"DOMAIN" required:"true" description:"Domain for the route"` +} + +type RemoveRoutePolicyArgs struct { + Domain string `positional-arg-name:"DOMAIN" required:"true" description:"Domain for the route"` +} + +type RemoveAccessRuleArgs struct { + Domain string `positional-arg-name:"DOMAIN" required:"true" description:"The domain name"` +} diff --git a/command/v7/actor.go b/command/v7/actor.go index daeac22dd0a..eb8822fcbca 100644 --- a/command/v7/actor.go +++ b/command/v7/actor.go @@ -23,6 +23,7 @@ import ( type Actor interface { ApplyOrganizationQuotaByName(quotaName string, orgGUID string) (v7action.Warnings, error) ApplySpaceQuotaByName(quotaName string, spaceGUID string, orgGUID string) (v7action.Warnings, error) + AddRoutePolicy(domainName, source, hostname, path string) (v7action.Warnings, error) AssignIsolationSegmentToSpaceByNameAndSpace(isolationSegmentName string, spaceGUID string) (v7action.Warnings, error) Authenticate(credentials map[string]string, origin string, grantType uaa.GrantType) error BindSecurityGroupToSpaces(securityGroupGUID string, spaces []resources.Space, lifecycle constant.SecurityGroupLifecycle) (v7action.Warnings, error) @@ -44,20 +45,21 @@ type Actor interface { CreateOrgRole(roleType constant.RoleType, orgGUID string, userNameOrGUID string, userOrigin string, isClient bool) (v7action.Warnings, error) CreateOrganization(orgName string) (resources.Organization, v7action.Warnings, error) CreateOrganizationQuota(name string, limits v7action.QuotaLimits) (v7action.Warnings, error) - CreatePrivateDomain(domainName string, orgName string) (v7action.Warnings, error) + CreatePrivateDomain(domainName string, orgName string, enforceAccessRules bool, accessRulesScope string) (v7action.Warnings, error) CreateRoute(spaceGUID, domainName, hostname, path string, port int, options map[string]*string) (resources.Route, v7action.Warnings, error) CreateRouteBinding(params v7action.CreateRouteBindingParams) (chan v7action.PollJobEvent, v7action.Warnings, error) CreateSecurityGroup(name, filePath string) (v7action.Warnings, error) CreateServiceAppBinding(params v7action.CreateServiceAppBindingParams) (chan v7action.PollJobEvent, v7action.Warnings, error) CreateServiceBroker(model resources.ServiceBroker) (v7action.Warnings, error) CreateServiceKey(params v7action.CreateServiceKeyParams) (chan v7action.PollJobEvent, v7action.Warnings, error) - CreateSharedDomain(domainName string, internal bool, routerGroupName string) (v7action.Warnings, error) + CreateSharedDomain(domainName string, internal bool, routerGroupName string, enforceAccessRules bool, accessRulesScope string) (v7action.Warnings, error) CreateSpace(spaceName, orgGUID string) (resources.Space, v7action.Warnings, error) CreateSpaceQuota(spaceQuotaName string, orgGuid string, limits v7action.QuotaLimits) (v7action.Warnings, error) CreateSpaceRole(roleType constant.RoleType, orgGUID string, spaceGUID string, userNameOrGUID string, userOrigin string, isClient bool) (v7action.Warnings, error) CreateUser(username string, password string, origin string) (resources.User, v7action.Warnings, error) CreateUserProvidedServiceInstance(instance resources.ServiceInstance) (v7action.Warnings, error) DeleteApplicationByNameAndSpace(name, spaceGUID string, deleteRoutes bool) (v7action.Warnings, error) + DeleteRoutePolicyBySource(domainName, source, hostname, path string) (v7action.Warnings, error) DeleteBuildpackByNameAndStackAndLifecycle(buildpackName string, buildpackStack string, buildpackLifecycle string) (v7action.Warnings, error) DeleteDomain(domain resources.Domain) (v7action.Warnings, error) DeleteInstanceByApplicationNameSpaceProcessTypeAndIndex(appName string, spaceGUID string, processType string, instanceIndex int) (v7action.Warnings, error) @@ -87,6 +89,8 @@ type Actor interface { EnableServiceAccess(offeringName, brokerName, orgName, planName string) (v7action.SkippedPlans, v7action.Warnings, error) EntitleIsolationSegmentToOrganizationByName(isolationSegmentName string, orgName string) (v7action.Warnings, error) GetAppFeature(appGUID string, featureName string) (resources.ApplicationFeature, v7action.Warnings, error) + GetRoutePoliciesByRoute(domainName, hostname, path string) ([]resources.RoutePolicy, v7action.Warnings, error) + GetRoutePoliciesForSpace(spaceGUID string, domainName string, hostname string, path string, labelSelector string) ([]v7action.RoutePolicyWithRoute, v7action.Warnings, error) GetAppSummariesForSpace(spaceGUID string, labels string, omitStats bool) ([]v7action.ApplicationSummary, v7action.Warnings, error) GetApplicationByNameAndSpace(appName string, spaceGUID string) (resources.Application, v7action.Warnings, error) GetApplicationMapForRoute(route resources.Route) (map[string]resources.Application, v7action.Warnings, error) diff --git a/command/v7/add_route_policy_command.go b/command/v7/add_route_policy_command.go new file mode 100644 index 00000000000..7845d4b7e3e --- /dev/null +++ b/command/v7/add_route_policy_command.go @@ -0,0 +1,278 @@ +package v7 + +import ( + "fmt" + + "code.cloudfoundry.org/cli/v9/actor/actionerror" + "code.cloudfoundry.org/cli/v9/actor/v7action" + "code.cloudfoundry.org/cli/v9/command/flag" + "code.cloudfoundry.org/cli/v9/command/translatableerror" +) + +type AddRoutePolicyCommand struct { + BaseCommand + + RequiredArgs flag.AddRoutePolicyArgs `positional-args:"yes"` + Hostname string `long:"hostname" required:"true" description:"Hostname for the route"` + Path string `long:"path" description:"Path for the route"` + + // Source resolution flags (mutually exclusive as primary source) + SourceApp string `long:"source-app" description:"Allow access from this app (by name)"` + SourceSpace string `long:"source-space" description:"Allow access from all apps in this space (by name) or specify the space for --source-app"` + SourceOrg string `long:"source-org" description:"Allow access from all apps in this org (by name) or specify the org for --source-space/--source-app"` + SourceAny bool `long:"source-any" description:"Allow access from any authenticated app"` + + // Advanced: raw source flag + Source string `long:"source" description:"Raw source (cf:app:, cf:space:, cf:org:, or cf:any)"` + + usage interface{} `usage:"CF_NAME add-route-policy DOMAIN --hostname HOSTNAME [--source-app APP_NAME [--source-space SPACE_NAME] [--source-org ORG_NAME] | --source-space SPACE_NAME [--source-org ORG_NAME] | --source-org ORG_NAME | --source-any | --source SOURCE] [--path PATH]\n\nALLOW ACCESS TO A ROUTE:\n Create a route policy that allows specific apps, spaces, or orgs to access a route using mTLS authentication.\n\nEXAMPLES:\n # Allow the \"frontend-app\" (in current space) to access the backend route\n cf add-route-policy apps.identity --source-app frontend-app --hostname backend\n\n # Allow an app in a different space to access the route\n cf add-route-policy apps.identity --source-app api-client --source-space other-space --hostname backend\n\n # Allow an app in a different org to access the route\n cf add-route-policy apps.identity --source-app external-client --source-space external-space --source-org external-org --hostname backend\n\n # Allow all apps in the \"monitoring\" space to access the API metrics endpoint\n cf add-route-policy apps.identity --source-space monitoring --hostname api --path /metrics\n\n # Allow all apps in a space in a different org\n cf add-route-policy apps.identity --source-space prod-space --source-org prod-org --hostname api\n\n # Allow all apps in the \"platform\" org to access the route\n cf add-route-policy apps.identity --source-org platform --hostname shared-api\n\n # Allow any authenticated app to access the public API\n cf add-route-policy apps.identity --source-any --hostname public-api\n\n # Use raw source (advanced)\n cf add-route-policy apps.identity --source cf:app:d76446a1-f429-4444-8797-be2f78b75b08 --hostname backend"` + relatedCommands interface{} `related_commands:"route-policies, remove-route-policy, create-shared-domain"` +} + +func (cmd AddRoutePolicyCommand) Execute(args []string) error { + // Validate source flags + if err := cmd.validateSourceFlags(); err != nil { + return err + } + + err := cmd.SharedActor.CheckTarget(true, true) + if err != nil { + return err + } + + user, err := cmd.Actor.GetCurrentUser() + if err != nil { + return err + } + + // Resolve source from source flags + source, scopeDisplay, warnings, err := cmd.resolveSource() + cmd.UI.DisplayWarnings(warnings) + if err != nil { + return err + } + + // Validate source format + if err := validateSource(source); err != nil { + return err + } + + domainName := cmd.RequiredArgs.Domain + + cmd.UI.DisplayTextWithFlavor("Adding route policy for route {{.Hostname}}.{{.Domain}}{{.Path}} as {{.User}}...", + map[string]interface{}{ + "Hostname": cmd.Hostname, + "Domain": domainName, + "Path": formatPath(cmd.Path), + "User": user.Name, + }) + + // Display resolved source (for transparency) + cmd.UI.DisplayText(" {{.ScopeDisplay}}", + map[string]interface{}{ + "ScopeDisplay": scopeDisplay, + }) + cmd.UI.DisplayText(" source: {{.Source}}", + map[string]interface{}{ + "Source": source, + }) + + warnings, err = cmd.Actor.AddRoutePolicy(domainName, source, cmd.Hostname, cmd.Path) + cmd.UI.DisplayWarnings(warnings) + if err != nil { + return err + } + + cmd.UI.DisplayOK() + + return nil +} + +// validateSourceFlags ensures exactly one source target is specified and validates combinations +func (cmd AddRoutePolicyCommand) validateSourceFlags() error { + sourceFlags := []string{} + + if cmd.Source != "" { + sourceFlags = append(sourceFlags, "--source") + } + if cmd.SourceApp != "" { + sourceFlags = append(sourceFlags, "--source-app") + } + if cmd.SourceSpace != "" && cmd.SourceApp == "" { + // --source-space only counts as a primary source if --source-app is NOT provided + sourceFlags = append(sourceFlags, "--source-space") + } + if cmd.SourceOrg != "" && cmd.SourceSpace == "" && cmd.SourceApp == "" { + // --source-org only counts as a primary source if neither --source-space nor --source-app are provided + sourceFlags = append(sourceFlags, "--source-org") + } + if cmd.SourceAny { + sourceFlags = append(sourceFlags, "--source-any") + } + + if len(sourceFlags) == 0 { + return translatableerror.RequiredArgumentError{ + ArgumentName: "one of: --source-app, --source-space, --source-org, --source-any, or --source", + } + } + + if len(sourceFlags) > 1 { + return translatableerror.ArgumentCombinationError{ + Args: sourceFlags, + } + } + + return nil +} + +// resolveSource resolves source flags to a source string +// Returns (source, scopeDisplay, warnings, error) +// scopeDisplay is a human-readable description for output (e.g., "scope: app, source: frontend-app") +func (cmd AddRoutePolicyCommand) resolveSource() (string, string, v7action.Warnings, error) { + var allWarnings v7action.Warnings + + // Priority: --source flag (raw source, no resolution needed) + if cmd.Source != "" { + return cmd.Source, fmt.Sprintf("source: %s", cmd.Source), allWarnings, nil + } + + // --source-any + if cmd.SourceAny { + return "cf:any", "scope: any, source: any authenticated app", allWarnings, nil + } + + // --source-app (with optional --source-space and --source-org for cross-space/org lookup) + if cmd.SourceApp != "" { + // Determine space GUID for app lookup + spaceGUID := cmd.Config.TargetedSpace().GUID + spaceName := cmd.Config.TargetedSpace().Name + orgName := cmd.Config.TargetedOrganization().Name + + if cmd.SourceSpace != "" { + // Determine org GUID for space lookup + orgGUID := cmd.Config.TargetedOrganization().GUID + if cmd.SourceOrg != "" { + org, warnings, err := cmd.Actor.GetOrganizationByName(cmd.SourceOrg) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return "", "", allWarnings, err + } + orgGUID = org.GUID + orgName = cmd.SourceOrg + } + + // Resolve space by name + space, warnings, err := cmd.Actor.GetSpaceByNameAndOrganization(cmd.SourceSpace, orgGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return "", "", allWarnings, err + } + spaceGUID = space.GUID + spaceName = cmd.SourceSpace + } + + // Resolve app by name in the determined space + app, warnings, err := cmd.Actor.GetApplicationByNameAndSpace(cmd.SourceApp, spaceGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + // Enhanced error message for app not found + if _, ok := err.(actionerror.ApplicationNotFoundError); ok { + if cmd.SourceSpace == "" { + // App not found in current space + return "", "", allWarnings, fmt.Errorf( + "App '%s' not found in space '%s' / org '%s'.\nTIP: If the app is in a different space or org, use --source-space and/or --source-org flags.", + cmd.SourceApp, + cmd.Config.TargetedSpace().Name, + cmd.Config.TargetedOrganization().Name, + ) + } + } + return "", "", allWarnings, err + } + + scopeDisplay := fmt.Sprintf("scope: app, source: %s", cmd.SourceApp) + if cmd.SourceSpace != "" { + scopeDisplay += fmt.Sprintf(" (space: %s", spaceName) + if cmd.SourceOrg != "" { + scopeDisplay += fmt.Sprintf(", org: %s", orgName) + } + scopeDisplay += ")" + } + + return fmt.Sprintf("cf:app:%s", app.GUID), scopeDisplay, allWarnings, nil + } + + // --source-space (without --source-app, so create space-level policy) + if cmd.SourceSpace != "" { + // Determine org GUID for space lookup + orgGUID := cmd.Config.TargetedOrganization().GUID + orgName := cmd.Config.TargetedOrganization().Name + if cmd.SourceOrg != "" { + org, warnings, err := cmd.Actor.GetOrganizationByName(cmd.SourceOrg) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return "", "", allWarnings, err + } + orgGUID = org.GUID + orgName = cmd.SourceOrg + } + + // Resolve space by name + space, warnings, err := cmd.Actor.GetSpaceByNameAndOrganization(cmd.SourceSpace, orgGUID) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return "", "", allWarnings, err + } + + scopeDisplay := fmt.Sprintf("scope: space, source: %s", cmd.SourceSpace) + if cmd.SourceOrg != "" { + scopeDisplay += fmt.Sprintf(" (org: %s)", orgName) + } + + return fmt.Sprintf("cf:space:%s", space.GUID), scopeDisplay, allWarnings, nil + } + + // --source-org (without --source-space or --source-app, so create org-level policy) + if cmd.SourceOrg != "" { + org, warnings, err := cmd.Actor.GetOrganizationByName(cmd.SourceOrg) + allWarnings = append(allWarnings, warnings...) + if err != nil { + return "", "", allWarnings, err + } + + scopeDisplay := fmt.Sprintf("scope: org, source: %s", cmd.SourceOrg) + + return fmt.Sprintf("cf:org:%s", org.GUID), scopeDisplay, allWarnings, nil + } + + // Should never reach here due to validation + return "", "", allWarnings, fmt.Errorf("no source specified") +} + +func validateSource(source string) error { + // Basic validation - check for cf:app:, cf:space:, cf:org:, or cf:any prefix + validPrefixes := []string{"cf:app:", "cf:space:", "cf:org:", "cf:any"} + for _, prefix := range validPrefixes { + if len(source) >= len(prefix) && source[:len(prefix)] == prefix { + if prefix == "cf:any" { + if source != "cf:any" { + return fmt.Errorf("source 'cf:any' must not have a GUID suffix") + } + return nil + } + // For other sources, ensure there's a GUID after the prefix + if len(source) <= len(prefix) { + return fmt.Errorf("source '%s' must include a GUID (e.g., %s)", source, prefix) + } + return nil + } + } + return fmt.Errorf("source must start with one of: cf:app:, cf:space:, cf:org:, or be exactly 'cf:any'") +} + +func formatPath(path string) string { + if path == "" { + return "" + } + return path +} diff --git a/command/v7/buildpacks_command.go b/command/v7/buildpacks_command.go index 8ccdc1d5f63..4c8d3dc06dd 100644 --- a/command/v7/buildpacks_command.go +++ b/command/v7/buildpacks_command.go @@ -3,8 +3,8 @@ package v7 import ( "strconv" - "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccversion" - "code.cloudfoundry.org/cli/v9/command" + "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccversion" + "code.cloudfoundry.org/cli/v9/command" "code.cloudfoundry.org/cli/v9/resources" "code.cloudfoundry.org/cli/v9/util/ui" ) diff --git a/command/v7/buildpacks_command_test.go b/command/v7/buildpacks_command_test.go index 41240936ba0..34ca62acae4 100644 --- a/command/v7/buildpacks_command_test.go +++ b/command/v7/buildpacks_command_test.go @@ -10,7 +10,7 @@ import ( "code.cloudfoundry.org/cli/v9/actor/v7action" "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" "code.cloudfoundry.org/cli/v9/command/commandfakes" - "code.cloudfoundry.org/cli/v9/command/translatableerror" + "code.cloudfoundry.org/cli/v9/command/translatableerror" . "code.cloudfoundry.org/cli/v9/command/v7" "code.cloudfoundry.org/cli/v9/command/v7/v7fakes" "code.cloudfoundry.org/cli/v9/util/configv3" diff --git a/command/v7/copy_source_command.go b/command/v7/copy_source_command.go index 9a9b73c26ac..658deb4e6c6 100644 --- a/command/v7/copy_source_command.go +++ b/command/v7/copy_source_command.go @@ -1,18 +1,18 @@ package v7 import ( - "strconv" - "strings" + "strconv" + "strings" - "code.cloudfoundry.org/cli/v9/actor/v7action" + "code.cloudfoundry.org/cli/v9/actor/v7action" "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" - "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccversion" + "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccversion" "code.cloudfoundry.org/cli/v9/api/logcache" "code.cloudfoundry.org/cli/v9/command" "code.cloudfoundry.org/cli/v9/command/flag" "code.cloudfoundry.org/cli/v9/command/translatableerror" "code.cloudfoundry.org/cli/v9/command/v7/shared" - "code.cloudfoundry.org/cli/v9/resources" + "code.cloudfoundry.org/cli/v9/resources" "code.cloudfoundry.org/cli/v9/util/configv3" ) diff --git a/command/v7/create_buildpack_command.go b/command/v7/create_buildpack_command.go index da6cbac2c8c..7017a115229 100644 --- a/command/v7/create_buildpack_command.go +++ b/command/v7/create_buildpack_command.go @@ -6,7 +6,7 @@ import ( "code.cloudfoundry.org/cli/v9/actor/v7action" "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccerror" - "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccversion" + "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccversion" "code.cloudfoundry.org/cli/v9/command" "code.cloudfoundry.org/cli/v9/command/flag" "code.cloudfoundry.org/cli/v9/command/translatableerror" diff --git a/command/v7/create_private_domain_command.go b/command/v7/create_private_domain_command.go index 2701ca91c47..62ff3143314 100644 --- a/command/v7/create_private_domain_command.go +++ b/command/v7/create_private_domain_command.go @@ -10,9 +10,11 @@ import ( type CreatePrivateDomainCommand struct { BaseCommand - RequiredArgs flag.OrgDomain `positional-args:"yes"` - usage interface{} `usage:"CF_NAME create-private-domain ORG DOMAIN"` - relatedCommands interface{} `related_commands:"create-shared-domain, domains, share-private-domain"` + RequiredArgs flag.OrgDomain `positional-args:"yes"` + EnforceRoutePolicies bool `long:"enforce-route-policies" description:"Enable platform-enforced access control for routes on this domain (requires mTLS domain configuration in GoRouter)"` + Scope string `long:"scope" description:"Operator-level scope boundary for route policies: 'any', 'org', or 'space' (only valid with --enforce-route-policies)"` + usage interface{} `usage:"CF_NAME create-private-domain ORG DOMAIN [--enforce-route-policies [--scope (any|org|space)]]"` + relatedCommands interface{} `related_commands:"create-shared-domain, domains, share-private-domain, add-route-policy, route-policies"` } func (cmd CreatePrivateDomainCommand) Execute(args []string) error { @@ -29,6 +31,16 @@ func (cmd CreatePrivateDomainCommand) Execute(args []string) error { domain := cmd.RequiredArgs.Domain orgName := cmd.RequiredArgs.Organization + // Validate that --scope is only used with --enforce-route-policies + if cmd.Scope != "" && !cmd.EnforceRoutePolicies { + return fmt.Errorf("--scope can only be used with --enforce-route-policies") + } + + // Validate scope values + if cmd.Scope != "" && cmd.Scope != "any" && cmd.Scope != "org" && cmd.Scope != "space" { + return fmt.Errorf("--scope must be one of: any, org, space") + } + cmd.UI.DisplayTextWithFlavor("Creating private domain {{.Domain}} for org {{.Organization}} as {{.User}}...", map[string]interface{}{ "Domain": domain, @@ -36,7 +48,7 @@ func (cmd CreatePrivateDomainCommand) Execute(args []string) error { "Organization": orgName, }) - warnings, err := cmd.Actor.CreatePrivateDomain(domain, orgName) + warnings, err := cmd.Actor.CreatePrivateDomain(domain, orgName, cmd.EnforceRoutePolicies, cmd.Scope) cmd.UI.DisplayWarnings(warnings) if err != nil { @@ -53,9 +65,16 @@ func (cmd CreatePrivateDomainCommand) Execute(args []string) error { cmd.UI.DisplayOK() - cmd.UI.DisplayText("TIP: Domain '{{.Domain}}' is a private domain. Run 'cf share-private-domain' to share this domain with a different org.", - map[string]interface{}{ - "Domain": domain, - }) + if cmd.EnforceRoutePolicies { + cmd.UI.DisplayText("TIP: Domain '{{.Domain}}' is a private identity-aware domain with route policy enforcement enabled. Routes on this domain require route policies to allow traffic.", + map[string]interface{}{ + "Domain": domain, + }) + } else { + cmd.UI.DisplayText("TIP: Domain '{{.Domain}}' is a private domain. Run 'cf share-private-domain' to share this domain with a different org.", + map[string]interface{}{ + "Domain": domain, + }) + } return nil } diff --git a/command/v7/create_private_domain_command_test.go b/command/v7/create_private_domain_command_test.go index 67db5bf98cd..d30941f39d7 100644 --- a/command/v7/create_private_domain_command_test.go +++ b/command/v7/create_private_domain_command_test.go @@ -113,7 +113,7 @@ var _ = Describe("create-private-domain Command", func() { It("creates the domain", func() { Expect(fakeActor.CreatePrivateDomainCallCount()).To(Equal(1)) - expectedDomainName, expectedOrgName := fakeActor.CreatePrivateDomainArgsForCall(0) + expectedDomainName, expectedOrgName, _, _ := fakeActor.CreatePrivateDomainArgsForCall(0) Expect(expectedDomainName).To(Equal(domainName)) Expect(expectedOrgName).To(Equal(orgName)) }) diff --git a/command/v7/create_route_command.go b/command/v7/create_route_command.go index 9c203ebbbb7..ff4dd6fc3a3 100644 --- a/command/v7/create_route_command.go +++ b/command/v7/create_route_command.go @@ -7,8 +7,8 @@ import ( "code.cloudfoundry.org/cli/v9/command" "code.cloudfoundry.org/cli/v9/resources" - "code.cloudfoundry.org/cli/v9/actor/actionerror" - "code.cloudfoundry.org/cli/v9/command/flag" + "code.cloudfoundry.org/cli/v9/actor/actionerror" + "code.cloudfoundry.org/cli/v9/command/flag" ) type CreateRouteCommand struct { diff --git a/command/v7/create_route_command_test.go b/command/v7/create_route_command_test.go index 8803a9bcce5..23dc37ebed2 100644 --- a/command/v7/create_route_command_test.go +++ b/command/v7/create_route_command_test.go @@ -7,7 +7,7 @@ import ( "code.cloudfoundry.org/cli/v9/actor/actionerror" "code.cloudfoundry.org/cli/v9/actor/v7action" - "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccversion" + "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccversion" "code.cloudfoundry.org/cli/v9/command/commandfakes" "code.cloudfoundry.org/cli/v9/command/flag" . "code.cloudfoundry.org/cli/v9/command/v7" diff --git a/command/v7/create_shared_domain_command.go b/command/v7/create_shared_domain_command.go index e48ec61dd6f..169133915aa 100644 --- a/command/v7/create_shared_domain_command.go +++ b/command/v7/create_shared_domain_command.go @@ -1,17 +1,21 @@ package v7 import ( + "fmt" + "code.cloudfoundry.org/cli/v9/command/flag" ) type CreateSharedDomainCommand struct { BaseCommand - RequiredArgs flag.Domain `positional-args:"yes"` - RouterGroup string `long:"router-group" description:"Routes for this domain will use routers in the specified router group"` - Internal bool `long:"internal" description:"Applications that use internal routes communicate directly on the container network"` - usage interface{} `usage:"CF_NAME create-shared-domain DOMAIN [--router-group ROUTER_GROUP_NAME | --internal]"` - relatedCommands interface{} `related_commands:"create-private-domain, domains"` + RequiredArgs flag.Domain `positional-args:"yes"` + RouterGroup string `long:"router-group" description:"Routes for this domain will use routers in the specified router group"` + Internal bool `long:"internal" description:"Applications that use internal routes communicate directly on the container network"` + EnforceRoutePolicies bool `long:"enforce-route-policies" description:"Enable platform-enforced access control for routes on this domain (requires mTLS domain configuration in GoRouter)"` + Scope string `long:"scope" description:"Operator-level scope boundary for route policies: 'any', 'org', or 'space' (only valid with --enforce-route-policies)"` + usage interface{} `usage:"CF_NAME create-shared-domain DOMAIN [--router-group ROUTER_GROUP_NAME | --internal] [--enforce-route-policies [--scope (any|org|space)]]"` + relatedCommands interface{} `related_commands:"create-private-domain, domains, add-route-policy, route-policies"` } func (cmd CreateSharedDomainCommand) Execute(args []string) error { @@ -27,22 +31,40 @@ func (cmd CreateSharedDomainCommand) Execute(args []string) error { domain := cmd.RequiredArgs.Domain + // Validate that --scope is only used with --enforce-route-policies + if cmd.Scope != "" && !cmd.EnforceRoutePolicies { + return fmt.Errorf("--scope can only be used with --enforce-route-policies") + } + + // Validate scope values + if cmd.Scope != "" && cmd.Scope != "any" && cmd.Scope != "org" && cmd.Scope != "space" { + return fmt.Errorf("--scope must be one of: any, org, space") + } + cmd.UI.DisplayTextWithFlavor("Creating shared domain {{.Domain}} as {{.User}}...", map[string]interface{}{ "Domain": domain, "User": user.Name, }) - warnings, err := cmd.Actor.CreateSharedDomain(domain, cmd.Internal, cmd.RouterGroup) + warnings, err := cmd.Actor.CreateSharedDomain(domain, cmd.Internal, cmd.RouterGroup, cmd.EnforceRoutePolicies, cmd.Scope) cmd.UI.DisplayWarnings(warnings) if err != nil { return err } cmd.UI.DisplayOK() - cmd.UI.DisplayText("TIP: Domain '{{.Domain}}' is shared with all orgs. Run 'cf domains' to view available domains.", - map[string]interface{}{ - "Domain": domain, - }) + + if cmd.EnforceRoutePolicies { + cmd.UI.DisplayText("TIP: Domain '{{.Domain}}' is a shared identity-aware domain with route policy enforcement enabled. Routes on this domain require route policies to allow traffic.", + map[string]interface{}{ + "Domain": domain, + }) + } else { + cmd.UI.DisplayText("TIP: Domain '{{.Domain}}' is shared with all orgs. Run 'cf domains' to view available domains.", + map[string]interface{}{ + "Domain": domain, + }) + } return nil } diff --git a/command/v7/create_shared_domain_command_test.go b/command/v7/create_shared_domain_command_test.go index 9df31c8cbb3..6e757f92859 100644 --- a/command/v7/create_shared_domain_command_test.go +++ b/command/v7/create_shared_domain_command_test.go @@ -126,7 +126,7 @@ var _ = Describe("create-shared-domain Command", func() { It("creates the domain", func() { Expect(fakeActor.CreateSharedDomainCallCount()).To(Equal(1)) - expectedDomainName, expectedInternal, expectedRouterGroup := fakeActor.CreateSharedDomainArgsForCall(0) + expectedDomainName, expectedInternal, expectedRouterGroup, _, _ := fakeActor.CreateSharedDomainArgsForCall(0) Expect(expectedDomainName).To(Equal(domainName)) Expect(expectedInternal).To(BeTrue()) Expect(expectedRouterGroup).To(Equal("router-group")) diff --git a/command/v7/create_user_provided_service_command.go b/command/v7/create_user_provided_service_command.go index c5d9ec963c0..c329297ad51 100644 --- a/command/v7/create_user_provided_service_command.go +++ b/command/v7/create_user_provided_service_command.go @@ -1,7 +1,7 @@ package v7 import ( - "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccerror" + "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccerror" "code.cloudfoundry.org/cli/v9/command" "code.cloudfoundry.org/cli/v9/command/flag" "code.cloudfoundry.org/cli/v9/resources" diff --git a/command/v7/delete_buildpack_command.go b/command/v7/delete_buildpack_command.go index aa139a1b63d..a564ec7051f 100644 --- a/command/v7/delete_buildpack_command.go +++ b/command/v7/delete_buildpack_command.go @@ -2,8 +2,8 @@ package v7 import ( "code.cloudfoundry.org/cli/v9/actor/actionerror" - "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccversion" - "code.cloudfoundry.org/cli/v9/command" + "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccversion" + "code.cloudfoundry.org/cli/v9/command" "code.cloudfoundry.org/cli/v9/command/flag" ) diff --git a/command/v7/delete_buildpack_command_test.go b/command/v7/delete_buildpack_command_test.go index 2a61cf2e6ad..2bf7ef7f22d 100644 --- a/command/v7/delete_buildpack_command_test.go +++ b/command/v7/delete_buildpack_command_test.go @@ -6,7 +6,7 @@ import ( "code.cloudfoundry.org/cli/v9/actor/actionerror" "code.cloudfoundry.org/cli/v9/actor/v7action" "code.cloudfoundry.org/cli/v9/command/commandfakes" - "code.cloudfoundry.org/cli/v9/command/translatableerror" + "code.cloudfoundry.org/cli/v9/command/translatableerror" . "code.cloudfoundry.org/cli/v9/command/v7" "code.cloudfoundry.org/cli/v9/command/v7/v7fakes" "code.cloudfoundry.org/cli/v9/util/ui" diff --git a/command/v7/remove_route_policy_command.go b/command/v7/remove_route_policy_command.go new file mode 100644 index 00000000000..e026d2fd918 --- /dev/null +++ b/command/v7/remove_route_policy_command.go @@ -0,0 +1,73 @@ +package v7 + +import ( + "code.cloudfoundry.org/cli/v9/command/flag" +) + +type RemoveRoutePolicyCommand struct { + BaseCommand + + RequiredArgs flag.RemoveRoutePolicyArgs `positional-args:"yes"` + Source string `long:"source" required:"true" description:"Source to identify the route policy (cf:app:, cf:space:, cf:org:, or cf:any)"` + Hostname string `long:"hostname" required:"true" description:"Hostname for the route"` + Path string `long:"path" description:"Path for the route"` + Force bool `short:"f" description:"Force deletion without confirmation"` + usage interface{} `usage:"CF_NAME remove-route-policy DOMAIN --source SOURCE --hostname HOSTNAME [--path PATH] [-f]\n\nEXAMPLES:\n cf remove-route-policy apps.identity --source cf:app:d76446a1-f429-4444-8797-be2f78b75b08 --hostname backend\n cf remove-route-policy apps.identity --source cf:space:2b26e210-1b48-4e60-8432-f24bc5927789 --hostname api --path /metrics -f\n cf remove-route-policy apps.identity --source cf:any --hostname public-api -f"` + relatedCommands interface{} `related_commands:"route-policies, add-route-policy"` +} + +func (cmd RemoveRoutePolicyCommand) Execute(args []string) error { + err := cmd.SharedActor.CheckTarget(true, true) + if err != nil { + return err + } + + user, err := cmd.Actor.GetCurrentUser() + if err != nil { + return err + } + + // Validate source format + if err := validateSource(cmd.Source); err != nil { + return err + } + + domainName := cmd.RequiredArgs.Domain + + if !cmd.Force { + prompt := "Really remove route policy with source {{.Source}} for route {{.Hostname}}.{{.Domain}}{{.Path}}?" + response, promptErr := cmd.UI.DisplayBoolPrompt(false, prompt, map[string]interface{}{ + "Source": cmd.Source, + "Hostname": cmd.Hostname, + "Domain": domainName, + "Path": formatPath(cmd.Path), + }) + + if promptErr != nil { + return promptErr + } + + if !response { + cmd.UI.DisplayText("Route policy has not been removed.") + return nil + } + } + + cmd.UI.DisplayTextWithFlavor("Removing route policy for route {{.Hostname}}.{{.Domain}}{{.Path}} as {{.User}}...", + map[string]interface{}{ + "Hostname": cmd.Hostname, + "Domain": domainName, + "Path": formatPath(cmd.Path), + "User": user.Name, + }) + + warnings, err := cmd.Actor.DeleteRoutePolicyBySource(domainName, cmd.Source, cmd.Hostname, cmd.Path) + cmd.UI.DisplayWarnings(warnings) + if err != nil { + return err + } + + cmd.UI.DisplayOK() + + return nil +} diff --git a/command/v7/restage_command.go b/command/v7/restage_command.go index 35042ac3285..ea39d1d32c0 100644 --- a/command/v7/restage_command.go +++ b/command/v7/restage_command.go @@ -1,19 +1,19 @@ package v7 import ( - "strconv" - "strings" + "strconv" + "strings" - "code.cloudfoundry.org/cli/v9/actor/actionerror" + "code.cloudfoundry.org/cli/v9/actor/actionerror" "code.cloudfoundry.org/cli/v9/actor/v7action" "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" - "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccversion" + "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccversion" "code.cloudfoundry.org/cli/v9/api/logcache" "code.cloudfoundry.org/cli/v9/command" "code.cloudfoundry.org/cli/v9/command/flag" "code.cloudfoundry.org/cli/v9/command/translatableerror" "code.cloudfoundry.org/cli/v9/command/v7/shared" - "code.cloudfoundry.org/cli/v9/resources" + "code.cloudfoundry.org/cli/v9/resources" ) type RestageCommand struct { diff --git a/command/v7/restart_command.go b/command/v7/restart_command.go index 6fc987a4e8b..fda8b0ef4b1 100644 --- a/command/v7/restart_command.go +++ b/command/v7/restart_command.go @@ -1,18 +1,18 @@ package v7 import ( - "strconv" - "strings" + "strconv" + "strings" - "code.cloudfoundry.org/cli/v9/actor/v7action" + "code.cloudfoundry.org/cli/v9/actor/v7action" "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" - "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccversion" + "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccversion" "code.cloudfoundry.org/cli/v9/api/logcache" "code.cloudfoundry.org/cli/v9/command" "code.cloudfoundry.org/cli/v9/command/flag" "code.cloudfoundry.org/cli/v9/command/translatableerror" "code.cloudfoundry.org/cli/v9/command/v7/shared" - "code.cloudfoundry.org/cli/v9/resources" + "code.cloudfoundry.org/cli/v9/resources" ) type RestartCommand struct { diff --git a/command/v7/revision_command_test.go b/command/v7/revision_command_test.go index 4a55130835d..6003f11b646 100644 --- a/command/v7/revision_command_test.go +++ b/command/v7/revision_command_test.go @@ -1,18 +1,18 @@ package v7_test import ( - "errors" + "errors" - "code.cloudfoundry.org/cli/v9/actor/actionerror" - "code.cloudfoundry.org/cli/v9/actor/v7action" - "code.cloudfoundry.org/cli/v9/command/commandfakes" - "code.cloudfoundry.org/cli/v9/command/flag" + "code.cloudfoundry.org/cli/v9/actor/actionerror" + "code.cloudfoundry.org/cli/v9/actor/v7action" + "code.cloudfoundry.org/cli/v9/command/commandfakes" + "code.cloudfoundry.org/cli/v9/command/flag" v7 "code.cloudfoundry.org/cli/v9/command/v7" "code.cloudfoundry.org/cli/v9/command/v7/v7fakes" - "code.cloudfoundry.org/cli/v9/util/ui" "code.cloudfoundry.org/cli/v9/resources" "code.cloudfoundry.org/cli/v9/types" "code.cloudfoundry.org/cli/v9/util/configv3" + "code.cloudfoundry.org/cli/v9/util/ui" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" . "github.com/onsi/gomega/gbytes" diff --git a/command/v7/rollback_command.go b/command/v7/rollback_command.go index ff5ddad6ed9..abf19514f41 100644 --- a/command/v7/rollback_command.go +++ b/command/v7/rollback_command.go @@ -7,13 +7,13 @@ import ( "code.cloudfoundry.org/cli/v9/actor/sharedaction" "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" - "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccversion" + "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccversion" "code.cloudfoundry.org/cli/v9/cf/errors" "code.cloudfoundry.org/cli/v9/command" "code.cloudfoundry.org/cli/v9/command/flag" "code.cloudfoundry.org/cli/v9/command/translatableerror" "code.cloudfoundry.org/cli/v9/command/v7/shared" - "code.cloudfoundry.org/cli/v9/resources" + "code.cloudfoundry.org/cli/v9/resources" ) type RollbackCommand struct { diff --git a/command/v7/route_policies_command.go b/command/v7/route_policies_command.go new file mode 100644 index 00000000000..ef191180233 --- /dev/null +++ b/command/v7/route_policies_command.go @@ -0,0 +1,88 @@ +package v7 + +import ( + "code.cloudfoundry.org/cli/v9/util/ui" +) + +type RoutePoliciesCommand struct { + BaseCommand + + Domain string `long:"domain" description:"Filter by domain name"` + Hostname string `long:"hostname" description:"Filter by hostname"` + Path string `long:"path" description:"Filter by path"` + Labels string `long:"labels" description:"Selector to filter route policies by labels"` + + usage interface{} `usage:"CF_NAME route-policies [--domain DOMAIN] [--hostname HOSTNAME] [--path PATH] [--labels SELECTOR]\n\nEXAMPLES:\n cf route-policies\n cf route-policies --domain apps.identity\n cf route-policies --domain apps.identity --hostname backend\n cf route-policies --labels env=prod"` + relatedCommands interface{} `related_commands:"add-route-policy, remove-route-policy, routes"` +} + +func (cmd RoutePoliciesCommand) Execute(args []string) error { + // Check target (org + space required) + err := cmd.SharedActor.CheckTarget(true, true) + if err != nil { + return err + } + + // Get current user + user, err := cmd.Actor.GetCurrentUser() + if err != nil { + return err + } + + // Display contextual header + cmd.UI.DisplayTextWithFlavor( + "Getting route policies in org {{.OrgName}} / space {{.SpaceName}} as {{.Username}}...", + map[string]interface{}{ + "OrgName": cmd.Config.TargetedOrganization().Name, + "SpaceName": cmd.Config.TargetedSpace().Name, + "Username": user.Name, + }) + cmd.UI.DisplayNewline() + + // Fetch route policies for space with filters + policiesWithRoutes, warnings, err := cmd.Actor.GetRoutePoliciesForSpace( + cmd.Config.TargetedSpace().GUID, + cmd.Domain, + cmd.Hostname, + cmd.Path, + cmd.Labels, + ) + cmd.UI.DisplayWarnings(warnings) + if err != nil { + return err + } + + // Handle empty results + if len(policiesWithRoutes) == 0 { + cmd.UI.DisplayText("No route policies found.") + return nil + } + + // Build table data + table := [][]string{ + { + cmd.UI.TranslateText("host"), + cmd.UI.TranslateText("domain"), + cmd.UI.TranslateText("path"), + cmd.UI.TranslateText("source"), + cmd.UI.TranslateText("scope"), + cmd.UI.TranslateText("name"), + }, + } + + for _, policyWithRoute := range policiesWithRoutes { + table = append(table, []string{ + policyWithRoute.Route.Host, + policyWithRoute.DomainName, + policyWithRoute.Route.Path, + policyWithRoute.Source, + policyWithRoute.ScopeType, + policyWithRoute.SourceName, + }) + } + + // Display table + cmd.UI.DisplayTableWithHeader("", table, ui.DefaultTableSpacePadding) + + return nil +} diff --git a/command/v7/shared/sharedfakes/fake_app_stager.go b/command/v7/shared/sharedfakes/fake_app_stager.go index 09bb3654f5a..9e9e9f2e749 100644 --- a/command/v7/shared/sharedfakes/fake_app_stager.go +++ b/command/v7/shared/sharedfakes/fake_app_stager.go @@ -258,12 +258,6 @@ func (fake *FakeAppStager) StartAppReturnsOnCall(i int, result1 error) { func (fake *FakeAppStager) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.stageAndStartMutex.RLock() - defer fake.stageAndStartMutex.RUnlock() - fake.stageAppMutex.RLock() - defer fake.stageAppMutex.RUnlock() - fake.startAppMutex.RLock() - defer fake.startAppMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/command/v7/stack_command_test.go b/command/v7/stack_command_test.go index 537fc822704..e7819b8ba59 100644 --- a/command/v7/stack_command_test.go +++ b/command/v7/stack_command_test.go @@ -196,29 +196,29 @@ var _ = Describe("Stack Command", func() { }) }) - Context("When the state is not ACTIVE but has no reason", func() { - BeforeEach(func() { - stack := resources.Stack{ - Name: "some-stack-name", - GUID: "some-stack-guid", - Description: "some-stack-desc", - State: "RESTRICTED", - } - fakeActor.GetStackByNameReturns(stack, v7action.Warnings{}, nil) - }) + Context("When the state is not ACTIVE but has no reason", func() { + BeforeEach(func() { + stack := resources.Stack{ + Name: "some-stack-name", + GUID: "some-stack-guid", + Description: "some-stack-desc", + State: "RESTRICTED", + } + fakeActor.GetStackByNameReturns(stack, v7action.Warnings{}, nil) + }) - It("Displays the stack information with state and empty reason", func() { - Expect(executeErr).ToNot(HaveOccurred()) - Expect(fakeActor.GetStackByNameArgsForCall(0)).To(Equal("some-stack-name")) - Expect(fakeActor.GetStackByNameCallCount()).To(Equal(1)) + It("Displays the stack information with state and empty reason", func() { + Expect(executeErr).ToNot(HaveOccurred()) + Expect(fakeActor.GetStackByNameArgsForCall(0)).To(Equal("some-stack-name")) + Expect(fakeActor.GetStackByNameCallCount()).To(Equal(1)) - Expect(testUI.Out).To(Say("name:\\s+some-stack-name")) - Expect(testUI.Out).To(Say("description:\\s+some-stack-desc")) - Expect(testUI.Out).To(Say("state:\\s+RESTRICTED")) - Expect(testUI.Out).To(Say("reason:")) + Expect(testUI.Out).To(Say("name:\\s+some-stack-name")) + Expect(testUI.Out).To(Say("description:\\s+some-stack-desc")) + Expect(testUI.Out).To(Say("state:\\s+RESTRICTED")) + Expect(testUI.Out).To(Say("reason:")) + }) }) }) - }) When("The Stack does not Exist", func() { expectedError := actionerror.StackNotFoundError{Name: "some-stack-name"} diff --git a/command/v7/update_buildpack_command.go b/command/v7/update_buildpack_command.go index a45d17e3da0..a73b6524d79 100644 --- a/command/v7/update_buildpack_command.go +++ b/command/v7/update_buildpack_command.go @@ -7,7 +7,7 @@ import ( "code.cloudfoundry.org/cli/v9/actor/v7action" "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccerror" "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3" - "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccversion" + "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccversion" "code.cloudfoundry.org/cli/v9/command" "code.cloudfoundry.org/cli/v9/command/flag" "code.cloudfoundry.org/cli/v9/command/translatableerror" diff --git a/command/v7/update_stack_command_test.go b/command/v7/update_stack_command_test.go index 5b32106a392..c65d01ff834 100644 --- a/command/v7/update_stack_command_test.go +++ b/command/v7/update_stack_command_test.go @@ -158,67 +158,66 @@ var _ = Describe("update-stack Command", func() { }) }) - Context("when state values are provided in different cases", func() { - It("accepts 'active' and capitalizes it", func() { - cmd.State = "active" - fakeActor.GetStackByNameReturns(resources.Stack{GUID: "guid"}, v7action.Warnings{}, nil) - fakeActor.UpdateStackReturns(resources.Stack{Name: "some-stack", State: resources.StackStateActive}, v7action.Warnings{}, nil) + Context("when state values are provided in different cases", func() { + It("accepts 'active' and capitalizes it", func() { + cmd.State = "active" + fakeActor.GetStackByNameReturns(resources.Stack{GUID: "guid"}, v7action.Warnings{}, nil) + fakeActor.UpdateStackReturns(resources.Stack{Name: "some-stack", State: resources.StackStateActive}, v7action.Warnings{}, nil) - executeErr = cmd.Execute(args) + executeErr = cmd.Execute(args) - Expect(executeErr).ToNot(HaveOccurred()) - _, state, _ := fakeActor.UpdateStackArgsForCall(0) - Expect(state).To(Equal(resources.StackStateActive)) - }) + Expect(executeErr).ToNot(HaveOccurred()) + _, state, _ := fakeActor.UpdateStackArgsForCall(0) + Expect(state).To(Equal(resources.StackStateActive)) + }) - It("accepts 'RESTRICTED' and keeps it capitalized", func() { - cmd.State = "RESTRICTED" - fakeActor.GetStackByNameReturns(resources.Stack{GUID: "guid"}, v7action.Warnings{}, nil) - fakeActor.UpdateStackReturns(resources.Stack{Name: "some-stack", State: resources.StackStateRestricted}, v7action.Warnings{}, nil) + It("accepts 'RESTRICTED' and keeps it capitalized", func() { + cmd.State = "RESTRICTED" + fakeActor.GetStackByNameReturns(resources.Stack{GUID: "guid"}, v7action.Warnings{}, nil) + fakeActor.UpdateStackReturns(resources.Stack{Name: "some-stack", State: resources.StackStateRestricted}, v7action.Warnings{}, nil) - executeErr = cmd.Execute(args) + executeErr = cmd.Execute(args) - Expect(executeErr).ToNot(HaveOccurred()) - _, state, _ := fakeActor.UpdateStackArgsForCall(0) - Expect(state).To(Equal(resources.StackStateRestricted)) - }) + Expect(executeErr).ToNot(HaveOccurred()) + _, state, _ := fakeActor.UpdateStackArgsForCall(0) + Expect(state).To(Equal(resources.StackStateRestricted)) + }) - It("accepts 'Disabled' and capitalizes it", func() { - cmd.State = "Disabled" - fakeActor.GetStackByNameReturns(resources.Stack{GUID: "guid"}, v7action.Warnings{}, nil) - fakeActor.UpdateStackReturns(resources.Stack{Name: "some-stack", State: resources.StackStateDisabled}, v7action.Warnings{}, nil) + It("accepts 'Disabled' and capitalizes it", func() { + cmd.State = "Disabled" + fakeActor.GetStackByNameReturns(resources.Stack{GUID: "guid"}, v7action.Warnings{}, nil) + fakeActor.UpdateStackReturns(resources.Stack{Name: "some-stack", State: resources.StackStateDisabled}, v7action.Warnings{}, nil) - executeErr = cmd.Execute(args) + executeErr = cmd.Execute(args) - Expect(executeErr).ToNot(HaveOccurred()) - _, state, _ := fakeActor.UpdateStackArgsForCall(0) - Expect(state).To(Equal(resources.StackStateDisabled)) + Expect(executeErr).ToNot(HaveOccurred()) + _, state, _ := fakeActor.UpdateStackArgsForCall(0) + Expect(state).To(Equal(resources.StackStateDisabled)) + }) }) - }) - Context("when the reason flag is provided", func() { - BeforeEach(func() { - cmd.State = "deprecated" - cmd.Reason = "Use cflinuxfs4 instead" - fakeActor.GetStackByNameReturns(resources.Stack{GUID: "guid"}, v7action.Warnings{}, nil) - fakeActor.UpdateStackReturns(resources.Stack{ - Name: "some-stack", - Description: "some description", - State: resources.StackStateDeprecated, - StateReason: "Use cflinuxfs4 instead", - }, v7action.Warnings{}, nil) - }) + Context("when the reason flag is provided", func() { + BeforeEach(func() { + cmd.State = "deprecated" + cmd.Reason = "Use cflinuxfs4 instead" + fakeActor.GetStackByNameReturns(resources.Stack{GUID: "guid"}, v7action.Warnings{}, nil) + fakeActor.UpdateStackReturns(resources.Stack{ + Name: "some-stack", + Description: "some description", + State: resources.StackStateDeprecated, + StateReason: "Use cflinuxfs4 instead", + }, v7action.Warnings{}, nil) + }) - It("passes the reason to the actor and displays it", func() { - Expect(executeErr).ToNot(HaveOccurred()) + It("passes the reason to the actor and displays it", func() { + Expect(executeErr).ToNot(HaveOccurred()) - Expect(fakeActor.UpdateStackCallCount()).To(Equal(1)) - _, _, reason := fakeActor.UpdateStackArgsForCall(0) - Expect(reason).To(Equal("Use cflinuxfs4 instead")) + Expect(fakeActor.UpdateStackCallCount()).To(Equal(1)) + _, _, reason := fakeActor.UpdateStackArgsForCall(0) + Expect(reason).To(Equal("Use cflinuxfs4 instead")) - Expect(testUI.Out).To(Say(`reason:\s+Use cflinuxfs4 instead`)) + Expect(testUI.Out).To(Say(`reason:\s+Use cflinuxfs4 instead`)) + }) }) }) - }) }) - diff --git a/command/v7/v7fakes/fake_actor.go b/command/v7/v7fakes/fake_actor.go index e8f1915a932..595d351f4aa 100644 --- a/command/v7/v7fakes/fake_actor.go +++ b/command/v7/v7fakes/fake_actor.go @@ -22,6 +22,22 @@ import ( ) type FakeActor struct { + AddRoutePolicyStub func(string, string, string, string) (v7action.Warnings, error) + addRoutePolicyMutex sync.RWMutex + addRoutePolicyArgsForCall []struct { + arg1 string + arg2 string + arg3 string + arg4 string + } + addRoutePolicyReturns struct { + result1 v7action.Warnings + result2 error + } + addRoutePolicyReturnsOnCall map[int]struct { + result1 v7action.Warnings + result2 error + } ApplyOrganizationQuotaByNameStub func(string, string) (v7action.Warnings, error) applyOrganizationQuotaByNameMutex sync.RWMutex applyOrganizationQuotaByNameArgsForCall []struct { @@ -357,11 +373,13 @@ type FakeActor struct { result1 v7action.Warnings result2 error } - CreatePrivateDomainStub func(string, string) (v7action.Warnings, error) + CreatePrivateDomainStub func(string, string, bool, string) (v7action.Warnings, error) createPrivateDomainMutex sync.RWMutex createPrivateDomainArgsForCall []struct { arg1 string arg2 string + arg3 bool + arg4 string } createPrivateDomainReturns struct { result1 v7action.Warnings @@ -463,12 +481,14 @@ type FakeActor struct { result2 v7action.Warnings result3 error } - CreateSharedDomainStub func(string, bool, string) (v7action.Warnings, error) + CreateSharedDomainStub func(string, bool, string, bool, string) (v7action.Warnings, error) createSharedDomainMutex sync.RWMutex createSharedDomainArgsForCall []struct { arg1 string arg2 bool arg3 string + arg4 bool + arg5 string } createSharedDomainReturns struct { result1 v7action.Warnings @@ -730,6 +750,22 @@ type FakeActor struct { result2 v7action.Warnings result3 error } + DeleteRoutePolicyBySourceStub func(string, string, string, string) (v7action.Warnings, error) + deleteRoutePolicyBySourceMutex sync.RWMutex + deleteRoutePolicyBySourceArgsForCall []struct { + arg1 string + arg2 string + arg3 string + arg4 string + } + deleteRoutePolicyBySourceReturns struct { + result1 v7action.Warnings + result2 error + } + deleteRoutePolicyBySourceReturnsOnCall map[int]struct { + result1 v7action.Warnings + result2 error + } DeleteSecurityGroupStub func(string) (v7action.Warnings, error) deleteSecurityGroupMutex sync.RWMutex deleteSecurityGroupArgsForCall []struct { @@ -1863,6 +1899,42 @@ type FakeActor struct { result2 v7action.Warnings result3 error } + GetRoutePoliciesByRouteStub func(string, string, string) ([]resources.RoutePolicy, v7action.Warnings, error) + getRoutePoliciesByRouteMutex sync.RWMutex + getRoutePoliciesByRouteArgsForCall []struct { + arg1 string + arg2 string + arg3 string + } + getRoutePoliciesByRouteReturns struct { + result1 []resources.RoutePolicy + result2 v7action.Warnings + result3 error + } + getRoutePoliciesByRouteReturnsOnCall map[int]struct { + result1 []resources.RoutePolicy + result2 v7action.Warnings + result3 error + } + GetRoutePoliciesForSpaceStub func(string, string, string, string, string) ([]v7action.RoutePolicyWithRoute, v7action.Warnings, error) + getRoutePoliciesForSpaceMutex sync.RWMutex + getRoutePoliciesForSpaceArgsForCall []struct { + arg1 string + arg2 string + arg3 string + arg4 string + arg5 string + } + getRoutePoliciesForSpaceReturns struct { + result1 []v7action.RoutePolicyWithRoute + result2 v7action.Warnings + result3 error + } + getRoutePoliciesForSpaceReturnsOnCall map[int]struct { + result1 []v7action.RoutePolicyWithRoute + result2 v7action.Warnings + result3 error + } GetRouteSummariesStub func([]resources.Route) ([]v7action.RouteSummary, v7action.Warnings, error) getRouteSummariesMutex sync.RWMutex getRouteSummariesArgsForCall []struct { @@ -3780,6 +3852,73 @@ type FakeActor struct { invocationsMutex sync.RWMutex } +func (fake *FakeActor) AddRoutePolicy(arg1 string, arg2 string, arg3 string, arg4 string) (v7action.Warnings, error) { + fake.addRoutePolicyMutex.Lock() + ret, specificReturn := fake.addRoutePolicyReturnsOnCall[len(fake.addRoutePolicyArgsForCall)] + fake.addRoutePolicyArgsForCall = append(fake.addRoutePolicyArgsForCall, struct { + arg1 string + arg2 string + arg3 string + arg4 string + }{arg1, arg2, arg3, arg4}) + stub := fake.AddRoutePolicyStub + fakeReturns := fake.addRoutePolicyReturns + fake.recordInvocation("AddRoutePolicy", []interface{}{arg1, arg2, arg3, arg4}) + fake.addRoutePolicyMutex.Unlock() + if stub != nil { + return stub(arg1, arg2, arg3, arg4) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *FakeActor) AddRoutePolicyCallCount() int { + fake.addRoutePolicyMutex.RLock() + defer fake.addRoutePolicyMutex.RUnlock() + return len(fake.addRoutePolicyArgsForCall) +} + +func (fake *FakeActor) AddRoutePolicyCalls(stub func(string, string, string, string) (v7action.Warnings, error)) { + fake.addRoutePolicyMutex.Lock() + defer fake.addRoutePolicyMutex.Unlock() + fake.AddRoutePolicyStub = stub +} + +func (fake *FakeActor) AddRoutePolicyArgsForCall(i int) (string, string, string, string) { + fake.addRoutePolicyMutex.RLock() + defer fake.addRoutePolicyMutex.RUnlock() + argsForCall := fake.addRoutePolicyArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4 +} + +func (fake *FakeActor) AddRoutePolicyReturns(result1 v7action.Warnings, result2 error) { + fake.addRoutePolicyMutex.Lock() + defer fake.addRoutePolicyMutex.Unlock() + fake.AddRoutePolicyStub = nil + fake.addRoutePolicyReturns = struct { + result1 v7action.Warnings + result2 error + }{result1, result2} +} + +func (fake *FakeActor) AddRoutePolicyReturnsOnCall(i int, result1 v7action.Warnings, result2 error) { + fake.addRoutePolicyMutex.Lock() + defer fake.addRoutePolicyMutex.Unlock() + fake.AddRoutePolicyStub = nil + if fake.addRoutePolicyReturnsOnCall == nil { + fake.addRoutePolicyReturnsOnCall = make(map[int]struct { + result1 v7action.Warnings + result2 error + }) + } + fake.addRoutePolicyReturnsOnCall[i] = struct { + result1 v7action.Warnings + result2 error + }{result1, result2} +} + func (fake *FakeActor) ApplyOrganizationQuotaByName(arg1 string, arg2 string) (v7action.Warnings, error) { fake.applyOrganizationQuotaByNameMutex.Lock() ret, specificReturn := fake.applyOrganizationQuotaByNameReturnsOnCall[len(fake.applyOrganizationQuotaByNameArgsForCall)] @@ -5273,19 +5412,21 @@ func (fake *FakeActor) CreateOrganizationQuotaReturnsOnCall(i int, result1 v7act }{result1, result2} } -func (fake *FakeActor) CreatePrivateDomain(arg1 string, arg2 string) (v7action.Warnings, error) { +func (fake *FakeActor) CreatePrivateDomain(arg1 string, arg2 string, arg3 bool, arg4 string) (v7action.Warnings, error) { fake.createPrivateDomainMutex.Lock() ret, specificReturn := fake.createPrivateDomainReturnsOnCall[len(fake.createPrivateDomainArgsForCall)] fake.createPrivateDomainArgsForCall = append(fake.createPrivateDomainArgsForCall, struct { arg1 string arg2 string - }{arg1, arg2}) + arg3 bool + arg4 string + }{arg1, arg2, arg3, arg4}) stub := fake.CreatePrivateDomainStub fakeReturns := fake.createPrivateDomainReturns - fake.recordInvocation("CreatePrivateDomain", []interface{}{arg1, arg2}) + fake.recordInvocation("CreatePrivateDomain", []interface{}{arg1, arg2, arg3, arg4}) fake.createPrivateDomainMutex.Unlock() if stub != nil { - return stub(arg1, arg2) + return stub(arg1, arg2, arg3, arg4) } if specificReturn { return ret.result1, ret.result2 @@ -5299,17 +5440,17 @@ func (fake *FakeActor) CreatePrivateDomainCallCount() int { return len(fake.createPrivateDomainArgsForCall) } -func (fake *FakeActor) CreatePrivateDomainCalls(stub func(string, string) (v7action.Warnings, error)) { +func (fake *FakeActor) CreatePrivateDomainCalls(stub func(string, string, bool, string) (v7action.Warnings, error)) { fake.createPrivateDomainMutex.Lock() defer fake.createPrivateDomainMutex.Unlock() fake.CreatePrivateDomainStub = stub } -func (fake *FakeActor) CreatePrivateDomainArgsForCall(i int) (string, string) { +func (fake *FakeActor) CreatePrivateDomainArgsForCall(i int) (string, string, bool, string) { fake.createPrivateDomainMutex.RLock() defer fake.createPrivateDomainMutex.RUnlock() argsForCall := fake.createPrivateDomainArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2 + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4 } func (fake *FakeActor) CreatePrivateDomainReturns(result1 v7action.Warnings, result2 error) { @@ -5740,20 +5881,22 @@ func (fake *FakeActor) CreateServiceKeyReturnsOnCall(i int, result1 chan v7actio }{result1, result2, result3} } -func (fake *FakeActor) CreateSharedDomain(arg1 string, arg2 bool, arg3 string) (v7action.Warnings, error) { +func (fake *FakeActor) CreateSharedDomain(arg1 string, arg2 bool, arg3 string, arg4 bool, arg5 string) (v7action.Warnings, error) { fake.createSharedDomainMutex.Lock() ret, specificReturn := fake.createSharedDomainReturnsOnCall[len(fake.createSharedDomainArgsForCall)] fake.createSharedDomainArgsForCall = append(fake.createSharedDomainArgsForCall, struct { arg1 string arg2 bool arg3 string - }{arg1, arg2, arg3}) + arg4 bool + arg5 string + }{arg1, arg2, arg3, arg4, arg5}) stub := fake.CreateSharedDomainStub fakeReturns := fake.createSharedDomainReturns - fake.recordInvocation("CreateSharedDomain", []interface{}{arg1, arg2, arg3}) + fake.recordInvocation("CreateSharedDomain", []interface{}{arg1, arg2, arg3, arg4, arg5}) fake.createSharedDomainMutex.Unlock() if stub != nil { - return stub(arg1, arg2, arg3) + return stub(arg1, arg2, arg3, arg4, arg5) } if specificReturn { return ret.result1, ret.result2 @@ -5767,17 +5910,17 @@ func (fake *FakeActor) CreateSharedDomainCallCount() int { return len(fake.createSharedDomainArgsForCall) } -func (fake *FakeActor) CreateSharedDomainCalls(stub func(string, bool, string) (v7action.Warnings, error)) { +func (fake *FakeActor) CreateSharedDomainCalls(stub func(string, bool, string, bool, string) (v7action.Warnings, error)) { fake.createSharedDomainMutex.Lock() defer fake.createSharedDomainMutex.Unlock() fake.CreateSharedDomainStub = stub } -func (fake *FakeActor) CreateSharedDomainArgsForCall(i int) (string, bool, string) { +func (fake *FakeActor) CreateSharedDomainArgsForCall(i int) (string, bool, string, bool, string) { fake.createSharedDomainMutex.RLock() defer fake.createSharedDomainMutex.RUnlock() argsForCall := fake.createSharedDomainArgsForCall[i] - return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3 + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4, argsForCall.arg5 } func (fake *FakeActor) CreateSharedDomainReturns(result1 v7action.Warnings, result2 error) { @@ -6928,6 +7071,73 @@ func (fake *FakeActor) DeleteRouteBindingReturnsOnCall(i int, result1 chan v7act }{result1, result2, result3} } +func (fake *FakeActor) DeleteRoutePolicyBySource(arg1 string, arg2 string, arg3 string, arg4 string) (v7action.Warnings, error) { + fake.deleteRoutePolicyBySourceMutex.Lock() + ret, specificReturn := fake.deleteRoutePolicyBySourceReturnsOnCall[len(fake.deleteRoutePolicyBySourceArgsForCall)] + fake.deleteRoutePolicyBySourceArgsForCall = append(fake.deleteRoutePolicyBySourceArgsForCall, struct { + arg1 string + arg2 string + arg3 string + arg4 string + }{arg1, arg2, arg3, arg4}) + stub := fake.DeleteRoutePolicyBySourceStub + fakeReturns := fake.deleteRoutePolicyBySourceReturns + fake.recordInvocation("DeleteRoutePolicyBySource", []interface{}{arg1, arg2, arg3, arg4}) + fake.deleteRoutePolicyBySourceMutex.Unlock() + if stub != nil { + return stub(arg1, arg2, arg3, arg4) + } + if specificReturn { + return ret.result1, ret.result2 + } + return fakeReturns.result1, fakeReturns.result2 +} + +func (fake *FakeActor) DeleteRoutePolicyBySourceCallCount() int { + fake.deleteRoutePolicyBySourceMutex.RLock() + defer fake.deleteRoutePolicyBySourceMutex.RUnlock() + return len(fake.deleteRoutePolicyBySourceArgsForCall) +} + +func (fake *FakeActor) DeleteRoutePolicyBySourceCalls(stub func(string, string, string, string) (v7action.Warnings, error)) { + fake.deleteRoutePolicyBySourceMutex.Lock() + defer fake.deleteRoutePolicyBySourceMutex.Unlock() + fake.DeleteRoutePolicyBySourceStub = stub +} + +func (fake *FakeActor) DeleteRoutePolicyBySourceArgsForCall(i int) (string, string, string, string) { + fake.deleteRoutePolicyBySourceMutex.RLock() + defer fake.deleteRoutePolicyBySourceMutex.RUnlock() + argsForCall := fake.deleteRoutePolicyBySourceArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4 +} + +func (fake *FakeActor) DeleteRoutePolicyBySourceReturns(result1 v7action.Warnings, result2 error) { + fake.deleteRoutePolicyBySourceMutex.Lock() + defer fake.deleteRoutePolicyBySourceMutex.Unlock() + fake.DeleteRoutePolicyBySourceStub = nil + fake.deleteRoutePolicyBySourceReturns = struct { + result1 v7action.Warnings + result2 error + }{result1, result2} +} + +func (fake *FakeActor) DeleteRoutePolicyBySourceReturnsOnCall(i int, result1 v7action.Warnings, result2 error) { + fake.deleteRoutePolicyBySourceMutex.Lock() + defer fake.deleteRoutePolicyBySourceMutex.Unlock() + fake.DeleteRoutePolicyBySourceStub = nil + if fake.deleteRoutePolicyBySourceReturnsOnCall == nil { + fake.deleteRoutePolicyBySourceReturnsOnCall = make(map[int]struct { + result1 v7action.Warnings + result2 error + }) + } + fake.deleteRoutePolicyBySourceReturnsOnCall[i] = struct { + result1 v7action.Warnings + result2 error + }{result1, result2} +} + func (fake *FakeActor) DeleteSecurityGroup(arg1 string) (v7action.Warnings, error) { fake.deleteSecurityGroupMutex.Lock() ret, specificReturn := fake.deleteSecurityGroupReturnsOnCall[len(fake.deleteSecurityGroupArgsForCall)] @@ -11851,6 +12061,146 @@ func (fake *FakeActor) GetRouteLabelsReturnsOnCall(i int, result1 map[string]typ }{result1, result2, result3} } +func (fake *FakeActor) GetRoutePoliciesByRoute(arg1 string, arg2 string, arg3 string) ([]resources.RoutePolicy, v7action.Warnings, error) { + fake.getRoutePoliciesByRouteMutex.Lock() + ret, specificReturn := fake.getRoutePoliciesByRouteReturnsOnCall[len(fake.getRoutePoliciesByRouteArgsForCall)] + fake.getRoutePoliciesByRouteArgsForCall = append(fake.getRoutePoliciesByRouteArgsForCall, struct { + arg1 string + arg2 string + arg3 string + }{arg1, arg2, arg3}) + stub := fake.GetRoutePoliciesByRouteStub + fakeReturns := fake.getRoutePoliciesByRouteReturns + fake.recordInvocation("GetRoutePoliciesByRoute", []interface{}{arg1, arg2, arg3}) + fake.getRoutePoliciesByRouteMutex.Unlock() + if stub != nil { + return stub(arg1, arg2, arg3) + } + if specificReturn { + return ret.result1, ret.result2, ret.result3 + } + return fakeReturns.result1, fakeReturns.result2, fakeReturns.result3 +} + +func (fake *FakeActor) GetRoutePoliciesByRouteCallCount() int { + fake.getRoutePoliciesByRouteMutex.RLock() + defer fake.getRoutePoliciesByRouteMutex.RUnlock() + return len(fake.getRoutePoliciesByRouteArgsForCall) +} + +func (fake *FakeActor) GetRoutePoliciesByRouteCalls(stub func(string, string, string) ([]resources.RoutePolicy, v7action.Warnings, error)) { + fake.getRoutePoliciesByRouteMutex.Lock() + defer fake.getRoutePoliciesByRouteMutex.Unlock() + fake.GetRoutePoliciesByRouteStub = stub +} + +func (fake *FakeActor) GetRoutePoliciesByRouteArgsForCall(i int) (string, string, string) { + fake.getRoutePoliciesByRouteMutex.RLock() + defer fake.getRoutePoliciesByRouteMutex.RUnlock() + argsForCall := fake.getRoutePoliciesByRouteArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3 +} + +func (fake *FakeActor) GetRoutePoliciesByRouteReturns(result1 []resources.RoutePolicy, result2 v7action.Warnings, result3 error) { + fake.getRoutePoliciesByRouteMutex.Lock() + defer fake.getRoutePoliciesByRouteMutex.Unlock() + fake.GetRoutePoliciesByRouteStub = nil + fake.getRoutePoliciesByRouteReturns = struct { + result1 []resources.RoutePolicy + result2 v7action.Warnings + result3 error + }{result1, result2, result3} +} + +func (fake *FakeActor) GetRoutePoliciesByRouteReturnsOnCall(i int, result1 []resources.RoutePolicy, result2 v7action.Warnings, result3 error) { + fake.getRoutePoliciesByRouteMutex.Lock() + defer fake.getRoutePoliciesByRouteMutex.Unlock() + fake.GetRoutePoliciesByRouteStub = nil + if fake.getRoutePoliciesByRouteReturnsOnCall == nil { + fake.getRoutePoliciesByRouteReturnsOnCall = make(map[int]struct { + result1 []resources.RoutePolicy + result2 v7action.Warnings + result3 error + }) + } + fake.getRoutePoliciesByRouteReturnsOnCall[i] = struct { + result1 []resources.RoutePolicy + result2 v7action.Warnings + result3 error + }{result1, result2, result3} +} + +func (fake *FakeActor) GetRoutePoliciesForSpace(arg1 string, arg2 string, arg3 string, arg4 string, arg5 string) ([]v7action.RoutePolicyWithRoute, v7action.Warnings, error) { + fake.getRoutePoliciesForSpaceMutex.Lock() + ret, specificReturn := fake.getRoutePoliciesForSpaceReturnsOnCall[len(fake.getRoutePoliciesForSpaceArgsForCall)] + fake.getRoutePoliciesForSpaceArgsForCall = append(fake.getRoutePoliciesForSpaceArgsForCall, struct { + arg1 string + arg2 string + arg3 string + arg4 string + arg5 string + }{arg1, arg2, arg3, arg4, arg5}) + stub := fake.GetRoutePoliciesForSpaceStub + fakeReturns := fake.getRoutePoliciesForSpaceReturns + fake.recordInvocation("GetRoutePoliciesForSpace", []interface{}{arg1, arg2, arg3, arg4, arg5}) + fake.getRoutePoliciesForSpaceMutex.Unlock() + if stub != nil { + return stub(arg1, arg2, arg3, arg4, arg5) + } + if specificReturn { + return ret.result1, ret.result2, ret.result3 + } + return fakeReturns.result1, fakeReturns.result2, fakeReturns.result3 +} + +func (fake *FakeActor) GetRoutePoliciesForSpaceCallCount() int { + fake.getRoutePoliciesForSpaceMutex.RLock() + defer fake.getRoutePoliciesForSpaceMutex.RUnlock() + return len(fake.getRoutePoliciesForSpaceArgsForCall) +} + +func (fake *FakeActor) GetRoutePoliciesForSpaceCalls(stub func(string, string, string, string, string) ([]v7action.RoutePolicyWithRoute, v7action.Warnings, error)) { + fake.getRoutePoliciesForSpaceMutex.Lock() + defer fake.getRoutePoliciesForSpaceMutex.Unlock() + fake.GetRoutePoliciesForSpaceStub = stub +} + +func (fake *FakeActor) GetRoutePoliciesForSpaceArgsForCall(i int) (string, string, string, string, string) { + fake.getRoutePoliciesForSpaceMutex.RLock() + defer fake.getRoutePoliciesForSpaceMutex.RUnlock() + argsForCall := fake.getRoutePoliciesForSpaceArgsForCall[i] + return argsForCall.arg1, argsForCall.arg2, argsForCall.arg3, argsForCall.arg4, argsForCall.arg5 +} + +func (fake *FakeActor) GetRoutePoliciesForSpaceReturns(result1 []v7action.RoutePolicyWithRoute, result2 v7action.Warnings, result3 error) { + fake.getRoutePoliciesForSpaceMutex.Lock() + defer fake.getRoutePoliciesForSpaceMutex.Unlock() + fake.GetRoutePoliciesForSpaceStub = nil + fake.getRoutePoliciesForSpaceReturns = struct { + result1 []v7action.RoutePolicyWithRoute + result2 v7action.Warnings + result3 error + }{result1, result2, result3} +} + +func (fake *FakeActor) GetRoutePoliciesForSpaceReturnsOnCall(i int, result1 []v7action.RoutePolicyWithRoute, result2 v7action.Warnings, result3 error) { + fake.getRoutePoliciesForSpaceMutex.Lock() + defer fake.getRoutePoliciesForSpaceMutex.Unlock() + fake.GetRoutePoliciesForSpaceStub = nil + if fake.getRoutePoliciesForSpaceReturnsOnCall == nil { + fake.getRoutePoliciesForSpaceReturnsOnCall = make(map[int]struct { + result1 []v7action.RoutePolicyWithRoute + result2 v7action.Warnings + result3 error + }) + } + fake.getRoutePoliciesForSpaceReturnsOnCall[i] = struct { + result1 []v7action.RoutePolicyWithRoute + result2 v7action.Warnings + result3 error + }{result1, result2, result3} +} + func (fake *FakeActor) GetRouteSummaries(arg1 []resources.Route) ([]v7action.RouteSummary, v7action.Warnings, error) { var arg1Copy []resources.Route if arg1 != nil { diff --git a/command/v7/v7fakes/fake_actor_reloader.go b/command/v7/v7fakes/fake_actor_reloader.go index 87876729587..2fd49dc658f 100644 --- a/command/v7/v7fakes/fake_actor_reloader.go +++ b/command/v7/v7fakes/fake_actor_reloader.go @@ -95,8 +95,6 @@ func (fake *FakeActorReloader) ReloadReturnsOnCall(i int, result1 v7.Actor, resu func (fake *FakeActorReloader) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.reloadMutex.RLock() - defer fake.reloadMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/command/v7/v7fakes/fake_diff_displayer.go b/command/v7/v7fakes/fake_diff_displayer.go index 8287b97c16d..9117049608a 100644 --- a/command/v7/v7fakes/fake_diff_displayer.go +++ b/command/v7/v7fakes/fake_diff_displayer.go @@ -95,8 +95,6 @@ func (fake *FakeDiffDisplayer) DisplayDiffReturnsOnCall(i int, result1 error) { func (fake *FakeDiffDisplayer) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.displayDiffMutex.RLock() - defer fake.displayDiffMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/command/v7/v7fakes/fake_label_setter.go b/command/v7/v7fakes/fake_label_setter.go index 36443f1b9bb..0acdb5434c5 100644 --- a/command/v7/v7fakes/fake_label_setter.go +++ b/command/v7/v7fakes/fake_label_setter.go @@ -90,8 +90,6 @@ func (fake *FakeLabelSetter) ExecuteReturnsOnCall(i int, result1 error) { func (fake *FakeLabelSetter) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.executeMutex.RLock() - defer fake.executeMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/command/v7/v7fakes/fake_label_unsetter.go b/command/v7/v7fakes/fake_label_unsetter.go index 48ec32fe771..554424cb19a 100644 --- a/command/v7/v7fakes/fake_label_unsetter.go +++ b/command/v7/v7fakes/fake_label_unsetter.go @@ -90,8 +90,6 @@ func (fake *FakeLabelUnsetter) ExecuteReturnsOnCall(i int, result1 error) { func (fake *FakeLabelUnsetter) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.executeMutex.RLock() - defer fake.executeMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/command/v7/v7fakes/fake_manifest_locator.go b/command/v7/v7fakes/fake_manifest_locator.go index 0e41343c30c..592132dfe0e 100644 --- a/command/v7/v7fakes/fake_manifest_locator.go +++ b/command/v7/v7fakes/fake_manifest_locator.go @@ -97,8 +97,6 @@ func (fake *FakeManifestLocator) PathReturnsOnCall(i int, result1 string, result func (fake *FakeManifestLocator) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.pathMutex.RLock() - defer fake.pathMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/command/v7/v7fakes/fake_manifest_parser.go b/command/v7/v7fakes/fake_manifest_parser.go index dff85521ea8..d571390ed17 100644 --- a/command/v7/v7fakes/fake_manifest_parser.go +++ b/command/v7/v7fakes/fake_manifest_parser.go @@ -269,12 +269,6 @@ func (fake *FakeManifestParser) ParseManifestReturnsOnCall(i int, result1 manife func (fake *FakeManifestParser) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.interpolateManifestMutex.RLock() - defer fake.interpolateManifestMutex.RUnlock() - fake.marshalManifestMutex.RLock() - defer fake.marshalManifestMutex.RUnlock() - fake.parseManifestMutex.RLock() - defer fake.parseManifestMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/command/v7/v7fakes/fake_network_policies_actor.go b/command/v7/v7fakes/fake_network_policies_actor.go index 8bcdf225bd5..91ee1014c2e 100644 --- a/command/v7/v7fakes/fake_network_policies_actor.go +++ b/command/v7/v7fakes/fake_network_policies_actor.go @@ -182,10 +182,6 @@ func (fake *FakeNetworkPoliciesActor) NetworkPoliciesBySpaceAndAppNameReturnsOnC func (fake *FakeNetworkPoliciesActor) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.networkPoliciesBySpaceMutex.RLock() - defer fake.networkPoliciesBySpaceMutex.RUnlock() - fake.networkPoliciesBySpaceAndAppNameMutex.RLock() - defer fake.networkPoliciesBySpaceAndAppNameMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/command/v7/v7fakes/fake_networking_actor.go b/command/v7/v7fakes/fake_networking_actor.go index 1ca88ae4370..7fb0f93c709 100644 --- a/command/v7/v7fakes/fake_networking_actor.go +++ b/command/v7/v7fakes/fake_networking_actor.go @@ -105,8 +105,6 @@ func (fake *FakeNetworkingActor) AddNetworkPolicyReturnsOnCall(i int, result1 cf func (fake *FakeNetworkingActor) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.addNetworkPolicyMutex.RLock() - defer fake.addNetworkPolicyMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/command/v7/v7fakes/fake_progress_bar.go b/command/v7/v7fakes/fake_progress_bar.go index 53118843760..6a6c8a7b163 100644 --- a/command/v7/v7fakes/fake_progress_bar.go +++ b/command/v7/v7fakes/fake_progress_bar.go @@ -146,12 +146,6 @@ func (fake *FakeProgressBar) ReadyCalls(stub func()) { func (fake *FakeProgressBar) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.completeMutex.RLock() - defer fake.completeMutex.RUnlock() - fake.newProgressBarWrapperMutex.RLock() - defer fake.newProgressBarWrapperMutex.RUnlock() - fake.readyMutex.RLock() - defer fake.readyMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/command/v7/v7fakes/fake_push_actor.go b/command/v7/v7fakes/fake_push_actor.go index 74c6db82946..8517b124f1b 100644 --- a/command/v7/v7fakes/fake_push_actor.go +++ b/command/v7/v7fakes/fake_push_actor.go @@ -338,14 +338,6 @@ func (fake *FakePushActor) HandleFlagOverridesReturnsOnCall(i int, result1 manif func (fake *FakePushActor) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.actualizeMutex.RLock() - defer fake.actualizeMutex.RUnlock() - fake.createPushPlansMutex.RLock() - defer fake.createPushPlansMutex.RUnlock() - fake.handleDeploymentScaleFlagOverridesMutex.RLock() - defer fake.handleDeploymentScaleFlagOverridesMutex.RUnlock() - fake.handleFlagOverridesMutex.RLock() - defer fake.handleFlagOverridesMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/command/v7/v7fakes/fake_remove_network_policy_actor.go b/command/v7/v7fakes/fake_remove_network_policy_actor.go index 9c3a4d61aa8..390bf258738 100644 --- a/command/v7/v7fakes/fake_remove_network_policy_actor.go +++ b/command/v7/v7fakes/fake_remove_network_policy_actor.go @@ -105,8 +105,6 @@ func (fake *FakeRemoveNetworkPolicyActor) RemoveNetworkPolicyReturnsOnCall(i int func (fake *FakeRemoveNetworkPolicyActor) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.removeNetworkPolicyMutex.RLock() - defer fake.removeNetworkPolicyMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/command/v7/v7fakes/fake_revisions_actor.go b/command/v7/v7fakes/fake_revisions_actor.go index e126f4ea24b..50186a8febd 100644 --- a/command/v7/v7fakes/fake_revisions_actor.go +++ b/command/v7/v7fakes/fake_revisions_actor.go @@ -101,8 +101,6 @@ func (fake *FakeRevisionsActor) GetRevisionsByApplicationNameAndSpaceReturnsOnCa func (fake *FakeRevisionsActor) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.getRevisionsByApplicationNameAndSpaceMutex.RLock() - defer fake.getRevisionsByApplicationNameAndSpaceMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/command/v7/v7fakes/fake_set_label_actor.go b/command/v7/v7fakes/fake_set_label_actor.go index 5cbb7852e91..113aa2be611 100644 --- a/command/v7/v7fakes/fake_set_label_actor.go +++ b/command/v7/v7fakes/fake_set_label_actor.go @@ -318,16 +318,16 @@ func (fake *FakeSetLabelActor) UpdateBuildpackLabelsByBuildpackNameAndStackAndLi fake.updateBuildpackLabelsByBuildpackNameAndStackAndLifecycleArgsForCall = append(fake.updateBuildpackLabelsByBuildpackNameAndStackAndLifecycleArgsForCall, struct { arg1 string arg2 string - arg3 string - arg4 map[string]types.NullString - }{arg1, arg2, arg3, arg4}) - stub := fake.UpdateBuildpackLabelsByBuildpackNameAndStackAndLifecycleStub - fakeReturns := fake.updateBuildpackLabelsByBuildpackNameAndStackAndLifecycleReturns - fake.recordInvocation("UpdateBuildpackLabelsByBuildpackNameAndStackAndLifecycle", []interface{}{arg1, arg2, arg3, arg4}) - fake.updateBuildpackLabelsByBuildpackNameAndStackAndLifecycleMutex.Unlock() - if stub != nil { - return stub(arg1, arg2, arg3, arg4) - } + arg3 string + arg4 map[string]types.NullString + }{arg1, arg2, arg3, arg4}) + stub := fake.UpdateBuildpackLabelsByBuildpackNameAndStackAndLifecycleStub + fakeReturns := fake.updateBuildpackLabelsByBuildpackNameAndStackAndLifecycleReturns + fake.recordInvocation("UpdateBuildpackLabelsByBuildpackNameAndStackAndLifecycle", []interface{}{arg1, arg2, arg3, arg4}) + fake.updateBuildpackLabelsByBuildpackNameAndStackAndLifecycleMutex.Unlock() + if stub != nil { + return stub(arg1, arg2, arg3, arg4) + } if specificReturn { return ret.result1, ret.result2 } @@ -973,30 +973,6 @@ func (fake *FakeSetLabelActor) UpdateStackLabelsByStackNameReturnsOnCall(i int, func (fake *FakeSetLabelActor) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.getCurrentUserMutex.RLock() - defer fake.getCurrentUserMutex.RUnlock() - fake.updateApplicationLabelsByApplicationNameMutex.RLock() - defer fake.updateApplicationLabelsByApplicationNameMutex.RUnlock() - fake.updateBuildpackLabelsByBuildpackNameAndStackAndLifecycleMutex.RLock() - defer fake.updateBuildpackLabelsByBuildpackNameAndStackAndLifecycleMutex.RUnlock() - fake.updateDomainLabelsByDomainNameMutex.RLock() - defer fake.updateDomainLabelsByDomainNameMutex.RUnlock() - fake.updateOrganizationLabelsByOrganizationNameMutex.RLock() - defer fake.updateOrganizationLabelsByOrganizationNameMutex.RUnlock() - fake.updateRouteLabelsMutex.RLock() - defer fake.updateRouteLabelsMutex.RUnlock() - fake.updateServiceBrokerLabelsByServiceBrokerNameMutex.RLock() - defer fake.updateServiceBrokerLabelsByServiceBrokerNameMutex.RUnlock() - fake.updateServiceInstanceLabelsMutex.RLock() - defer fake.updateServiceInstanceLabelsMutex.RUnlock() - fake.updateServiceOfferingLabelsMutex.RLock() - defer fake.updateServiceOfferingLabelsMutex.RUnlock() - fake.updateServicePlanLabelsMutex.RLock() - defer fake.updateServicePlanLabelsMutex.RUnlock() - fake.updateSpaceLabelsBySpaceNameMutex.RLock() - defer fake.updateSpaceLabelsBySpaceNameMutex.RUnlock() - fake.updateStackLabelsByStackNameMutex.RLock() - defer fake.updateStackLabelsByStackNameMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/command/v7/v7fakes/fake_shared_sshactor.go b/command/v7/v7fakes/fake_shared_sshactor.go index a7756d048bc..b30b6111543 100644 --- a/command/v7/v7fakes/fake_shared_sshactor.go +++ b/command/v7/v7fakes/fake_shared_sshactor.go @@ -90,8 +90,6 @@ func (fake *FakeSharedSSHActor) ExecuteSecureShellReturnsOnCall(i int, result1 e func (fake *FakeSharedSSHActor) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.executeSecureShellMutex.RLock() - defer fake.executeSecureShellMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/command/v7/v7fakes/fake_v7actor_for_push.go b/command/v7/v7fakes/fake_v7actor_for_push.go index 22407358123..0341fb15432 100644 --- a/command/v7/v7fakes/fake_v7actor_for_push.go +++ b/command/v7/v7fakes/fake_v7actor_for_push.go @@ -448,16 +448,6 @@ func (fake *FakeV7ActorForPush) SetSpaceManifestReturnsOnCall(i int, result1 v7a func (fake *FakeV7ActorForPush) Invocations() map[string][][]interface{} { fake.invocationsMutex.RLock() defer fake.invocationsMutex.RUnlock() - fake.getApplicationByNameAndSpaceMutex.RLock() - defer fake.getApplicationByNameAndSpaceMutex.RUnlock() - fake.getDetailedAppSummaryMutex.RLock() - defer fake.getDetailedAppSummaryMutex.RUnlock() - fake.getStreamingLogsForApplicationByNameAndSpaceMutex.RLock() - defer fake.getStreamingLogsForApplicationByNameAndSpaceMutex.RUnlock() - fake.restartApplicationMutex.RLock() - defer fake.restartApplicationMutex.RUnlock() - fake.setSpaceManifestMutex.RLock() - defer fake.setSpaceManifestMutex.RUnlock() copiedInvocations := map[string][][]interface{}{} for key, value := range fake.invocations { copiedInvocations[key] = value diff --git a/devbox.json b/devbox.json new file mode 100644 index 00000000000..211ce41b32c --- /dev/null +++ b/devbox.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://raw.githubusercontent.com/jetify-com/devbox/0.16.0/.schema/devbox.schema.json", + "packages": ["go@1.26.1"], + "shell": { + "init_hook": [ + "echo 'Welcome to devbox!' > /dev/null" + ], + "scripts": { + "test": [ + "echo \"Error: no test specified\" && exit 1" + ] + } + } +} diff --git a/devbox.lock b/devbox.lock new file mode 100644 index 00000000000..19ff081759c --- /dev/null +++ b/devbox.lock @@ -0,0 +1,57 @@ +{ + "lockfile_version": "1", + "packages": { + "github:NixOS/nixpkgs/nixpkgs-unstable": { + "last_modified": "2026-03-16T02:27:38Z", + "resolved": "github:NixOS/nixpkgs/f8573b9c935cfaa162dd62cc9e75ae2db86f85df?lastModified=1773628058&narHash=sha256-hpXH0z3K9xv0fHaje136KY872VT2T5uwxtezlAskQgY%3D" + }, + "go@1.26.1": { + "last_modified": "2026-03-21T07:29:51Z", + "resolved": "github:NixOS/nixpkgs/09061f748ee21f68a089cd5d91ec1859cd93d0be#go", + "source": "devbox-search", + "version": "1.26.1", + "systems": { + "aarch64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/kh43nhaz1qcpwws2xq805lrmwpmn9i3k-go-1.26.1", + "default": true + } + ], + "store_path": "/nix/store/kh43nhaz1qcpwws2xq805lrmwpmn9i3k-go-1.26.1" + }, + "aarch64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/rz1pqbm5z3zfby250i0djfmfzzj7khg9-go-1.26.1", + "default": true + } + ], + "store_path": "/nix/store/rz1pqbm5z3zfby250i0djfmfzzj7khg9-go-1.26.1" + }, + "x86_64-darwin": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/yv6jj27racylbfjw6a1cdr91ndxbgyf6-go-1.26.1", + "default": true + } + ], + "store_path": "/nix/store/yv6jj27racylbfjw6a1cdr91ndxbgyf6-go-1.26.1" + }, + "x86_64-linux": { + "outputs": [ + { + "name": "out", + "path": "/nix/store/ckcq2mj8zk0drhaaacy6mp9d924hnr4m-go-1.26.1", + "default": true + } + ], + "store_path": "/nix/store/ckcq2mj8zk0drhaaacy6mp9d924hnr4m-go-1.26.1" + } + } + } + } +} diff --git a/integration/v7/isolated/revision_command_test.go b/integration/v7/isolated/revision_command_test.go index 423eccddb48..8243d2d6e04 100644 --- a/integration/v7/isolated/revision_command_test.go +++ b/integration/v7/isolated/revision_command_test.go @@ -1,13 +1,13 @@ package isolated import ( - "bytes" - "encoding/json" - "fmt" - "os/exec" - "strings" + "bytes" + "encoding/json" + "fmt" + "os/exec" + "strings" - . "code.cloudfoundry.org/cli/v9/cf/util/testhelpers/matchers" + . "code.cloudfoundry.org/cli/v9/cf/util/testhelpers/matchers" "code.cloudfoundry.org/cli/v9/integration/helpers" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" diff --git a/integration/v7/isolated/update_stack_command_test.go b/integration/v7/isolated/update_stack_command_test.go index ed4cf7668b9..5af25b52a42 100644 --- a/integration/v7/isolated/update_stack_command_test.go +++ b/integration/v7/isolated/update_stack_command_test.go @@ -255,4 +255,3 @@ var _ = Describe("update-stack command", func() { }) }) }) - diff --git a/resources/deployment_resource.go b/resources/deployment_resource.go index 03fa7f9d5b6..b4410ad0548 100644 --- a/resources/deployment_resource.go +++ b/resources/deployment_resource.go @@ -5,7 +5,7 @@ import ( "code.cloudfoundry.org/cli/v9/api/cloudcontroller" "code.cloudfoundry.org/cli/v9/api/cloudcontroller/ccv3/constant" - "code.cloudfoundry.org/cli/v9/types" + "code.cloudfoundry.org/cli/v9/types" ) type Deployment struct { diff --git a/resources/domain_resource.go b/resources/domain_resource.go index 1a032a78b01..a1956561d1d 100644 --- a/resources/domain_resource.go +++ b/resources/domain_resource.go @@ -6,12 +6,14 @@ import ( ) type Domain struct { - GUID string `json:"guid,omitempty"` - Name string `json:"name"` - Internal types.NullBool `json:"internal,omitempty"` - OrganizationGUID string `jsonry:"relationships.organization.data.guid,omitempty"` - RouterGroup string `jsonry:"router_group.guid,omitempty"` - Protocols []string `jsonry:"supported_protocols,omitempty"` + GUID string `json:"guid,omitempty"` + Name string `json:"name"` + Internal types.NullBool `json:"internal,omitempty"` + OrganizationGUID string `jsonry:"relationships.organization.data.guid,omitempty"` + RouterGroup string `jsonry:"router_group.guid,omitempty"` + Protocols []string `jsonry:"supported_protocols,omitempty"` + EnforceRoutePolicies types.NullBool `json:"enforce_route_policies,omitempty"` + RoutePoliciesScope string `json:"route_policies_scope,omitempty"` // Metadata is used for custom tagging of API resources Metadata *Metadata `json:"metadata,omitempty"` @@ -19,25 +21,31 @@ type Domain struct { func (d Domain) MarshalJSON() ([]byte, error) { type domainWithBoolPointer struct { - GUID string `jsonry:"guid,omitempty"` - Name string `jsonry:"name"` - Internal *bool `jsonry:"internal,omitempty"` - OrganizationGUID string `jsonry:"relationships.organization.data.guid,omitempty"` - RouterGroup string `jsonry:"router_group.guid,omitempty"` - Protocols []string `jsonry:"supported_protocols,omitempty"` + GUID string `jsonry:"guid,omitempty"` + Name string `jsonry:"name"` + Internal *bool `jsonry:"internal,omitempty"` + OrganizationGUID string `jsonry:"relationships.organization.data.guid,omitempty"` + RouterGroup string `jsonry:"router_group.guid,omitempty"` + Protocols []string `jsonry:"supported_protocols,omitempty"` + EnforceRoutePolicies *bool `jsonry:"enforce_route_policies,omitempty"` + RoutePoliciesScope string `jsonry:"route_policies_scope,omitempty"` } clone := domainWithBoolPointer{ - GUID: d.GUID, - Name: d.Name, - OrganizationGUID: d.OrganizationGUID, - RouterGroup: d.RouterGroup, - Protocols: d.Protocols, + GUID: d.GUID, + Name: d.Name, + OrganizationGUID: d.OrganizationGUID, + RouterGroup: d.RouterGroup, + Protocols: d.Protocols, + RoutePoliciesScope: d.RoutePoliciesScope, } if d.Internal.IsSet { clone.Internal = &d.Internal.Value } + if d.EnforceRoutePolicies.IsSet { + clone.EnforceRoutePolicies = &d.EnforceRoutePolicies.Value + } return jsonry.Marshal(clone) } diff --git a/resources/process_resource.go b/resources/process_resource.go index 1d136266b17..0dd88719e02 100644 --- a/resources/process_resource.go +++ b/resources/process_resource.go @@ -134,9 +134,9 @@ type marshalProcess struct { DiskInMB json.Number `json:"disk_in_mb,omitempty"` LogRateLimitInBPS json.Number `json:"log_rate_limit_in_bytes_per_second,omitempty"` - HealthCheck *healthCheck `json:"health_check,omitempty"` - ReadinessHealthCheck *readinessHealthCheck `json:"readiness_health_check,omitempty"` - EmbeddedProcessInstances []EmbeddedProcessInstance `json:"process_instances,omitempty"` + HealthCheck *healthCheck `json:"health_check,omitempty"` + ReadinessHealthCheck *readinessHealthCheck `json:"readiness_health_check,omitempty"` + EmbeddedProcessInstances []EmbeddedProcessInstance `json:"process_instances,omitempty"` } func marshalCommand(p Process, ccProcess *marshalProcess) { diff --git a/resources/route_policy_resource.go b/resources/route_policy_resource.go new file mode 100644 index 00000000000..6701876b567 --- /dev/null +++ b/resources/route_policy_resource.go @@ -0,0 +1,79 @@ +package resources + +import ( + "encoding/json" + "time" + + "code.cloudfoundry.org/cli/v9/api/cloudcontroller" +) + +type RoutePolicy struct { + GUID string `json:"guid,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + Source string `json:"source"` + RouteGUID string `json:"-"` + + // Metadata is used for custom tagging of API resources + Metadata *Metadata `json:"metadata,omitempty"` +} + +func (r RoutePolicy) MarshalJSON() ([]byte, error) { + type alias struct { + GUID string `json:"guid,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + Source string `json:"source"` + Metadata *Metadata `json:"metadata,omitempty"` + + Relationships struct { + Route struct { + Data struct { + GUID string `json:"guid"` + } `json:"data"` + } `json:"route"` + } `json:"relationships"` + } + + var aliasData alias + aliasData.GUID = r.GUID + aliasData.CreatedAt = r.CreatedAt + aliasData.UpdatedAt = r.UpdatedAt + aliasData.Source = r.Source + aliasData.Metadata = r.Metadata + aliasData.Relationships.Route.Data.GUID = r.RouteGUID + + return json.Marshal(aliasData) +} + +func (r *RoutePolicy) UnmarshalJSON(data []byte) error { + var alias struct { + GUID string `json:"guid,omitempty"` + CreatedAt *time.Time `json:"created_at,omitempty"` + UpdatedAt *time.Time `json:"updated_at,omitempty"` + Source string `json:"source"` + Metadata *Metadata `json:"metadata,omitempty"` + + Relationships struct { + Route struct { + Data struct { + GUID string `json:"guid,omitempty"` + } `json:"data,omitempty"` + } `json:"route,omitempty"` + } `json:"relationships,omitempty"` + } + + err := cloudcontroller.DecodeJSON(data, &alias) + if err != nil { + return err + } + + r.GUID = alias.GUID + r.CreatedAt = alias.CreatedAt + r.UpdatedAt = alias.UpdatedAt + r.Source = alias.Source + r.RouteGUID = alias.Relationships.Route.Data.GUID + r.Metadata = alias.Metadata + + return nil +} diff --git a/resources/route_policy_resource_test.go b/resources/route_policy_resource_test.go new file mode 100644 index 00000000000..b742e78a893 --- /dev/null +++ b/resources/route_policy_resource_test.go @@ -0,0 +1,65 @@ +package resources_test + +import ( + "encoding/json" + "testing" + + "code.cloudfoundry.org/cli/v9/resources" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestRoutePolicyResource(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "RoutePolicy Resource Suite") +} + +var _ = Describe("RoutePolicy", func() { + Describe("MarshalJSON", func() { + It("marshals the route policy with relationships", func() { + policy := resources.RoutePolicy{ + Source: "cf:app:some-app-guid", + RouteGUID: "some-route-guid", + } + + data, err := json.Marshal(policy) + Expect(err).NotTo(HaveOccurred()) + + var result map[string]interface{} + err = json.Unmarshal(data, &result) + Expect(err).NotTo(HaveOccurred()) + + Expect(result["source"]).To(Equal("cf:app:some-app-guid")) + Expect(result["relationships"]).NotTo(BeNil()) + + relationships := result["relationships"].(map[string]interface{}) + route := relationships["route"].(map[string]interface{}) + routeData := route["data"].(map[string]interface{}) + Expect(routeData["guid"]).To(Equal("some-route-guid")) + }) + }) + + Describe("UnmarshalJSON", func() { + It("unmarshals the route policy from relationships", func() { + jsonData := `{ + "guid": "some-guid", + "source": "cf:app:app-guid", + "relationships": { + "route": { + "data": { + "guid": "route-guid-123" + } + } + } + }` + + var policy resources.RoutePolicy + err := json.Unmarshal([]byte(jsonData), &policy) + Expect(err).NotTo(HaveOccurred()) + + Expect(policy.GUID).To(Equal("some-guid")) + Expect(policy.Source).To(Equal("cf:app:app-guid")) + Expect(policy.RouteGUID).To(Equal("route-guid-123")) + }) + }) +})