Skip to content

Commit 178a2ce

Browse files
rkosteranujc25
andauthored
RFC0055 Identity-Aware Routing (#3758)
* Enhance add-access-rule command UX with intuitive name-based flags This commit improves the user experience for the add-access-rule command by replacing the positional GUID-based SELECTOR argument with intuitive flags that accept human-readable names and support cross-space/org resolution. Changes: **Command Interface:** - Remove positional SELECTOR argument (breaking change, acceptable for unreleased feature) - Add new flags: --source-app, --source-space, --source-org, --source-any, --selector - Support hierarchical name resolution: - --source-app APP_NAME (looks in current space) - --source-app APP_NAME --source-space SPACE (cross-space in current org) - --source-app APP_NAME --source-space SPACE --source-org ORG (cross-org) - --source-space SPACE (space-level rule) - --source-org ORG (org-level rule) - --source-any (allow any authenticated app) - --selector SELECTOR (raw GUID-based selector for advanced users) - Validate exactly one primary source is specified - Display verbose output showing resolved selector for transparency **Terminology Update:** - Rename all "target" terminology to "source" throughout codebase - Access rules specify the source (who can access), not the target - Update AccessRuleWithRoute.TargetName → SourceName - Update resolveAccessRuleTarget() → resolveAccessRuleSource() - Update access-rules list command table header: "target" → "source" **Error Handling:** - Provide helpful error messages when app not found in current space - Suggest using --source-space and --source-org flags for cross-space/org access - Follow CF CLI patterns from add-network-policy command **Testing:** - Add 17 comprehensive test cases for add-access-rule command - Update 19 actor tests to use new SourceName field - All tests passing (36/36) **Domain Integration:** - Add enforce_access_rules support to create-shared-domain and create-private-domain - Add --enforce-access-rules and --access-rules-scope flags - Update domain resource with new fields Examples: # Simple case - app in current space cf add-access-rule allow-frontend apps.identity --source-app frontend-app --hostname backend # Cross-space access cf add-access-rule allow-other apps.identity --source-app api-client --source-space other-space --hostname backend # Cross-org access cf add-access-rule allow-prod apps.identity --source-app client --source-space prod-space --source-org prod-org --hostname api # Space-level rule cf add-access-rule allow-monitoring apps.identity --source-space monitoring --hostname api # Org-level rule cf add-access-rule allow-platform apps.identity --source-org platform --hostname shared-api # Any authenticated app cf add-access-rule allow-all apps.identity --source-any --hostname public-api Related to: cloudfoundry/community#1438 * Remove access rule names per RFC updates Per RFC commits 882b69a and 11752f2, access rules no longer have user-provided names. They are identified by their selector only, with labels/annotations used for metadata instead. Changes: - Removed RULE_NAME argument from add-access-rule command - Removed Name field from AccessRule API resource - Updated access-rules list to show 4 columns (route, selector, scope, source) - SourceName now represents resolved app/space/org name from selector - Updated remove-access-rule to use --selector flag instead of rule name - Renamed DeleteAccessRule() to DeleteAccessRuleBySelector() - Updated all tests to remove Name field references All tests passing. * Refine access-rules output to show separate host, domain, and path columns Changed table format from: route selector scope source backend.apps.identity ... app frontend-app To: host domain path selector scope source backend apps.identity ... app frontend-app api apps.identity /metrics ... space monitoring This provides better clarity by separating the route components into individual columns, making it easier to scan and filter visually. * Rebrand RFC terminology: access rules → route policies, selector → source Complete terminology shift for identity-aware routing RFC implementation: **Access Rules → Route Policies** - API: /v3/access_rules → /v3/route_policies - CLI commands: - cf access-rules → cf route-policies - cf add-access-rule → cf add-route-policy - cf remove-access-rule → cf remove-route-policy - Domain flags: --enforce-access-rules → --enforce-route-policies - Domain fields: enforce_access_rules → enforce_route_policies, access_rules_scope → route_policies_scope **Selector → Source** - API field: "selector" → "source" - CLI flag: --selector → --source - Query params: selectors → sources, selector_resource_guids → source_guids - Table column headers: "selector/source" → "source/name" - Internal types: AccessRule → RoutePolicy, AccessRuleWithRoute → RoutePolicyWithRoute - Error types: AccessRuleNotFoundError → RoutePolicyNotFoundError **Rationale (per RFC)** - "Route policies" aligns with existing CF "network policies" terminology - "Source" matches C2C network policy convention (source → destination) - Improves clarity: policies define allowed sources that can reach routes - Better mental model for users familiar with CF networking concepts This is a breaking change but acceptable since RFC is pre-GA with only POC/lab implementations. Clean terminology is preferred over backward compatibility at this stage. Co-authored-by: RFC Community <cloudfoundry/community#1438> Aligns-with: cloudfoundry/community@be8d74c1 * Add name-based source flags to remove-route-policy Extract source resolution flags (--source-app, --source-space, --source-org, --source-any, --source) into a shared RoutePolicySourceFlags struct embedded in both add-route-policy and remove-route-policy commands. Previously remove-route-policy only accepted --source with a raw GUID-format value (cf:app:<guid>, etc.), while add-route-policy supported name-based resolution. The two commands now have matching flag sets. * Add CAPI version check for route policy commands Guard add-route-policy, remove-route-policy, and route-policies with an unconditional MinimumCCAPIVersionCheck against MinVersionRoutePolicies. Guard create-shared-domain and create-private-domain conditionally when --enforce-route-policies is passed. MinVersionRoutePolicies is currently a placeholder (3.999.0); a failing test in ccversion/minimum_version_test.go keeps the TODO visible until the real CAPI version is confirmed and the constant is updated. * Add route policies column to cf domains output Show a single 'route policies' column when the CAPI version supports it. The column is blank for plain domains, 'enforced' when enforcement is on with no scope, and 'enforced (org/space/any)' when a scope is set. The column is gated on MinVersionRoutePolicies so it silently disappears on older CAPI targets — no hard error, cf domains still works everywhere. * Add cf/cli to .gitignore to prevent binary commits * Add unit tests for route policy commands, actor, and ccv3 client * Fix: reject --source-org with --source-app when --source-space is missing When a user specifies --source-org with --source-app but omits --source-space, validateSourceFlags() previously passed (treating --source-app as the sole primary flag), and resolveSource() silently ignored --source-org, resolving the app in the currently targeted space. Add a pre-check in validateSourceFlags() that returns RequiredFlagsError (--source-org and --source-space must be used together) whenever --source-org is combined with --source-app but --source-space is absent. * test: add scope/enforce coverage for CreatePrivateDomain in domain_test.go Refactor CreatePrivateDomain describe block to use JustBeforeEach pattern and add Context block for enforceAccessRules=true with non-empty scope, mirroring the existing coverage in CreateSharedDomain. * refactor: consolidate Add/RemoveRoutePolicyArgs into single RoutePolicyArgs Three identical one-field structs replaced with a single shared type. Description aligned with the existing convention in arguments.go. * test: add dedicated tests for route_policy_source_flags and create-private-domain new flags - route_policy_source_flags_test.go: covers all validateSourceFlags branches (no flags, single flags, qualifier combinations, RequiredFlagsError, ArgumentCombinationError) and all resolveSource paths (raw --source, --source-any, --source-app with/without cross-space/org, --source-space, --source-org, error propagation from each actor call) - create_private_domain_command_test.go: adds coverage for --scope without --enforce-route-policies, invalid --scope values, API version check failure, --enforce-route-policies success (identity-aware TIP), and --scope forwarding * test: add --enforce-route-policies and --scope coverage to create-shared-domain test Mirrors the coverage added to create_private_domain_command_test.go: - --scope without --enforce-route-policies returns an error - invalid --scope value returns an error - --enforce-route-policies with old API version returns MinimumCFAPIVersionNotMetError - --enforce-route-policies success: identity-aware TIP, enforce=true passed to actor - --enforce-route-policies + --scope: scope forwarded to actor - default path now explicitly asserts enforce=false, scope empty * refactor: extract shared --enforce-route-policies / --scope test behaviour Introduce EnforceRoutePoliciesBehavior and ItEnforcesRoutePolicies in enforce_route_policies_shared_test.go. Both create-shared-domain and create-private-domain tests now delegate the duplicate When blocks to the shared helper, parameterised only by TIPAdjective and the actor-specific arg-extraction closures. ccversion and translatableerror imports removed from both individual test files. * chore: remove devbox.json and devbox.lock from tracked files * Remove whitespace-only changes from unrelated files Bulk find-and-replace tooling from the rebrand commit introduced spaces→tabs indentation fixes and Invocations() mutex-lock removals in files completely unrelated to the route-policies feature. Restore all of them to origin/main to keep the feature diff focused. * fix: guard AddRoutePolicy against non-enforcing domains Add a client-side check in AddRoutePolicy that returns DomainNotEnforcingRoutePoliciesError if the domain does not have enforce_route_policies enabled, before attempting the API call. CAPI already enforces this server-side (route_policies_controller.rb:129), but the client-side guard provides a user-friendly error message with the domain name rather than a GUID-based 422 response. - Add actionerror.DomainNotEnforcingRoutePoliciesError - Guard in actor/v7action/route_policy.go after domain fetch - Update tests: set EnforceRoutePolicies on success-path domains - Add new spec: When the domain does not enforce route policies * refactor: move GetRoutesByDomain to route.go Belongs alongside GetRoutesBySpace and GetRoutesByOrg rather than in route_policy.go. * refactor: simplify GetRoutesByDomain — drop redundant copy loop ccv3.GetRoutes already returns []resources.Route directly; the loop copying each element was a no-op identity conversion. * feat: add -n short flag for --hostname on route policy commands * refactor: extract resolveOrgGUID/resolveSpaceGUID to eliminate duplication The org and space resolution blocks were duplicated between the --source-app and --source-space branches of resolveSource. Extract into standalone helpers. Add dedicated unit tests for each helper plus the previously missing --source-space + --source-org error path. * refactor: convert source flags test to package v7_test with v7fakes Switch route_policy_source_flags_test.go from package v7 (internal white-box test) to the standard package v7_test pattern used throughout the command layer. Tests now use v7fakes.FakeActor via AddRoutePolicyCommand.Execute() instead of an inline stub actor, which was required to work around the circular import between package v7 and v7fakes. resolveOrgGUID and resolveSpaceGUID are no longer tested in isolation (they are unexported and not accessible from v7_test), but all their code paths are covered by the resolveSource tests that exercise the full flag-combination matrix through Execute(). * perf: use ?include=source to resolve policy source names in one API call Replace resolveRoutePolicySource (which made a separate GetApplications/ GetSpaces/GetOrganizations call per policy) with sourceInfoFromIncluded, a pure map lookup against resources returned by ?include=route,source. CAPI's IncludeRoutePolicySourceDecorator already batches all referenced app/space/org GUIDs into a single query and returns them inline, so the route-policies command now resolves N source names with 0 extra API calls regardless of how many policies are displayed. * refactor: filter routes slice before map, pre-populate domain cache, add -d flag T10: filter includedResources.Routes slice for all three conditions (domain/ hostname/path) before building routeByGUID, so the map is only populated from matching routes. T11: create domainCache before the filter block; when a domain filter is used, pre-populate domainCache[domain.GUID] from the GetDomainByName result so the subsequent cache-fill loop is a no-op for the common single-domain case. T14: add short:'d' to the --domain flag on route-policies command. Also replace hardcoded version string in route_policies_command_test.go with ccversion.MinVersionRoutePolicies so the test stays valid when the constant is updated. * feat: register PATCH /v3/route_policies/:guid in CAPI metadata client * feat: add RoutePolicyAmbiguityError for route-policy label disambiguation * feat: implement GetRoutePolicyLabels and UpdateRoutePolicyLabels actor methods - Add resolveRoutePolicyGUID helper to find policies with ambiguity/not-found error handling - Implement GetRoutePolicyLabels to retrieve labels from route policies with optional source filtering - Implement UpdateRoutePolicyLabels to set labels on route policies with optional source filtering - Add comprehensive test coverage for success cases, error conditions, and edge cases - All 1262 tests pass * feat: add route-policy methods to Actor/SetLabelActor interfaces, regenerate fakes * feat: add route-policy support to labels command and label updater - Add RoutePolicy resource type to LabelsCommand.Execute() with GetRoutePolicyLabels() support - Add RoutePolicy to LabelsCommand.checkTarget() and Resources() documentation - Fix add_route_policy_command_test and remove_route_policy_command_test to expect correct API version 3.221.0 - Fix labels_command_test shared validation test to include route-policy in checkTarget expectations All 2299 tests passing. * feat: add route-policy support to cf labels command * feat: add --source flag to set-label and unset-label commands * fix: refactor testForResourceType helper to take explicit plural URI segment * fix: remove orphaned comment fragment in route_policy_source_flags_test.go * test: document that route-policy ResourceName is passed as-is to label setter * test: document that route-policy ResourceName is passed as-is to label unsetter * fix: remove duplicate RunSpecs in route_policy_resource_test.go * refactor: move resolveRoutePolicyGUID to route_policy.go The Get/UpdateRoutePolicyLabels wrappers in label.go follow the same convention as every other resource (GetRouteLabels, GetDomainLabels, etc.): the thin label wrapper stays in label.go and delegates GUID resolution to a helper in the resource's own file. Move the route-policy resolver alongside the other route-policy actor methods and drop the now-unused ccv3 import from label.go. * refactor: collapse resolveSource into a single org->space->app cascade Replace the three separate --source-app/--source-space/--source-org branches with one linear cascade: each level (org, then space, then app) refines the GUID the next level resolves against, and the most specific flag provided becomes the scope. The result is built once as cf:<scope>:<guid>. This removes the resolveOrgGUID/resolveSpaceGUID helpers, since GUID resolution now happens exactly once per level inline. Source strings, verbose scope output, warning ordering, and the app-not-found TIP error are all unchanged; the existing black-box command specs cover them. * fix: list route-policy in set-label and unset-label resource help * feat: add -p short flag for --path on add/remove-route-policy * Fix create-private-domain integration test SEE ALSO expectation The related_commands tag on CreatePrivateDomainCommand was updated to include add-route-policy and route-policies, but the integration test still asserted the old SEE ALSO text, causing the help/usage specs to time out waiting for a substring that no longer appears contiguously in the rendered output. * Set MinVersionRoutePolicies to the released CAPI version 3.224.0 capi-release 1.239.0 (https://github.com/cloudfoundry/capi-release/releases/tag/1.239.0) ships RFC0055 Identity-Aware Routing with CC API version 3.224.0. Replace the 3.221.0 guess with the confirmed value, drop the now-obsolete placeholder guard test, and have the command tests reference the constant instead of a hardcoded string so they can't drift from it again. --------- Co-authored-by: Anuj Chaudhari <chaudharianuj93@gmail.com>
1 parent 9c5e2a0 commit 178a2ce

57 files changed

Lines changed: 4921 additions & 184 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ _testmain.go
2626
# Built binaries
2727
*.exe
2828
/cli
29+
/cf/cli
2930

3031
out/
3132
release/*
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package actionerror
2+
3+
import "fmt"
4+
5+
// DomainNotEnforcingRoutePoliciesError is returned when a user attempts to
6+
// add a route policy to a domain that does not have enforce_route_policies enabled.
7+
type DomainNotEnforcingRoutePoliciesError struct {
8+
Name string
9+
}
10+
11+
func (e DomainNotEnforcingRoutePoliciesError) Error() string {
12+
return fmt.Sprintf("Domain '%s' does not have route policy enforcement enabled.", e.Name)
13+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package actionerror
2+
3+
import "fmt"
4+
5+
// RoutePolicyAmbiguityError is returned when a route has multiple policies
6+
// and no --source flag was given to disambiguate.
7+
type RoutePolicyAmbiguityError struct {
8+
RouteURL string
9+
Count int
10+
}
11+
12+
func (e RoutePolicyAmbiguityError) Error() string {
13+
return fmt.Sprintf(
14+
"Route '%s' has %d policies. Specify one with --source.",
15+
e.RouteURL, e.Count,
16+
)
17+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package actionerror
2+
3+
import "fmt"
4+
5+
type RoutePolicyNotFoundError struct {
6+
Source string
7+
}
8+
9+
func (e RoutePolicyNotFoundError) Error() string {
10+
return fmt.Sprintf("Route policy with source '%s' not found.", e.Source)
11+
}

actor/v7action/cloud_controller_client.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ type CloudControllerClient interface {
2020
CancelDeployment(deploymentGUID string) (ccv3.Warnings, error)
2121
ContinueDeployment(deploymentGUID string) (ccv3.Warnings, error)
2222
CopyPackage(sourcePackageGUID string, targetAppGUID string) (resources.Package, ccv3.Warnings, error)
23+
CreateRoutePolicy(routePolicy resources.RoutePolicy) (resources.RoutePolicy, ccv3.Warnings, error)
2324
CreateApplication(app resources.Application) (resources.Application, ccv3.Warnings, error)
2425
CreateApplicationDeployment(dep resources.Deployment) (string, ccv3.Warnings, error)
2526
CreateApplicationProcessScale(appGUID string, process resources.Process) (resources.Process, ccv3.Warnings, error)
@@ -42,6 +43,7 @@ type CloudControllerClient interface {
4243
CreateSpace(space resources.Space) (resources.Space, ccv3.Warnings, error)
4344
CreateSpaceQuota(spaceQuota resources.SpaceQuota) (resources.SpaceQuota, ccv3.Warnings, error)
4445
CreateUser(userGUID string) (resources.User, ccv3.Warnings, error)
46+
DeleteRoutePolicy(guid string) (ccv3.JobURL, ccv3.Warnings, error)
4547
DeleteApplication(guid string) (ccv3.JobURL, ccv3.Warnings, error)
4648
DeleteApplicationProcessInstance(appGUID string, processType string, instanceIndex int) (ccv3.Warnings, error)
4749
DeleteBuildpack(buildpackGUID string) (ccv3.JobURL, ccv3.Warnings, error)
@@ -63,6 +65,7 @@ type CloudControllerClient interface {
6365
DeleteUser(userGUID string) (ccv3.JobURL, ccv3.Warnings, error)
6466
DownloadDroplet(dropletGUID string) ([]byte, ccv3.Warnings, error)
6567
EntitleIsolationSegmentToOrganizations(isoGUID string, orgGUIDs []string) (resources.RelationshipList, ccv3.Warnings, error)
68+
GetRoutePolicies(query ...ccv3.Query) ([]resources.RoutePolicy, ccv3.IncludedResources, ccv3.Warnings, error)
6669
GetApplicationByNameAndSpace(appName string, spaceGUID string) (resources.Application, ccv3.Warnings, error)
6770
GetApplicationDropletCurrent(appGUID string) (resources.Droplet, ccv3.Warnings, error)
6871
GetApplicationEnvironment(appGUID string) (ccv3.Environment, ccv3.Warnings, error)

actor/v7action/domain.go

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ func (actor Actor) CheckRoute(domainName string, hostname string, path string, p
2424
return matches, allWarnings, err
2525
}
2626

27-
func (actor Actor) CreateSharedDomain(domainName string, internal bool, routerGroupName string) (Warnings, error) {
27+
func (actor Actor) CreateSharedDomain(domainName string, internal bool, routerGroupName string, enforceAccessRules bool, accessRulesScope string) (Warnings, error) {
2828
allWarnings := Warnings{}
2929
routerGroupGUID := ""
3030

@@ -37,28 +37,45 @@ func (actor Actor) CreateSharedDomain(domainName string, internal bool, routerGr
3737
routerGroupGUID = routerGroup.GUID
3838
}
3939

40-
_, warnings, err := actor.CloudControllerClient.CreateDomain(resources.Domain{
40+
domain := resources.Domain{
4141
Name: domainName,
4242
Internal: types.NullBool{IsSet: true, Value: internal},
4343
RouterGroup: routerGroupGUID,
44-
})
44+
}
45+
46+
// Set enforce_route_policies if specified
47+
if enforceAccessRules {
48+
domain.EnforceRoutePolicies = types.NullBool{IsSet: true, Value: true}
49+
domain.RoutePoliciesScope = accessRulesScope
50+
}
51+
52+
_, warnings, err := actor.CloudControllerClient.CreateDomain(domain)
4553
allWarnings = append(allWarnings, Warnings(warnings)...)
4654

4755
return allWarnings, err
4856
}
4957

50-
func (actor Actor) CreatePrivateDomain(domainName string, orgName string) (Warnings, error) {
58+
func (actor Actor) CreatePrivateDomain(domainName string, orgName string, enforceAccessRules bool, accessRulesScope string) (Warnings, error) {
5159
allWarnings := Warnings{}
5260
organization, warnings, err := actor.GetOrganizationByName(orgName)
5361
allWarnings = append(allWarnings, warnings...)
5462

5563
if err != nil {
5664
return allWarnings, err
5765
}
58-
_, apiWarnings, err := actor.CloudControllerClient.CreateDomain(resources.Domain{
66+
67+
domain := resources.Domain{
5968
Name: domainName,
6069
OrganizationGUID: organization.GUID,
61-
})
70+
}
71+
72+
// Set enforce_route_policies if specified
73+
if enforceAccessRules {
74+
domain.EnforceRoutePolicies = types.NullBool{IsSet: true, Value: true}
75+
domain.RoutePoliciesScope = accessRulesScope
76+
}
77+
78+
_, apiWarnings, err := actor.CloudControllerClient.CreateDomain(domain)
6279

6380
actorWarnings := Warnings(apiWarnings)
6481
allWarnings = append(allWarnings, actorWarnings...)

actor/v7action/domain_test.go

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,17 +112,21 @@ var _ = Describe("Domain Actions", func() {
112112

113113
Describe("CreateSharedDomain", func() {
114114
var (
115-
warnings Warnings
116-
executeErr error
117-
routerGroup string
115+
warnings Warnings
116+
executeErr error
117+
routerGroup string
118+
enforceRules bool
119+
scope string
118120
)
119121

120122
JustBeforeEach(func() {
121-
warnings, executeErr = actor.CreateSharedDomain("the-domain-name", true, routerGroup)
123+
warnings, executeErr = actor.CreateSharedDomain("the-domain-name", true, routerGroup, enforceRules, scope)
122124
})
123125

124126
BeforeEach(func() {
125127
routerGroup = ""
128+
enforceRules = false
129+
scope = ""
126130
fakeCloudControllerClient.CreateDomainReturns(resources.Domain{}, ccv3.Warnings{"create-warning-1", "create-warning-2"}, errors.New("create-error"))
127131
})
128132

@@ -170,11 +174,40 @@ var _ = Describe("Domain Actions", func() {
170174
))
171175
})
172176
})
177+
178+
Context("when enforce route policies is enabled with a scope", func() {
179+
BeforeEach(func() {
180+
enforceRules = true
181+
scope = "org"
182+
fakeCloudControllerClient.CreateDomainReturns(resources.Domain{}, ccv3.Warnings{"create-warning-1"}, nil)
183+
})
184+
185+
It("passes EnforceRoutePolicies and RoutePoliciesScope to the client", func() {
186+
Expect(executeErr).NotTo(HaveOccurred())
187+
188+
Expect(fakeCloudControllerClient.CreateDomainCallCount()).To(Equal(1))
189+
passedDomain := fakeCloudControllerClient.CreateDomainArgsForCall(0)
190+
Expect(passedDomain.EnforceRoutePolicies).To(Equal(types.NullBool{IsSet: true, Value: true}))
191+
Expect(passedDomain.RoutePoliciesScope).To(Equal("org"))
192+
})
193+
})
173194
})
174195

175196
Describe("CreatePrivateDomain", func() {
197+
var (
198+
warnings Warnings
199+
executeErr error
200+
enforceRules bool
201+
scope string
202+
)
203+
204+
JustBeforeEach(func() {
205+
warnings, executeErr = actor.CreatePrivateDomain("private-domain-name", "org-name", enforceRules, scope)
206+
})
176207

177208
BeforeEach(func() {
209+
enforceRules = false
210+
scope = ""
178211
fakeCloudControllerClient.GetOrganizationsReturns(
179212
[]resources.Organization{
180213
{GUID: "org-guid"},
@@ -191,7 +224,6 @@ var _ = Describe("Domain Actions", func() {
191224
})
192225

193226
It("delegates to the cloud controller client", func() {
194-
warnings, executeErr := actor.CreatePrivateDomain("private-domain-name", "org-name")
195227
Expect(executeErr).To(MatchError("create-error"))
196228
Expect(warnings).To(ConsistOf("get-orgs-warning", "create-warning-1", "create-warning-2"))
197229

@@ -205,6 +237,23 @@ var _ = Describe("Domain Actions", func() {
205237
},
206238
))
207239
})
240+
241+
Context("when enforce route policies is enabled with a scope", func() {
242+
BeforeEach(func() {
243+
enforceRules = true
244+
scope = "org"
245+
fakeCloudControllerClient.CreateDomainReturns(resources.Domain{}, ccv3.Warnings{"create-warning-1"}, nil)
246+
})
247+
248+
It("passes EnforceRoutePolicies and RoutePoliciesScope to the client", func() {
249+
Expect(executeErr).NotTo(HaveOccurred())
250+
251+
Expect(fakeCloudControllerClient.CreateDomainCallCount()).To(Equal(1))
252+
passedDomain := fakeCloudControllerClient.CreateDomainArgsForCall(0)
253+
Expect(passedDomain.EnforceRoutePolicies).To(Equal(types.NullBool{IsSet: true, Value: true}))
254+
Expect(passedDomain.RoutePoliciesScope).To(Equal("org"))
255+
})
256+
})
208257
})
209258

210259
Describe("delete domain", func() {

actor/v7action/label.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,3 +178,19 @@ func (actor *Actor) updateResourceMetadata(resourceType string, resourceGUID str
178178

179179
return warnings, nil
180180
}
181+
182+
func (actor *Actor) GetRoutePolicyLabels(routeURL, spaceGUID, source string) (map[string]types.NullString, Warnings, error) {
183+
_, metadata, warnings, err := actor.resolveRoutePolicyGUID(routeURL, spaceGUID, source)
184+
if err != nil {
185+
return nil, warnings, err
186+
}
187+
return actor.extractLabels(metadata, warnings, nil)
188+
}
189+
190+
func (actor *Actor) UpdateRoutePolicyLabels(routeURL, spaceGUID, source string, labels map[string]types.NullString) (Warnings, error) {
191+
policyGUID, _, warnings, err := actor.resolveRoutePolicyGUID(routeURL, spaceGUID, source)
192+
if err != nil {
193+
return warnings, err
194+
}
195+
return actor.updateResourceMetadata("route-policy", policyGUID, resources.Metadata{Labels: labels}, warnings)
196+
}

0 commit comments

Comments
 (0)