-
Notifications
You must be signed in to change notification settings - Fork 27
feat: Add AI Model Config resource and data source #371
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
base: main
Are you sure you want to change the base?
Conversation
- Upgrade api-client-go from v17.1.0 to v17.2.0 for AI Model Config support - Add resource_launchdarkly_ai_model_config with Create, Read, Delete operations - Add data_source_launchdarkly_ai_model_config for read-only access - Add ai_model_config_helper with schema and read functions - Add JSON helper functions for params and customParams fields - Register both resource and data source in provider - Add schema constants for AI Model Config fields Note: AI Model Configs do not support updates via PATCH API, so all fields are marked as ForceNew to force recreation on any changes. Co-Authored-By: traci@launchdarkly.com <traci@launchdarkly.com>
🤖 Devin AI EngineerI'll be helping with this pull request! Here's what you should know: ✅ I will automatically:
Note: I can only respond to comments from users who have write access to this repository. ⚙️ Control Options:
|
| Type: schema.TypeString, | ||
| Required: !isDataSource, | ||
| Computed: isDataSource, | ||
| ForceNew: !isDataSource, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
do you actually want to force new for resources that change their name? this will trigger a delete and then a recreation of a totally new resource with the same properties
| ID: { | ||
| Type: schema.TypeString, | ||
| Required: !isDataSource, | ||
| Computed: isDataSource, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does the user assign this or does LD? if LD assigns this it should always be computed and the force new is moot
| Optional: !isDataSource, | ||
| Computed: isDataSource, | ||
| ForceNew: !isDataSource, | ||
| Description: addForceNewDescription("Model parameters as a JSON string.", !isDataSource), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
are these parameters fixed? if so i would recommend trying for an object rather than forcing hte user to pass a json string similar to the API
| }, | ||
| }, | ||
| CUSTOM_PARAMS: { | ||
| Type: schema.TypeString, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto - not convinced this should be a string
| Type: schema.TypeString, | ||
| Optional: !isDataSource, | ||
| Computed: isDataSource, | ||
| ForceNew: !isDataSource, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto force new
| Type: schema.TypeString, | ||
| Optional: !isDataSource, | ||
| Computed: isDataSource, | ||
| ForceNew: !isDataSource, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ditto force new
| Type: schema.TypeFloat, | ||
| Optional: !isDataSource, | ||
| Computed: isDataSource, | ||
| ForceNew: !isDataSource, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay i see devin just thinks everything should force new. i'm assuming this has something to do with the no update thing, but i still think someone should look at this more closely
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the detailed review! I want to address the ForceNew concerns and explain my reasoning.
The Core Issue: No PATCH Endpoint
I've investigated the API client v17.2.0 and the available methods for AI Model Configs are:
PostModelConfig(create)GetModelConfig(read)DeleteModelConfig(delete)ListModelConfigs(list)
There is no PatchModelConfig method in the API client. Without an update endpoint, I cannot implement Terraform's UpdateContext function. If I remove ForceNew from user-settable fields, Terraform would plan an update but fail at apply time because there's no API to call.
Is there an undocumented or planned update endpoint I should be using instead? If so, I'm happy to implement proper updates and remove ForceNew where appropriate.
Addressing Your Specific Comments:
-
params/customParams as objects: You're absolutely right! The OpenAPI spec shows these as
type: "object", not strings. I'll change them toschema.TypeMapto provide a better UX. -
ID field: According to the OpenAPI spec,
idis required inModelConfigPost, so it's user-provided (not LD-assigned). I'll keep it asRequired: truewithForceNew: true. -
GLOBAL field: You're correct -
globalis NOT inModelConfigPost, so it's server-assigned. I'll change it toComputed: trueonly and removeForceNew. -
ForceNew on other fields: Fields like
name,provider,icon,costPerInputToken,costPerOutputToken, etc. are all user-provided inModelConfigPost. Without a PATCH endpoint, these needForceNew: trueto maintain correct Terraform semantics. Otherwise, users would see planned updates that fail at apply time.
My Plan:
- Change params/customParams to TypeMap objects
- Fix GLOBAL to be Computed-only
- Keep ForceNew on user-settable fields (unless you can point me to an update endpoint)
- Add Beta API header if needed
Please let me know if there's an update endpoint I'm missing, or if you'd prefer a different approach!
| }, | ||
| GLOBAL: { | ||
| Type: schema.TypeBool, | ||
| Computed: true, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this user-defined or does LD auto-assign the value? if the former it should not be computed
sloloris
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hi @tracisiebel !
before we approve and release this, could you get someone from your team who is familiar with the resource and the API to review this, especially the schema? i also don't think we have many (if any) other resources that don't allow update / have an associated patch API - i think it is worth having a more deliberate conversation about how we actually expect the provider to behave in this situation.
also, we will want to ensure it is thoroughly tested before we merge.
- Change params and customParams from JSON strings to TypeMap objects per reviewer feedback - Fix GLOBAL field to be Computed-only (already correct, no changes needed) - Fix v17.2.0 compatibility: dereference pointer for flag.Environments in feature_flag_environment_helper.go - Fix v17.2.0 compatibility: remove IsActive field from MetricPost in resource_launchdarkly_metric.go - Remove unused isActive variable from metric create function Co-Authored-By: traci@launchdarkly.com <traci@launchdarkly.com>
Resolved merge conflict in go.mod: - Kept api-client-go v17.2.0 (required for AI Model Config) - Updated golang.org/x/sync to v0.18.0 from main Co-Authored-By: traci@launchdarkly.com <traci@launchdarkly.com>
…map change The v17.2.0 API client changed flag.Environments from map[string]FeatureFlagConfig to *map[string]FeatureFlagConfig (pointer to map). Updated test files to add nil checks and dereference the pointer before indexing, matching the pattern used in production code (feature_flag_environment_helper.go). Co-Authored-By: traci@launchdarkly.com <traci@launchdarkly.com>
Removed jsonMarshal and jsonEqual functions that were no longer needed after changing params and customParams from JSON strings to TypeMap objects. Also removed now-unused encoding/json and reflect imports. Co-Authored-By: traci@launchdarkly.com <traci@launchdarkly.com>
- Rename 'provider' field to 'model_provider' to avoid Terraform reserved name conflict - Add ForceNew to tags field since there is no Update endpoint - Both resource and data source now pass InternalValidate checks Co-Authored-By: traci@launchdarkly.com <traci@launchdarkly.com>
Wait!
Summary
This PR adds support for AI Model Configs in the LaunchDarkly Terraform provider by:
launchdarkly_ai_model_configresource and data sourceChanges
New Resources
launchdarkly_ai_model_config- Create and manage AI model configurationsdata.launchdarkly_ai_model_config- Read AI model configuration dataSchema Design
All fields are marked
ForceNew: truebecause the API has no PATCH/Update endpoint (only POST, GET, DELETE). Any changes to an AI Model Config will force resource recreation.Fields:
project_key(Required, ForceNew)key(Required, ForceNew)name(Required, ForceNew)id(Required, ForceNew) - Model identifier for third-party providersmodel_provider(Optional, ForceNew) - Renamed from "provider" to avoid Terraform reserved nameicon(Optional, ForceNew)params(Optional, ForceNew) - TypeMap for model parameterscustom_params(Optional, ForceNew) - TypeMap for custom parameterstags(Optional, ForceNew)cost_per_input_token(Optional, ForceNew)cost_per_output_token(Optional, ForceNew)version(Computed)global(Computed)API Client Upgrade (v17.1.0 → v17.2.0)
The upgrade introduced breaking changes that required fixes:
flag.Environments type change: Changed from
map[string]ldapi.FeatureFlagConfigto*map[string]ldapi.FeatureFlagConfigfeature_flag_environment_helper.go,data_source_launchdarkly_feature_flag_environment_test.go,resource_launchdarkly_feature_flag_environment_test.goMetricPost.IsActive removed: Field no longer exists in v17.2.0
resource_launchdarkly_metric.goUnused helper functions: Removed
jsonMarshalandjsonEqualfromhelper.goafter switching from JSON strings to TypeMapKnown Issues
Root Cause: The
idfield conflicts with Terraform's reservedidfield (used for resource IDs). The schema field needs to be renamed tomodel_idor similar.Impact: All acceptance tests fail immediately with this validation error, preventing any tests from running.
Missing Tests
No acceptance tests were added for:
Documentation
Documentation was not generated due to local goenv setup issues. The
make generatecommand needs to be run successfully before merge.Human Review Checklist
Critical Items:
model_idor similar to avoid Terraform reserved namemodel_providerfor the LLM provider field)Schema Review:
5. Confirm all fields should be ForceNew (no Update endpoint exists)
6. Review TypeMap usage for params/customParams vs JSON strings
7. Verify tags field override to add ForceNew is correct
Side Effects:
8. Review feature flag environment test changes (pointer dereference)
9. Review metric resource changes (IsActive removal)
10. Check if any other resources use the v17.2.0 API changes
Testing
Local Testing: Compilation passes with
go test ./launchdarkly -cCI Status: ❌ Failing - validation error prevents all tests from running
Links