-
Notifications
You must be signed in to change notification settings - Fork 13
Returning resource type for relationship members and adding more information to relationship #267
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,271 @@ | ||
| # Enhanced Relationship Member Types Proposal | ||
|
|
||
| ## Executive Summary | ||
|
|
||
| This proposal outlines the implementation of enhanced relationship member types for Microsoft Graph Bicep Types, transitioning from simple string arrays to rich object structures for improved object referencing, filtering, and type-based operations while maintaining backward compatibility. | ||
|
|
||
| ## Status: ✅ IMPLEMENTED | ||
|
|
||
| **Implementation Date:** October 24, 2025 | ||
| **Implementation Status:** Complete and Production Ready | ||
| **Test Coverage:** 11/11 tests passing | ||
| **Backward Compatibility:** Maintained for v1.0 API | ||
|
|
||
| ## Problem Statement | ||
|
|
||
| The current relationship member implementation uses simple string arrays containing only object IDs. This approach has several limitations: | ||
|
|
||
| 1. **Limited Type Information**: No way to determine object type (user, group, servicePrincipal) | ||
| 2. **Filtering Constraints**: Cannot filter relationship members by type | ||
| 3. **Object Dereferencing**: No human-readable identifiers for object lookup | ||
| 4. **Template Referencing**: Limited ability to reference objects in templates | ||
|
|
||
| ### Real-World Scenarios | ||
|
|
||
| **Scenario 1: App Ownership Assignment** | ||
| - Want to set app owners based on security group members | ||
| - Security groups may contain other groups, but groups cannot own apps | ||
| - Need to filter out group objects before assignment | ||
|
|
||
| **Scenario 2: User Lookup Operations** | ||
| - Want to look up user names in a security group | ||
| - Group may contain both users and service principals | ||
| - Need to differentiate object types for proper dereferencing | ||
|
|
||
| **Scenario 3: Template-based Object Referencing** | ||
| - Need to reference existing objects in templates | ||
| - Require unique identifiers beyond just object IDs | ||
| - Want human-readable names for better template maintainability | ||
|
|
||
| ## Solution Overview | ||
|
|
||
| Implement enhanced relationship member types that provide rich object metadata while maintaining backward compatibility through version-based conditional logic. | ||
|
|
||
| ### Enhanced Relationship Member Schema | ||
|
|
||
| ```typescript | ||
| { | ||
| id: string, // Required: The object ID | ||
| type: string, // Read-only: Object type (user, group, servicePrincipal, etc.) | ||
| displayName: string, // Read-only: Human-readable name | ||
| userPrincipalName: string, // Read-only: For users - their UPN | ||
| appId: string, // Read-only: For service principals - their app ID | ||
| uniqueName: string // Read-only: Unique name for template referencing | ||
| } | ||
| ``` | ||
|
|
||
| ### Version Strategy | ||
|
|
||
| - **Enhanced Versions**: `beta/1.1.0-preview` and `v1.0/1.1.0-preview` | ||
| - **Legacy Versions**: `v1.0/1.0.0` (maintains string arrays) | ||
| - **Detection Logic**: `isEnhancedRelationshipVersion()` function | ||
|
|
||
| ## Implementation Details | ||
|
|
||
| ### Core Files Modified | ||
|
|
||
| #### 1. swaggerWriter.ts | ||
| **Location:** `src/swagger-generation/src/swaggerWriter.ts` | ||
|
|
||
| **Changes:** | ||
| - Added `isEnhancedRelationshipVersion()` detection function | ||
| - Implemented conditional `microsoft.graph.relationshipMember` definition | ||
| - Enhanced `microsoft.graph.relationship` with version-specific structures | ||
|
|
||
| **Key Implementation:** | ||
| ```typescript | ||
| // Enhanced RelationshipMember type for enhanced versions | ||
| if (isEnhanced) { | ||
| baseDefinitions["microsoft.graph.relationshipMember"] = { | ||
| type: "object", | ||
| properties: { | ||
| id: { type: "string", description: "The unique identifier of the relationship member." }, | ||
| type: { type: "string", description: "The type of the relationship member...", readOnly: true }, | ||
| displayName: { type: "string", description: "The display name...", readOnly: true }, | ||
| userPrincipalName: { type: "string", description: "The user principal name...", readOnly: true }, | ||
| appId: { type: "string", description: "The application ID...", readOnly: true }, | ||
| uniqueName: { type: "string", description: "A unique name for referencing...", readOnly: true } | ||
| }, | ||
| required: ["id"] | ||
| }; | ||
| } | ||
| ``` | ||
|
|
||
| #### 2. generate.ts | ||
| **Location:** `src/generator/src/generate.ts` | ||
|
|
||
| **Changes:** | ||
| - Updated `extensionConfigForGeneration` with v1.1.0 configuration | ||
| - Enhanced `shouldIncludeFilePath` with v1.1.0 patterns | ||
| - Updated `buildTypeIndex` for v1.1.0 version handling | ||
|
|
||
| #### 3. index.ts (swagger-generation) | ||
| **Location:** `src/swagger-generation/src/index.ts` | ||
|
|
||
| **Changes:** | ||
| - Fixed `writeSwaggerReadMeFile` to include v1.1.0 AutoRest configuration | ||
| - Added v1.1.0 section to readme template | ||
| - Ensured proper AutoRest setup for all API versions | ||
|
|
||
| ### Test Coverage | ||
|
|
||
| #### Test Suite: swaggerWriter.test.ts | ||
| **Location:** `src/swagger-generation/tests/swaggerWriter.test.ts` | ||
|
|
||
| **Coverage:** | ||
| 1. **Enhanced Beta Test**: Validates `beta/1.1.0-preview` with full relationship member objects | ||
| 2. **Enhanced v1.1.0 Test**: Validates `v1.0/1.1.0-preview` with full relationship member objects | ||
| 3. **Legacy v1.0 Test**: Validates `v1.0/1.0.0` maintains simple string arrays | ||
|
|
||
| **Test Results:** ✅ 11/11 tests passing | ||
|
|
||
| ## API Version Comparison | ||
|
|
||
| ### Enhanced Versions (beta/1.1.0-preview, v1.0/1.1.0-preview) | ||
|
|
||
| ```json | ||
| { | ||
| "microsoft.graph.relationshipMember": { | ||
| "type": "object", | ||
| "properties": { | ||
| "id": { "type": "string", "description": "The unique identifier..." }, | ||
| "type": { "type": "string", "readOnly": true, "description": "The type of the relationship member..." }, | ||
| "displayName": { "type": "string", "readOnly": true, "description": "The display name..." }, | ||
| "userPrincipalName": { "type": "string", "readOnly": true, "description": "The user principal name..." }, | ||
| "appId": { "type": "string", "readOnly": true, "description": "The application ID..." }, | ||
| "uniqueName": { "type": "string", "readOnly": true, "description": "A unique name..." } | ||
| }, | ||
| "required": ["id"] | ||
| }, | ||
| "microsoft.graph.relationship": { | ||
| "properties": { | ||
| "relationships": { | ||
| "type": "array", | ||
| "items": { "$ref": "#/definitions/microsoft.graph.relationshipMember" }, | ||
| "description": "The list of relationship members with their IDs and types." | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ### Legacy Version (v1.0/1.0.0) | ||
|
|
||
| ```json | ||
| { | ||
| "microsoft.graph.relationship": { | ||
| "properties": { | ||
| "relationships": { | ||
| "type": "array", | ||
| "items": { "type": "string" }, | ||
| "description": "The list of object ids to be included in the relationship." | ||
| } | ||
| } | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ## Usage Examples | ||
|
|
||
| ### Scenario 1: Type-based Filtering | ||
| ```bicep | ||
| // Filter out groups when setting app owners | ||
| resource myApp 'Microsoft.Graph/applications@beta' = { | ||
| owners: { | ||
| relationships: filter(securityGroup.members, member => member.type != 'group') | ||
| } | ||
| } | ||
| ``` | ||
|
|
||
| ### Scenario 2: User Identification | ||
| ```bicep | ||
| // Get user information from mixed security group | ||
| resource myGroup 'Microsoft.Graph/groups@beta' existing = { | ||
| name: 'my-security-group' | ||
| } | ||
|
|
||
| // Extract users for name lookup | ||
| var users = filter(myGroup.members, member => member.type == 'user') | ||
| // Access: member.displayName, member.userPrincipalName | ||
| ``` | ||
|
|
||
| ### Scenario 3: Service Principal Operations | ||
| ```bicep | ||
| // Work with service principals in relationships | ||
| var servicePrincipals = filter(group.members, member => member.type == 'servicePrincipal') | ||
| // Access: member.appId for application operations | ||
| ``` | ||
|
|
||
| ## Validation Results | ||
|
|
||
| ### Production Validation | ||
| - ✅ **Beta Swagger**: `microsoftgraph-beta-1.1.0-preview.json` contains enhanced relationshipMember | ||
| - ✅ **v1.1 Swagger**: `microsoftgraph-v1.0-1.1.0-preview.json` contains enhanced relationshipMember | ||
| - ✅ **v1.0 Swagger**: `microsoftgraph-v1.0-1.0.0.json` maintains string arrays (no relationshipMember) | ||
|
|
||
| ### Test Validation | ||
| ```bash | ||
| npm test -- swaggerWriter.test.ts | ||
| # Result: 11 passed, 0 failed | ||
| ``` | ||
|
|
||
| ### Generated Output Verification | ||
| ```powershell | ||
| # Enhanced versions contain full object structure | ||
| Get-Content src\swagger-generation\output\microsoftgraph-beta-1.1.0-preview.json | | ||
| ConvertFrom-Json | Select-Object -ExpandProperty definitions | | ||
| Select-Object -ExpandProperty "microsoft.graph.relationshipMember" | ||
|
|
||
| # Legacy version uses simple strings | ||
| Get-Content src\swagger-generation\output\microsoftgraph-v1.0-1.0.0.json | | ||
| ConvertFrom-Json | Select-Object -ExpandProperty definitions | | ||
| Select-Object -ExpandProperty "microsoft.graph.relationship" | ||
| ``` | ||
|
|
||
| ## Benefits Delivered | ||
|
|
||
| 1. **Enhanced Type Information**: Full object metadata for intelligent operations | ||
| 2. **Improved Filtering**: Type-based filtering capabilities for relationships | ||
| 3. **Better Object Referencing**: Multiple identifiers (displayName, UPN, appId, uniqueName) | ||
| 4. **Template Flexibility**: Rich object properties for template-based operations | ||
| 5. **Backward Compatibility**: Zero impact on existing v1.0 implementations | ||
| 6. **Production Ready**: Comprehensive test coverage and validation | ||
|
|
||
| ## Migration Path | ||
|
|
||
| ### For New Implementations | ||
| - Use enhanced versions (`beta/1.1.0-preview` or `v1.0/1.1.0-preview`) | ||
| - Leverage rich relationship member objects for advanced scenarios | ||
|
|
||
| ### For Existing Implementations | ||
| - v1.0 implementations continue working unchanged | ||
| - Opt-in to enhanced versions when ready for advanced features | ||
| - No breaking changes in legacy API versions | ||
|
|
||
| ## Technical Architecture | ||
|
|
||
| ### Version Detection Logic | ||
| ```typescript | ||
| function isEnhancedRelationshipVersion(config: Config): boolean { | ||
| return (config.APIVersion === 'beta' && config.ExtensionVersion === '1.1.0-preview') || | ||
| (config.APIVersion === 'v1.0' && config.ExtensionVersion === '1.1.0-preview'); | ||
| } | ||
| ``` | ||
|
|
||
| ### Conditional Schema Generation | ||
| - Enhanced versions: Generate `microsoft.graph.relationshipMember` + enhanced `microsoft.graph.relationship` | ||
| - Legacy versions: Generate only `microsoft.graph.relationship` with string arrays | ||
| - All versions: Include `microsoft.graph.relationshipSemantics` for relationship handling | ||
|
|
||
| ## Future Considerations | ||
|
|
||
| 1. **Additional Object Properties**: Can extend relationshipMember with more Graph object properties | ||
| 2. **Custom Unique Names**: Potential for user-defined unique name generation | ||
| 3. **Type-specific Properties**: Could add type-specific property sets (e.g., group-specific properties) | ||
| 4. **Cross-reference Capabilities**: Enhanced object dereferencing across relationship types | ||
|
|
||
| ## Conclusion | ||
|
|
||
| The Enhanced Relationship Member Types implementation successfully addresses all identified limitations while maintaining full backward compatibility. The solution provides rich object metadata for advanced filtering, referencing, and type-based operations, enabling sophisticated Microsoft Graph Bicep template scenarios. | ||
|
|
||
| **Status: Production Ready** ✅ | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
34 changes: 34 additions & 0 deletions
34
generated/microsoftgraph/microsoft.graph/beta/1.1.0-preview/index.json
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,34 @@ | ||
| { | ||
| "resources": { | ||
| "Microsoft.Graph/groups@beta": { | ||
| "$ref": "types.json#/23" | ||
| }, | ||
| "Microsoft.Graph/applications@beta": { | ||
| "$ref": "types.json#/79" | ||
| }, | ||
| "Microsoft.Graph/servicePrincipals@beta": { | ||
| "$ref": "types.json#/97" | ||
| }, | ||
| "Microsoft.Graph/applications/federatedIdentityCredentials@beta": { | ||
| "$ref": "types.json#/103" | ||
| }, | ||
| "Microsoft.Graph/oauth2PermissionGrants@beta": { | ||
| "$ref": "types.json#/107" | ||
| }, | ||
| "Microsoft.Graph/appRoleAssignedTo@beta": { | ||
| "$ref": "types.json#/111" | ||
| }, | ||
| "Microsoft.Graph/users@beta": { | ||
| "$ref": "types.json#/116" | ||
| } | ||
| }, | ||
| "resourceFunctions": {}, | ||
| "settings": { | ||
| "name": "MicrosoftGraphBeta", | ||
| "version": "1.1.0-preview", | ||
| "isSingleton": false, | ||
| "configurationType": { | ||
| "$ref": "types.json#/117" | ||
| } | ||
| } | ||
| } |
23 changes: 23 additions & 0 deletions
23
generated/microsoftgraph/microsoft.graph/beta/1.1.0-preview/index.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,23 @@ | ||
| # Bicep Types | ||
| ## microsoft.graph | ||
| ### microsoft.graph/applications | ||
| * **Link**: [beta](types.md#resource-microsoftgraphapplicationsbeta) | ||
|
|
||
| ### microsoft.graph/applications/federatedidentitycredentials | ||
| * **Link**: [beta](types.md#resource-microsoftgraphapplicationsfederatedidentitycredentialsbeta) | ||
|
|
||
| ### microsoft.graph/approleassignedto | ||
| * **Link**: [beta](types.md#resource-microsoftgraphapproleassignedtobeta) | ||
|
|
||
| ### microsoft.graph/groups | ||
| * **Link**: [beta](types.md#resource-microsoftgraphgroupsbeta) | ||
|
|
||
| ### microsoft.graph/oauth2permissiongrants | ||
| * **Link**: [beta](types.md#resource-microsoftgraphoauth2permissiongrantsbeta) | ||
|
|
||
| ### microsoft.graph/serviceprincipals | ||
| * **Link**: [beta](types.md#resource-microsoftgraphserviceprincipalsbeta) | ||
|
|
||
| ### microsoft.graph/users | ||
| * **Link**: [beta](types.md#resource-microsoftgraphusersbeta) | ||
|
|
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.