Date: 2025-10-31 Reviewer: AI Code Review Scope: terraform-provider-simplemdm/provider directory
This review analyzes the code quality, test coverage, and technical debt in the terraform-provider-simplemdm codebase. The provider shows good overall structure and consistent patterns, but has areas for improvement in test coverage, code complexity, and code reuse.
- Test Coverage: 1.6% (unit tests only, excludes acceptance tests)
- Files Analyzed: 90+ Go files
- Lines of Code: ~12,000 lines
- Test Files: 60+ test files
- Critical Issues: 0
- Optimization Opportunities: 5 major areas
PASS
coverage: 1.6% of statements
ok github.com/DavidKrau/terraform-provider-simplemdm/provider 1.709s
- Comprehensive Acceptance Test Suite: All resources and data sources have acceptance tests
- Well-Documented Test Requirements:
TEST_COVERAGE.mdclearly explains fixture requirements - Dynamic Test Pattern: Most tests create resources dynamically rather than relying on fixtures
- Unit Tests Present: Some unit tests exist (e.g.,
TestNewAppResourceModelFromAPI_AllFields)
- Low Unit Test Coverage: Only 1.6% coverage from unit tests
- Acceptance Test Dependency: Most testing requires
TF_ACC=1and API access - Missing Unit Tests For:
- Helper functions (
diffFunction,boolPointerFromType, etc.) - Error handling paths
- API response parsing logic
- Complex business logic in resource Create/Update methods
- Helper functions (
- Add Unit Tests: Target 60%+ coverage for non-acceptance-test code
- Mock API Calls: Create mock client for testing without API dependency
- Test Edge Cases: Add tests for error conditions, nil values, empty responses
- Test Helper Functions: Add dedicated tests for utility functions
managedConfigs_data_source.go(163 lines)managedConfigs_data_source_test.go(50 lines)managedConfig_data_source.go(121 lines)managedConfig_helpers.go(155 lines)
- Clean Structure: Well-organized with separate helper file
- Proper Error Handling: Consistent use of
isNotFoundError()pattern - Good Documentation: Clear descriptions in schema
- Proper Type Usage: Correct use of Terraform types (types.String, etc.)
- Test Coverage: Comprehensive acceptance test with dynamic resource creation
- No unused imports detected
- No code duplication issues
- Error messages are clear and actionable
- Follows Terraform plugin framework best practices
The test TestAccManagedConfigsDataSource_basic properly:
- Creates app dynamically
- Creates multiple managed configs
- Tests data source with
depends_onfor consistency - Validates expected attributes
- Consistent file naming conventions
- Logical separation of concerns (resources, data sources, helpers)
- Clear registry pattern for registering resources/data sources
$ go vet ./...
# No issues found- No commented-out code blocks detected
- No unreachable code identified
- All exported functions are used
| File | Lines | Complexity Issue |
|---|---|---|
assignmentGroup_resource.go |
776 | Very long Create/Update methods |
app_resource.go |
666 | Complex nested conditionals |
customDeclaration_resource.go |
697 | Long methods |
deviceGroup_resource.go |
505 | Repetitive code patterns |
Issue: Lines 243-608 contain highly repetitive code for handling apps/profiles/groups/devices
// Pattern repeated 4 times for apps, profiles, groups, devices
for _, appId := range plan.Apps.Elements() {
err := r.client.AssignmentGroupAssignObject(...)
if err != nil {
resp.Diagnostics.AddError(...)
return
}
}Impact: ~300 lines could be reduced to ~100 lines
Recommendation: Extract to helper function handleAssignments()
Location: assignmentGroup_resource.go:711-741
func diffFunction(state []string, plan []string) (add []string, remove []string) {
// Uses nested loops - O(n²) complexity
for _, planObject := range plan {
ispresent := false
for _, stateObject := range state {
if planObject == stateObject {
ispresent = true
break
}
}
if !ispresent {
IDsToAdd = append(IDsToAdd, planObject)
}
}
// Similar loop for removals...
}Issue: Inefficient for large assignment groups Recommendation: Use map-based approach for O(n) complexity
Issue: Helper functions duplicated across files
boolPointerFromType(assignmentGroup_resource.go:743)stringPointerFromType(assignmentGroup_resource.go:752)int64PointerFromType(assignmentGroup_resource.go:761)
Recommendation: Move to shared provider/helpers.go file
Location: app_resource.go:210-300
Issue: 20+ similar if-else blocks for field mapping
if app.Data.Attributes.Name != "" {
model.Name = types.StringValue(app.Data.Attributes.Name)
} else {
model.Name = types.StringNull()
}
// Repeated 15+ times...Recommendation: Create generic stringOrNull() helper function
- 404 Detection: Consistent use of
isNotFoundError()helper - Context Propagation: Proper use of
context.Contextthroughout - User-Friendly Messages: Clear error messages with context
- State Cleanup: Proper
resp.State.RemoveResource(ctx)on 404s
Location: script_job_helpers.go:182-184
func isNotFoundError(err error) bool {
return err != nil && strings.Contains(err.Error(), "404")
}Usage: Found in 26 files - consistently applied ✅
File: assignmentGroup_resource.go:711
Severity: Medium
Type: Performance
Current Implementation: O(n²) nested loops Impact: Slow for large assignment groups (100+ items)
Recommended Fix:
func diffFunction(state []string, plan []string) (add []string, remove []string) {
stateMap := make(map[string]bool, len(state))
for _, s := range state {
stateMap[s] = true
}
planMap := make(map[string]bool, len(plan))
for _, p := range plan {
planMap[p] = true
if !stateMap[p] {
add = append(add, p)
}
}
for _, s := range state {
if !planMap[s] {
remove = append(remove, s)
}
}
return add, remove
}Benefit: Reduces complexity from O(n²) to O(n)
File: assignmentGroup_resource.go
Severity: Medium
Type: Maintainability
Problem: Lines 243-288 (Create) and 455-609 (Update) contain nearly identical logic repeated 4 times
Recommended Refactoring:
type assignmentConfig struct {
planElements []attr.Value
stateElements []attr.Value
objectType string
errorContext string
}
func (r *assignment_groupResource) handleAssignments(
ctx context.Context,
groupID string,
config assignmentConfig,
resp *resource.Response,
) {
// Unified logic for all assignment types
}Benefit: ~200 lines reduction, easier to maintain
Files: Multiple files Severity: Low Type: Code Reuse
Problem: Helper functions duplicated across files:
boolPointerFromTypestringPointerFromTypeint64PointerFromTypeboolValueOrDefault
Recommended Solution: Create provider/type_helpers.go
Files: Multiple resources Severity: Low Type: Readability
Examples:
assignmentGroup_resource.go:215-392- Create (177 lines)assignmentGroup_resource.go:429-688- Update (259 lines)
Recommendation: Extract sub-functions for:
- Assignment handling
- Command execution
- State restoration logic
$ go test ./provider/
PASS
ok github.com/DavidKrau/terraform-provider-simplemdm/provider 1.709sAll non-acceptance tests pass successfully:
TestNewAppResourceModelFromAPI_AllFields✅TestNewAppResourceModelFromAPI_PartialData✅TestAPICatalogCoverage✅TestResourceDocumentationCoverage✅TestDataSourceDocumentationCoverage✅
- Require
TF_ACC=1environment variable - Require
SIMPLEMDM_APIKEY - Well documented in
TEST_COVERAGE.md
- ✅ Consistent Architecture: Uniform resource/data source patterns
- ✅ Good Documentation: Clear schema descriptions and comments
- ✅ Proper Error Handling: Consistent error patterns throughout
- ✅ Test Coverage Strategy: Well-documented testing approach
- ✅ No Critical Bugs: No obvious bugs or security issues found
- ✅ Clean Imports: No unused imports detected
- ✅ Type Safety: Proper use of Terraform types framework
- ✅ Context Usage: Proper context propagation for cancellation
- Registry Pattern: Clean resource/data source registration
- Helper Functions: Good separation of API logic
- Error Recovery: Proper state cleanup on errors
- Eventual Consistency: Handles API eventual consistency in assignment groups
- Increase Unit Test Coverage (Current: 1.6%, Target: 60%+)
- Estimated effort: 2-3 days
- Impact: High - enables confident refactoring
-
Optimize
diffFunction- Change from O(n²) to O(n)- Estimated effort: 1 hour
- Impact: Medium - performance improvement for large assignments
-
Refactor Assignment Handling - Reduce ~200 lines of duplication
- Estimated effort: 4 hours
- Impact: Medium - improved maintainability
-
Extract Type Helper Functions - Consolidate duplicated helpers
- Estimated effort: 2 hours
- Impact: Low - cleaner code organization
-
Split Long Methods - Break down Create/Update methods
- Estimated effort: 3 hours
- Impact: Low - improved readability
- ✅ Fix
diffFunctionPerformance - Quick win, significant impact - ✅ Create
provider/type_helpers.go- Consolidate common helpers - Add Unit Tests for Helpers - Test existing utility functions
- Refactor Assignment Handling - Reduce code duplication
- Add Mock Client - Enable testing without API access
- Increase Unit Test Coverage - Target 30%+ coverage
- Extract Long Methods - Break down complex functions
- Add Integration Tests - Test end-to-end scenarios
- Performance Testing - Benchmark large-scale operations
| Category | Status | Notes |
|---|---|---|
| Unused Imports | ✅ Pass | go vet clean |
| Dead Code | ✅ Pass | No unreachable code |
| Error Handling | ✅ Pass | Consistent patterns |
| Test Coverage | 1.6% (needs improvement) | |
| Code Duplication | Assignment handling duplicated | |
| Performance | diffFunction needs optimization | |
| Documentation | ✅ Good | Well documented |
| Security | ✅ Pass | No issues found |
| Type Safety | ✅ Pass | Proper framework usage |
The terraform-provider-simplemdm codebase demonstrates good overall quality with consistent patterns, proper error handling, and comprehensive acceptance testing. The main areas for improvement are:
- Test Coverage: Needs significant increase in unit tests
- Code Duplication: Assignment handling code should be consolidated
- Performance:
diffFunctionneeds optimization for large datasets
Overall Grade: B+ (Good, with room for optimization)
Recommendation: Code is production-ready but would benefit from the suggested improvements for long-term maintainability.
- app_resource.go (666 lines)
- assignmentGroup_resource.go (776 lines)
- attribute_resource.go
- customDeclaration_resource.go (697 lines)
- customDeclaration_device_assignment_resource.go
- customProfile_resource.go (328 lines)
- device_command_resource.go (267 lines)
- device_resource.go (484 lines)
- deviceGroup_resource.go (505 lines)
- enrollment_resource.go (301 lines)
- managedConfig_resource.go (246 lines)
- profile_resource.go (369 lines)
- script_resource.go (239 lines)
- scriptJob_resource.go (441 lines)
- All data sources follow consistent patterns
- No significant issues identified
- assignment_group_helpers.go (277 lines)
- enrollment_helpers.go
- managedConfig_helpers.go (155 lines)
- script_job_helpers.go (294 lines)
- provider.go (159 lines)
- registry.go (432 lines)
- test_helpers.go