diff --git a/.generator/schemas/v2/openapi.yaml b/.generator/schemas/v2/openapi.yaml index 45672b441b..e83df8269e 100644 --- a/.generator/schemas/v2/openapi.yaml +++ b/.generator/schemas/v2/openapi.yaml @@ -1277,6 +1277,15 @@ components: example: "550e8400-e29b-41d4-a716-446655440001" format: uuid type: string + exposure_schedule_id: + description: The ID of the exposure schedule. + in: path + name: exposure_schedule_id + required: true + schema: + example: "550e8400-e29b-41d4-a716-446655440010" + format: uuid + type: string feature_flag_id: description: The ID of the feature flag. in: path @@ -3348,6 +3357,334 @@ components: - WARN - ERROR - OK + Allocation: + description: Targeting rule (allocation) details for a feature flag environment. + properties: + created_at: + description: The timestamp when the targeting rule allocation was created. + example: "2024-01-01T12:00:00Z" + format: date-time + type: string + environment_ids: + description: Environment IDs associated with this targeting rule allocation. + example: + - "550e8400-e29b-41d4-a716-446655440001" + items: + description: Environment ID linked to this targeting rule allocation. + format: uuid + type: string + type: array + experiment_id: + description: The experiment ID linked to this targeting rule allocation. + example: "550e8400-e29b-41d4-a716-446655440030" + nullable: true + type: string + exposure_schedule: + $ref: "#/components/schemas/AllocationExposureSchedule" + guardrail_metrics: + description: Guardrail metrics associated with this targeting rule allocation. + items: + $ref: "#/components/schemas/GuardrailMetric" + type: array + id: + description: The unique identifier of the targeting rule allocation. + example: "550e8400-e29b-41d4-a716-446655440020" + format: uuid + type: string + key: + description: The unique key of the targeting rule allocation. + example: "prod-rollout" + type: string + name: + description: The display name of the targeting rule. + example: "Production Rollout" + type: string + order_position: + description: Sort order position within the environment. + example: 0 + format: int64 + type: integer + targeting_rules: + description: Conditions associated with this targeting rule allocation. + items: + $ref: "#/components/schemas/TargetingRule" + type: array + type: + $ref: "#/components/schemas/AllocationType" + updated_at: + description: The timestamp when the targeting rule allocation was last updated. + example: "2024-01-01T12:00:00Z" + format: date-time + type: string + variant_weights: + description: Weighted variant assignments for this targeting rule allocation. + items: + $ref: "#/components/schemas/VariantWeight" + type: array + required: + - name + - key + - targeting_rules + - variant_weights + - order_position + - environment_ids + - type + - guardrail_metrics + - created_at + - updated_at + type: object + AllocationDataRequest: + description: Data wrapper for allocation request payloads. + properties: + attributes: + $ref: "#/components/schemas/UpsertAllocationRequest" + type: + $ref: "#/components/schemas/AllocationDataType" + required: + - type + - attributes + type: object + AllocationDataResponse: + description: Data wrapper for targeting rule allocation responses. + properties: + attributes: + $ref: "#/components/schemas/Allocation" + id: + description: The unique identifier of the targeting rule allocation. + example: "550e8400-e29b-41d4-a716-446655440020" + format: uuid + type: string + type: + $ref: "#/components/schemas/AllocationDataType" + required: + - id + - type + - attributes + type: object + AllocationDataType: + description: The resource type. + enum: + - "allocations" + example: "allocations" + type: string + x-enum-varnames: + - ALLOCATIONS + AllocationExposureGuardrailTrigger: + description: Guardrail trigger details for a progressive rollout. + properties: + allocation_exposure_schedule_id: + description: The progressive rollout ID this trigger belongs to. + example: "550e8400-e29b-41d4-a716-446655440010" + format: uuid + type: string + created_at: + description: The timestamp when this trigger was created. + example: "2024-01-01T12:00:00Z" + format: date-time + type: string + flagging_variant_id: + description: The variant ID that triggered this event. + example: "550e8400-e29b-41d4-a716-446655440001" + format: uuid + type: string + id: + description: The unique identifier of the guardrail trigger. + example: "550e8400-e29b-41d4-a716-446655440080" + format: uuid + type: string + metric_id: + description: The metric ID associated with the trigger. + example: "metric-error-rate" + type: string + triggered_action: + description: The action that was triggered. + example: "PAUSE" + type: string + updated_at: + description: The timestamp when this trigger was last updated. + example: "2024-01-01T12:00:00Z" + format: date-time + type: string + required: + - id + - allocation_exposure_schedule_id + - flagging_variant_id + - metric_id + - triggered_action + - created_at + - updated_at + type: object + AllocationExposureRolloutStep: + description: Exposure progression step details. + properties: + allocation_exposure_schedule_id: + description: The progressive rollout ID this step belongs to. + example: "550e8400-e29b-41d4-a716-446655440010" + format: uuid + type: string + created_at: + description: The timestamp when the progression step was created. + example: "2024-01-01T12:00:00Z" + format: date-time + type: string + exposure_ratio: + description: The exposure ratio for this step. + example: 0.1 + format: double + maximum: 1 + minimum: 0 + type: number + grouped_step_index: + description: Logical index grouping related steps. + example: 0 + format: int64 + minimum: 0 + type: integer + id: + description: The unique identifier of the progression step. + example: "550e8400-e29b-41d4-a716-446655440040" + format: uuid + type: string + interval_ms: + description: Step duration in milliseconds. + example: 3600000 + format: int64 + nullable: true + type: integer + is_pause_record: + description: Whether this step represents a pause record. + example: false + type: boolean + order_position: + description: Sort order for the progression step. + example: 0 + format: int64 + type: integer + updated_at: + description: The timestamp when the progression step was last updated. + example: "2024-01-01T12:00:00Z" + format: date-time + type: string + required: + - id + - allocation_exposure_schedule_id + - order_position + - exposure_ratio + - is_pause_record + - grouped_step_index + - created_at + - updated_at + type: object + AllocationExposureSchedule: + description: Progressive release details for a targeting rule allocation. + properties: + absolute_start_time: + description: The absolute UTC start time for this schedule. + example: "2025-06-13T12:00:00Z" + format: date-time + nullable: true + type: string + allocation_id: + description: The targeting rule allocation ID this progressive rollout belongs to. + example: "550e8400-e29b-41d4-a716-446655440020" + format: uuid + type: string + control_variant_id: + description: The control variant ID used for experiment comparisons. + example: "550e8400-e29b-41d4-a716-446655440012" + nullable: true + type: string + created_at: + description: The timestamp when the schedule was created. + example: "2024-01-01T12:00:00Z" + format: date-time + type: string + guardrail_triggered_action: + description: Last guardrail action triggered for this schedule. + example: "PAUSE" + nullable: true + type: string + guardrail_triggers: + description: Guardrail trigger records for this schedule. + items: + $ref: "#/components/schemas/AllocationExposureGuardrailTrigger" + type: array + id: + description: The unique identifier of the progressive rollout. + example: "550e8400-e29b-41d4-a716-446655440010" + format: uuid + type: string + rollout_options: + $ref: "#/components/schemas/RolloutOptions" + rollout_steps: + description: Ordered progression steps for exposure. + items: + $ref: "#/components/schemas/AllocationExposureRolloutStep" + type: array + updated_at: + description: The timestamp when the schedule was last updated. + example: "2024-01-01T12:00:00Z" + format: date-time + type: string + required: + - allocation_id + - rollout_options + - rollout_steps + - guardrail_triggers + - created_at + - updated_at + type: object + AllocationExposureScheduleData: + description: Data wrapper for progressive rollout schedule responses. + properties: + attributes: + $ref: "#/components/schemas/AllocationExposureSchedule" + id: + description: The unique identifier of the progressive rollout. + example: "550e8400-e29b-41d4-a716-446655440010" + format: uuid + type: string + type: + $ref: "#/components/schemas/AllocationExposureScheduleDataType" + required: + - id + - type + - attributes + type: object + AllocationExposureScheduleDataType: + description: The resource type for progressive rollout schedules. + enum: + - "allocation_exposure_schedules" + example: "allocation_exposure_schedules" + type: string + x-enum-varnames: + - ALLOCATION_EXPOSURE_SCHEDULES + AllocationExposureScheduleResponse: + description: Response containing a progressive rollout schedule. + properties: + data: + $ref: "#/components/schemas/AllocationExposureScheduleData" + required: + - data + type: object + AllocationResponse: + description: Response containing a single targeting rule (allocation). + properties: + data: + $ref: "#/components/schemas/AllocationDataResponse" + required: + - data + type: object + AllocationType: + description: The type of targeting rule (called allocation in the API model). + enum: + - FEATURE_GATE + - CANARY + example: "FEATURE_GATE" + type: string + x-enum-varnames: + - FEATURE_GATE + - CANARY Annotation: description: "A list of annotations used in the workflow. These are like sticky notes for your workflow!" properties: @@ -12764,6 +13101,92 @@ components: - SEARCH - CONTAINER - CALLOUTVALUE + Condition: + description: Targeting condition details. + properties: + attribute: + description: The user or request attribute to evaluate. + example: "country" + type: string + created_at: + description: The timestamp when the condition was created. + example: "2024-01-01T12:00:00Z" + format: date-time + type: string + id: + description: The unique identifier of the condition. + example: "550e8400-e29b-41d4-a716-446655440070" + format: uuid + type: string + operator: + $ref: "#/components/schemas/ConditionOperator" + updated_at: + description: The timestamp when the condition was last updated. + example: "2024-01-01T12:00:00Z" + format: date-time + type: string + value: + description: Values used by the selected operator. + example: ["US", "CA"] + items: + description: Target value for the selected operator. + type: string + type: array + required: + - id + - operator + - attribute + - value + - created_at + - updated_at + type: object + ConditionOperator: + description: The operator used in a targeting condition. + enum: + - LT + - LTE + - GT + - GTE + - MATCHES + - NOT_MATCHES + - ONE_OF + - NOT_ONE_OF + - IS_NULL + - EQUALS + example: "ONE_OF" + type: string + x-enum-varnames: + - LT + - LTE + - GT + - GTE + - MATCHES + - NOT_MATCHES + - ONE_OF + - NOT_ONE_OF + - IS_NULL + - EQUALS + ConditionRequest: + description: Condition request payload for targeting rules. + properties: + attribute: + description: The user or request attribute to evaluate. + example: "user_tier" + type: string + operator: + $ref: "#/components/schemas/ConditionOperator" + value: + description: Values used by the selected operator. + example: ["premium", "enterprise"] + items: + description: Target value for the selected operator. + type: string + type: array + required: + - operator + - attribute + - value + type: object ConfigCatCredentials: description: The definition of the `ConfigCatCredentials` object. oneOf: @@ -14190,6 +14613,14 @@ components: data: $ref: "#/components/schemas/ActionConnectionData" type: object + CreateAllocationsRequest: + description: Request to create targeting rules (allocations) for a feature flag in an environment. + properties: + data: + $ref: "#/components/schemas/AllocationDataRequest" + required: + - data + type: object CreateAppRequest: description: A request object for creating a new app. example: @@ -24613,6 +25044,78 @@ components: example: "One or several indexes are missing or invalid. Results hold data from the other indexes." type: string type: object + ExposureRolloutStepRequest: + description: Rollout step request payload. + properties: + exposure_ratio: + description: The exposure ratio for this step. + example: 0.5 + format: double + maximum: 1 + minimum: 0 + type: number + grouped_step_index: + description: Logical index grouping related steps. + example: 1 + format: int64 + minimum: 0 + type: integer + id: + description: The unique identifier of the progression step. + example: "550e8400-e29b-41d4-a716-446655440040" + format: uuid + type: string + interval_ms: + description: Step duration in milliseconds. + example: 3600000 + format: int64 + nullable: true + type: integer + is_pause_record: + description: Whether this step represents a pause record. + example: false + type: boolean + required: + - exposure_ratio + - is_pause_record + - grouped_step_index + type: object + ExposureScheduleRequest: + description: Progressive release request payload. + properties: + absolute_start_time: + description: The absolute UTC start time for this schedule. + example: "2025-06-13T12:00:00Z" + format: date-time + nullable: true + type: string + control_variant_id: + description: The control variant ID used for experiment comparisons. + example: "550e8400-e29b-41d4-a716-446655440012" + nullable: true + type: string + control_variant_key: + description: The control variant key used during creation workflows. + example: "control" + nullable: true + type: string + id: + description: The unique identifier of the progressive rollout. + example: "550e8400-e29b-41d4-a716-446655440010" + format: uuid + type: string + rollout_options: + $ref: "#/components/schemas/RolloutOptionsRequest" + rollout_steps: + description: Ordered progression steps for exposure. + items: + $ref: "#/components/schemas/ExposureRolloutStepRequest" + minItems: 1 + type: array + required: + - rollout_options + - rollout_steps + type: object FacetInfoRequest: description: Request body for retrieving facet value information for a specified attribute with optional filtering. example: @@ -25109,6 +25612,12 @@ components: description: Indicates whether this feature flag requires approval for changes. example: false type: boolean + tags: + description: Tags associated with the feature flag. + example: [] + items: + type: string + type: array updated_at: description: The timestamp when the feature flag was last updated. example: "2023-01-01T00:00:00Z" @@ -25154,6 +25663,14 @@ components: description: The name of the environment. example: "env-search-term" type: string + environment_queries: + description: Queries that target this environment. + example: + - "test-feature-flag" + - "env-search-term" + items: + type: string + type: array is_production: description: Indicates whether the environment is production. example: false @@ -29346,6 +29863,47 @@ components: example: "env:production" type: string type: array + GuardrailMetric: + description: Guardrail metric details. + properties: + metric_id: + description: The metric ID to monitor. + example: "metric-error-rate" + type: string + trigger_action: + $ref: "#/components/schemas/GuardrailTriggerAction" + triggered_by: + description: The signal or system that triggered the action. + example: "guardrail_monitor" + nullable: true + type: string + required: + - metric_id + - trigger_action + type: object + GuardrailMetricRequest: + description: Guardrail metric request payload. + properties: + metric_id: + description: The metric ID to monitor. + example: "metric-error-rate" + type: string + trigger_action: + $ref: "#/components/schemas/GuardrailTriggerAction" + required: + - metric_id + - trigger_action + type: object + GuardrailTriggerAction: + description: Action to perform when a guardrail threshold is triggered. + enum: + - PAUSE + - ABORT + example: "PAUSE" + type: string + x-enum-varnames: + - PAUSE + - ABORT HTTPBody: description: The definition of `HTTPBody` object. properties: @@ -36653,6 +37211,18 @@ components: format: int64 type: integer type: object + ListAllocationsResponse: + description: Response containing a list of targeting rules (allocations). + properties: + data: + description: List of targeting rules (allocations). + items: + $ref: "#/components/schemas/AllocationDataResponse" + description: Allocation item. + type: array + required: + - data + type: object ListAppKeyRegistrationsResponse: description: A paginated list of app key registrations. properties: @@ -47881,6 +48451,17 @@ components: - ARRAY_NUMBER - ARRAY_BOOLEAN - ARRAY_OBJECT + OverwriteAllocationsRequest: + description: Request to overwrite targeting rules (allocations) for a feature flag in an environment. + properties: + data: + description: Targeting rules (allocations) to replace existing ones with. + items: + $ref: "#/components/schemas/AllocationDataRequest" + type: array + required: + - data + type: object PageUrgency: default: high description: On-Call Page urgency level. @@ -53648,6 +54229,53 @@ components: type: string x-enum-varnames: - ROLES + RolloutOptions: + description: Applied progression options for a progressive rollout. + properties: + autostart: + description: Whether the schedule starts automatically. + example: false + type: boolean + selection_interval_ms: + description: Interval in milliseconds for uniform interval strategies. + example: 3600000 + format: int64 + type: integer + strategy: + $ref: "#/components/schemas/RolloutStrategy" + required: + - strategy + - autostart + - selection_interval_ms + type: object + RolloutOptionsRequest: + description: Rollout options request payload. + properties: + autostart: + description: Whether the schedule should begin automatically. + example: false + nullable: true + type: boolean + selection_interval_ms: + description: Interval in milliseconds for uniform interval strategies. + example: 3600000 + format: int64 + type: integer + strategy: + $ref: "#/components/schemas/RolloutStrategy" + required: + - strategy + type: object + RolloutStrategy: + description: The progression strategy used by a progressive rollout. + enum: + - UNIFORM_INTERVALS + - NO_ROLLOUT + example: "UNIFORM_INTERVALS" + type: string + x-enum-varnames: + - UNIFORM_INTERVALS + - NO_ROLLOUT RoutingRule: description: Represents a routing rule, including its attributes, relationships, and unique identifier. properties: @@ -67088,6 +67716,47 @@ components: description: Tag associated with your event. type: string type: array + TargetingRule: + description: Targeting rule details. + properties: + conditions: + description: Conditions evaluated by this targeting rule. + items: + $ref: "#/components/schemas/Condition" + type: array + created_at: + description: The timestamp when the targeting rule was created. + example: "2024-01-01T12:00:00Z" + format: date-time + type: string + id: + description: The unique identifier of the targeting rule. + example: "550e8400-e29b-41d4-a716-446655440060" + format: uuid + type: string + updated_at: + description: The timestamp when the targeting rule was last updated. + example: "2024-01-01T12:00:00Z" + format: date-time + type: string + required: + - id + - conditions + - created_at + - updated_at + type: object + TargetingRuleRequest: + description: Targeting rule request payload. + properties: + conditions: + description: Conditions that must match for this rule. + items: + $ref: "#/components/schemas/ConditionRequest" + minItems: 1 + type: array + required: + - conditions + type: object Targets: description: |- List of recipients to notify when a notification rule is triggered. Many different target types are supported, @@ -71274,6 +71943,51 @@ components: data: $ref: "#/components/schemas/WorkflowDataUpdate" type: object + UpsertAllocationRequest: + description: Request to create or update a targeting rule (allocation) for a feature flag environment. + properties: + experiment_id: + description: The experiment ID for experiment-linked allocations. + example: "550e8400-e29b-41d4-a716-446655440030" + nullable: true + type: string + exposure_schedule: + $ref: "#/components/schemas/ExposureScheduleRequest" + guardrail_metrics: + description: Guardrail metrics used to monitor and auto-pause or abort. + items: + $ref: "#/components/schemas/GuardrailMetricRequest" + type: array + id: + description: The unique identifier of the targeting rule allocation. + example: "550e8400-e29b-41d4-a716-446655440020" + format: uuid + type: string + key: + description: The unique key of the targeting rule allocation. + example: "prod-rollout" + type: string + name: + description: The display name of the targeting rule. + example: "Production Rollout" + type: string + targeting_rules: + description: Targeting rules that determine audience eligibility. + items: + $ref: "#/components/schemas/TargetingRuleRequest" + type: array + type: + $ref: "#/components/schemas/AllocationType" + variant_weights: + description: Variant distribution weights. + items: + $ref: "#/components/schemas/VariantWeightRequest" + type: array + required: + - name + - key + - type + type: object UpsertCatalogEntityRequest: description: Create or update entity request. oneOf: @@ -72168,6 +72882,60 @@ components: - name - value type: object + VariantWeight: + description: Variant weight details. + properties: + created_at: + description: The timestamp when the variant weight was created. + example: "2024-01-01T12:00:00Z" + format: date-time + type: string + id: + description: Unique identifier of the variant weight assignment. + example: "59061199-e2ff-46e9-8b40-2193e3b21687" + format: uuid + type: string + updated_at: + description: The timestamp when the variant weight was last updated. + example: "2024-01-01T12:00:00Z" + format: date-time + type: string + value: + description: The percentage weight for the variant. + example: 50 + format: double + type: number + variant: + $ref: "#/components/schemas/Variant" + variant_id: + description: The variant ID. + example: "550e8400-e29b-41d4-a716-446655440001" + format: uuid + type: string + required: + - variant_id + - value + type: object + VariantWeightRequest: + description: Variant weight request payload. + properties: + value: + description: The percentage weight for this variant. + example: 50 + format: double + type: number + variant_id: + description: The variant ID to assign weight to. + example: "550e8400-e29b-41d4-a716-446655440001" + format: uuid + type: string + variant_key: + description: The variant key to assign weight to. + example: "control" + type: string + required: + - value + type: object Version: description: Version of the notification rule. It is updated when the rule is modified. example: 1 @@ -84899,6 +85667,270 @@ paths: operator: AND permissions: - feature_flag_environment_config_write + /api/v2/feature-flags/exposure-schedules/{exposure_schedule_id}/pause: + post: + description: |- + Pauses a progressive rollout while preserving rollout state. + operationId: PauseExposureSchedule + parameters: + - $ref: "#/components/parameters/exposure_schedule_id" + responses: + "200": + content: + application/json: + examples: + default: + value: + absolute_start_time: "2025-06-13T12:00:00Z" + allocation_id: "550e8400-e29b-41d4-a716-446655440020" + control_variant_id: "550e8400-e29b-41d4-a716-446655440012" + created_at: "2024-01-01T12:00:00Z" + guardrail_triggered_action: + guardrail_triggers: [] + id: "550e8400-e29b-41d4-a716-446655440010" + rollout_options: + autostart: false + selection_interval_ms: 3600000 + strategy: "UNIFORM_INTERVALS" + rollout_steps: [] + updated_at: "2024-01-01T12:00:00Z" + schema: + $ref: "#/components/schemas/AllocationExposureScheduleResponse" + description: OK + "400": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Bad Request + "403": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Forbidden + "404": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Not Found + "409": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Conflict + "429": + $ref: "#/components/responses/TooManyRequestsResponse" + security: + - apiKeyAuth: [] + appKeyAuth: [] + summary: Pause a progressive rollout + tags: + - Feature Flags + x-permission: + operator: AND + permissions: + - feature_flag_config_write + /api/v2/feature-flags/exposure-schedules/{exposure_schedule_id}/resume: + post: + description: |- + Resumes progression for a previously paused progressive rollout. + operationId: ResumeExposureSchedule + parameters: + - $ref: "#/components/parameters/exposure_schedule_id" + responses: + "200": + content: + application/json: + examples: + default: + value: + absolute_start_time: "2025-06-13T12:00:00Z" + allocation_id: "550e8400-e29b-41d4-a716-446655440020" + control_variant_id: "550e8400-e29b-41d4-a716-446655440012" + created_at: "2024-01-01T12:00:00Z" + guardrail_triggered_action: + guardrail_triggers: [] + id: "550e8400-e29b-41d4-a716-446655440010" + rollout_options: + autostart: false + selection_interval_ms: 3600000 + strategy: "UNIFORM_INTERVALS" + rollout_steps: [] + updated_at: "2024-01-01T12:00:00Z" + schema: + $ref: "#/components/schemas/AllocationExposureScheduleResponse" + description: OK + "400": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Bad Request + "403": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Forbidden + "404": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Not Found + "409": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Conflict + "429": + $ref: "#/components/responses/TooManyRequestsResponse" + security: + - apiKeyAuth: [] + appKeyAuth: [] + summary: Resume a progressive rollout + tags: + - Feature Flags + x-permission: + operator: AND + permissions: + - feature_flag_config_write + /api/v2/feature-flags/exposure-schedules/{exposure_schedule_id}/start: + post: + description: |- + Starts a progressive rollout and begins progression. + operationId: StartExposureSchedule + parameters: + - $ref: "#/components/parameters/exposure_schedule_id" + responses: + "200": + content: + application/json: + examples: + default: + value: + absolute_start_time: "2025-06-13T12:00:00Z" + allocation_id: "550e8400-e29b-41d4-a716-446655440020" + control_variant_id: "550e8400-e29b-41d4-a716-446655440012" + created_at: "2024-01-01T12:00:00Z" + guardrail_triggered_action: + guardrail_triggers: [] + id: "550e8400-e29b-41d4-a716-446655440010" + rollout_options: + autostart: false + selection_interval_ms: 3600000 + strategy: "UNIFORM_INTERVALS" + rollout_steps: [] + updated_at: "2024-01-01T12:00:00Z" + schema: + $ref: "#/components/schemas/AllocationExposureScheduleResponse" + description: OK + "400": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Bad Request + "403": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Forbidden + "404": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Not Found + "409": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Conflict + "429": + $ref: "#/components/responses/TooManyRequestsResponse" + security: + - apiKeyAuth: [] + appKeyAuth: [] + summary: Start a progressive rollout + tags: + - Feature Flags + x-permission: + operator: AND + permissions: + - feature_flag_config_write + /api/v2/feature-flags/exposure-schedules/{exposure_schedule_id}/stop: + post: + description: |- + Stops a progressive rollout and marks it as aborted. + operationId: StopExposureSchedule + parameters: + - $ref: "#/components/parameters/exposure_schedule_id" + responses: + "200": + content: + application/json: + examples: + default: + value: + absolute_start_time: "2025-06-13T12:00:00Z" + allocation_id: "550e8400-e29b-41d4-a716-446655440020" + control_variant_id: "550e8400-e29b-41d4-a716-446655440012" + created_at: "2024-01-01T12:00:00Z" + guardrail_triggered_action: + guardrail_triggers: [] + id: "550e8400-e29b-41d4-a716-446655440010" + rollout_options: + autostart: false + selection_interval_ms: 3600000 + strategy: "UNIFORM_INTERVALS" + rollout_steps: [] + updated_at: "2024-01-01T12:00:00Z" + schema: + $ref: "#/components/schemas/AllocationExposureScheduleResponse" + description: OK + "400": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Bad Request + "403": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Forbidden + "404": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Not Found + "409": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Conflict + "429": + $ref: "#/components/responses/TooManyRequestsResponse" + security: + - apiKeyAuth: [] + appKeyAuth: [] + summary: Stop a progressive rollout + tags: + - Feature Flags + x-permission: + operator: AND + permissions: + - feature_flag_config_write /api/v2/feature-flags/{feature_flag_id}: get: description: |- @@ -85042,6 +86074,198 @@ paths: permissions: - feature_flag_config_write - feature_flag_environment_config_read + /api/v2/feature-flags/{feature_flag_id}/environments/{environment_id}/allocations: + post: + description: |- + Creates a new targeting rule (allocation) for a specific feature flag in a specific environment. + operationId: CreateAllocationsForFeatureFlagInEnvironment + parameters: + - $ref: "#/components/parameters/feature_flag_id" + - $ref: "#/components/parameters/environment_id" + requestBody: + content: + application/json: + example: + data: + attributes: + key: "prod-rollout" + name: "Production Rollout" + type: "FEATURE_GATE" + variant_weights: + - value: 50 + variant_id: "550e8400-e29b-41d4-a716-446655440001" + - value: 50 + variant_id: "550e8400-e29b-41d4-a716-446655440002" + type: "allocations" + schema: + $ref: "#/components/schemas/CreateAllocationsRequest" + required: true + responses: + "201": + content: + application/json: + examples: + default: + value: + data: + attributes: + created_at: "2024-01-01T12:00:00Z" + environment_ids: + - "550e8400-e29b-41d4-a716-446655440001" + guardrail_metrics: [] + id: "550e8400-e29b-41d4-a716-446655440020" + key: "prod-rollout" + name: "Production Rollout" + order_position: 0 + targeting_rules: [] + type: "FEATURE_GATE" + updated_at: "2024-01-01T12:00:00Z" + variant_weights: + - value: 50 + variant_id: "550e8400-e29b-41d4-a716-446655440001" + id: "550e8400-e29b-41d4-a716-446655440020" + type: "allocations" + schema: + $ref: "#/components/schemas/AllocationResponse" + description: Created + "202": + content: + application/json: + schema: + $ref: "#/components/schemas/AllocationResponse" + description: Accepted - Approval required for this change + "400": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Bad Request + "403": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Forbidden + "404": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Not Found + "409": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Conflict + "429": + $ref: "#/components/responses/TooManyRequestsResponse" + security: + - apiKeyAuth: [] + appKeyAuth: [] + summary: Create targeting rules for a flag env + tags: + - Feature Flags + x-permission: + operator: AND + permissions: + - feature_flag_config_write + put: + description: |- + Updates targeting rules (allocations) for a specific feature flag in a specific environment. + This operation replaces the existing allocation set with the request payload. + operationId: UpdateAllocationsForFeatureFlagInEnvironment + parameters: + - $ref: "#/components/parameters/feature_flag_id" + - $ref: "#/components/parameters/environment_id" + requestBody: + content: + application/json: + example: + data: + - attributes: + key: "prod-rollout" + name: "Production Rollout" + type: "FEATURE_GATE" + variant_weights: + - value: 50 + variant_id: "550e8400-e29b-41d4-a716-446655440001" + - value: 50 + variant_id: "550e8400-e29b-41d4-a716-446655440002" + type: "allocations" + schema: + $ref: "#/components/schemas/OverwriteAllocationsRequest" + required: true + responses: + "200": + content: + application/json: + examples: + default: + value: + data: + - attributes: + created_at: "2024-01-01T12:00:00Z" + environment_ids: + - "550e8400-e29b-41d4-a716-446655440001" + guardrail_metrics: [] + id: "550e8400-e29b-41d4-a716-446655440020" + key: "prod-rollout" + name: "Production Rollout" + order_position: 0 + targeting_rules: [] + type: "FEATURE_GATE" + updated_at: "2024-01-01T12:00:00Z" + variant_weights: + - value: 50 + variant_id: "550e8400-e29b-41d4-a716-446655440001" + id: "550e8400-e29b-41d4-a716-446655440020" + type: "allocations" + schema: + $ref: "#/components/schemas/ListAllocationsResponse" + description: OK + "202": + content: + application/json: + schema: + $ref: "#/components/schemas/ListAllocationsResponse" + description: Accepted - Approval required for this change + "400": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Bad Request + "403": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Forbidden + "404": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Not Found + "409": + content: + application/json: + schema: + $ref: "#/components/schemas/APIErrorResponse" + description: Conflict + "429": + $ref: "#/components/responses/TooManyRequestsResponse" + security: + - apiKeyAuth: [] + appKeyAuth: [] + summary: Update targeting rules for a flag + tags: + - Feature Flags + x-permission: + operator: AND + permissions: + - feature_flag_config_write /api/v2/feature-flags/{feature_flag_id}/environments/{environment_id}/disable: post: description: |- diff --git a/docs/datadog_api_client.v2.model.rst b/docs/datadog_api_client.v2.model.rst index 3325139a68..d1dc990342 100644 --- a/docs/datadog_api_client.v2.model.rst +++ b/docs/datadog_api_client.v2.model.rst @@ -298,6 +298,90 @@ datadog\_api\_client.v2.model.alert\_event\_custom\_attributes\_status module :members: :show-inheritance: +datadog\_api\_client.v2.model.allocation module +----------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.allocation + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.allocation\_data\_request module +-------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.allocation_data_request + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.allocation\_data\_response module +--------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.allocation_data_response + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.allocation\_data\_type module +----------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.allocation_data_type + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.allocation\_exposure\_guardrail\_trigger module +----------------------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.allocation_exposure_guardrail_trigger + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.allocation\_exposure\_rollout\_step module +------------------------------------------------------------------------ + +.. automodule:: datadog_api_client.v2.model.allocation_exposure_rollout_step + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.allocation\_exposure\_schedule module +------------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.allocation_exposure_schedule + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.allocation\_exposure\_schedule\_data module +------------------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.allocation_exposure_schedule_data + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.allocation\_exposure\_schedule\_data\_type module +------------------------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.allocation_exposure_schedule_data_type + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.allocation\_exposure\_schedule\_response module +----------------------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.allocation_exposure_schedule_response + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.allocation\_response module +--------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.allocation_response + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.allocation\_type module +----------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.allocation_type + :members: + :show-inheritance: + datadog\_api\_client.v2.model.annotation module ----------------------------------------------- @@ -5212,6 +5296,27 @@ datadog\_api\_client.v2.model.component\_type module :members: :show-inheritance: +datadog\_api\_client.v2.model.condition module +---------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.condition + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.condition\_operator module +-------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.condition_operator + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.condition\_request module +------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.condition_request + :members: + :show-inheritance: + datadog\_api\_client.v2.model.config\_cat\_credentials module ------------------------------------------------------------- @@ -5891,6 +5996,13 @@ datadog\_api\_client.v2.model.create\_action\_connection\_response module :members: :show-inheritance: +datadog\_api\_client.v2.model.create\_allocations\_request module +----------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.create_allocations_request + :members: + :show-inheritance: + datadog\_api\_client.v2.model.create\_app\_request module --------------------------------------------------------- @@ -10546,6 +10658,20 @@ datadog\_api\_client.v2.model.events\_warning module :members: :show-inheritance: +datadog\_api\_client.v2.model.exposure\_rollout\_step\_request module +--------------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.exposure_rollout_step_request + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.exposure\_schedule\_request module +---------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.exposure_schedule_request + :members: + :show-inheritance: + datadog\_api\_client.v2.model.facet\_info\_request module --------------------------------------------------------- @@ -12730,6 +12856,27 @@ datadog\_api\_client.v2.model.group\_tags module :members: :show-inheritance: +datadog\_api\_client.v2.model.guardrail\_metric module +------------------------------------------------------ + +.. automodule:: datadog_api_client.v2.model.guardrail_metric + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.guardrail\_metric\_request module +--------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.guardrail_metric_request + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.guardrail\_trigger\_action module +--------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.guardrail_trigger_action + :members: + :show-inheritance: + datadog\_api\_client.v2.model.hamr\_org\_connection\_attributes\_request module ------------------------------------------------------------------------------- @@ -15593,6 +15740,13 @@ datadog\_api\_client.v2.model.links module :members: :show-inheritance: +datadog\_api\_client.v2.model.list\_allocations\_response module +---------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.list_allocations_response + :members: + :show-inheritance: + datadog\_api\_client.v2.model.list\_apis\_response module --------------------------------------------------------- @@ -21501,6 +21655,13 @@ datadog\_api\_client.v2.model.output\_schema\_parameters\_type module :members: :show-inheritance: +datadog\_api\_client.v2.model.overwrite\_allocations\_request module +-------------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.overwrite_allocations_request + :members: + :show-inheritance: + datadog\_api\_client.v2.model.page\_urgency module -------------------------------------------------- @@ -24014,6 +24175,27 @@ datadog\_api\_client.v2.model.roles\_type module :members: :show-inheritance: +datadog\_api\_client.v2.model.rollout\_options module +----------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.rollout_options + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.rollout\_options\_request module +-------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.rollout_options_request + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.rollout\_strategy module +------------------------------------------------------ + +.. automodule:: datadog_api_client.v2.model.rollout_strategy + :members: + :show-inheritance: + datadog\_api\_client.v2.model.routing\_rule module -------------------------------------------------- @@ -30342,6 +30524,20 @@ datadog\_api\_client.v2.model.tags\_event\_attribute module :members: :show-inheritance: +datadog\_api\_client.v2.model.targeting\_rule module +---------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.targeting_rule + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.targeting\_rule\_request module +------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.targeting_rule_request + :members: + :show-inheritance: + datadog\_api\_client.v2.model.team module ----------------------------------------- @@ -32330,6 +32526,13 @@ datadog\_api\_client.v2.model.update\_workflow\_response module :members: :show-inheritance: +datadog\_api\_client.v2.model.upsert\_allocation\_request module +---------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.upsert_allocation_request + :members: + :show-inheritance: + datadog\_api\_client.v2.model.upsert\_catalog\_entity\_request module --------------------------------------------------------------------- @@ -32841,6 +33044,20 @@ datadog\_api\_client.v2.model.variant module :members: :show-inheritance: +datadog\_api\_client.v2.model.variant\_weight module +---------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.variant_weight + :members: + :show-inheritance: + +datadog\_api\_client.v2.model.variant\_weight\_request module +------------------------------------------------------------- + +.. automodule:: datadog_api_client.v2.model.variant_weight_request + :members: + :show-inheritance: + datadog\_api\_client.v2.model.version\_history\_update module ------------------------------------------------------------- diff --git a/examples/v2/feature-flags/CreateAllocationsForFeatureFlagInEnvironment.py b/examples/v2/feature-flags/CreateAllocationsForFeatureFlagInEnvironment.py new file mode 100644 index 0000000000..0439653296 --- /dev/null +++ b/examples/v2/feature-flags/CreateAllocationsForFeatureFlagInEnvironment.py @@ -0,0 +1,95 @@ +""" +Create targeting rules for a flag env returns "Created" response +""" + +from datadog_api_client import ApiClient, Configuration +from datadog_api_client.v2.api.feature_flags_api import FeatureFlagsApi +from datadog_api_client.v2.model.allocation_data_request import AllocationDataRequest +from datadog_api_client.v2.model.allocation_data_type import AllocationDataType +from datadog_api_client.v2.model.allocation_type import AllocationType +from datadog_api_client.v2.model.condition_operator import ConditionOperator +from datadog_api_client.v2.model.condition_request import ConditionRequest +from datadog_api_client.v2.model.create_allocations_request import CreateAllocationsRequest +from datadog_api_client.v2.model.exposure_rollout_step_request import ExposureRolloutStepRequest +from datadog_api_client.v2.model.exposure_schedule_request import ExposureScheduleRequest +from datadog_api_client.v2.model.guardrail_metric_request import GuardrailMetricRequest +from datadog_api_client.v2.model.guardrail_trigger_action import GuardrailTriggerAction +from datadog_api_client.v2.model.rollout_options_request import RolloutOptionsRequest +from datadog_api_client.v2.model.rollout_strategy import RolloutStrategy +from datadog_api_client.v2.model.targeting_rule_request import TargetingRuleRequest +from datadog_api_client.v2.model.upsert_allocation_request import UpsertAllocationRequest +from datadog_api_client.v2.model.variant_weight_request import VariantWeightRequest +from datetime import datetime +from dateutil.tz import tzutc +from uuid import UUID + +body = CreateAllocationsRequest( + data=AllocationDataRequest( + attributes=UpsertAllocationRequest( + experiment_id="550e8400-e29b-41d4-a716-446655440030", + exposure_schedule=ExposureScheduleRequest( + absolute_start_time=datetime(2025, 6, 13, 12, 0, tzinfo=tzutc()), + control_variant_id="550e8400-e29b-41d4-a716-446655440012", + control_variant_key="control", + id=UUID("550e8400-e29b-41d4-a716-446655440010"), + rollout_options=RolloutOptionsRequest( + autostart=False, + selection_interval_ms=3600000, + strategy=RolloutStrategy.UNIFORM_INTERVALS, + ), + rollout_steps=[ + ExposureRolloutStepRequest( + exposure_ratio=0.5, + grouped_step_index=1, + id=UUID("550e8400-e29b-41d4-a716-446655440040"), + interval_ms=3600000, + is_pause_record=False, + ), + ], + ), + guardrail_metrics=[ + GuardrailMetricRequest( + metric_id="metric-error-rate", + trigger_action=GuardrailTriggerAction.PAUSE, + ), + ], + id=UUID("550e8400-e29b-41d4-a716-446655440020"), + key="prod-rollout", + name="Production Rollout", + targeting_rules=[ + TargetingRuleRequest( + conditions=[ + ConditionRequest( + attribute="user_tier", + operator=ConditionOperator.ONE_OF, + value=[ + "premium", + "enterprise", + ], + ), + ], + ), + ], + type=AllocationType.FEATURE_GATE, + variant_weights=[ + VariantWeightRequest( + value=50.0, + variant_id=UUID("550e8400-e29b-41d4-a716-446655440001"), + variant_key="control", + ), + ], + ), + type=AllocationDataType.ALLOCATIONS, + ), +) + +configuration = Configuration() +with ApiClient(configuration) as api_client: + api_instance = FeatureFlagsApi(api_client) + response = api_instance.create_allocations_for_feature_flag_in_environment( + feature_flag_id=UUID("550e8400-e29b-41d4-a716-446655440000"), + environment_id=UUID("550e8400-e29b-41d4-a716-446655440001"), + body=body, + ) + + print(response) diff --git a/examples/v2/feature-flags/CreateAllocationsForFeatureFlagInEnvironment_3662093014.py b/examples/v2/feature-flags/CreateAllocationsForFeatureFlagInEnvironment_3662093014.py new file mode 100644 index 0000000000..f593195f15 --- /dev/null +++ b/examples/v2/feature-flags/CreateAllocationsForFeatureFlagInEnvironment_3662093014.py @@ -0,0 +1,48 @@ +""" +Create allocation for a flag in an environment returns "Created" response +""" + +from os import environ +from datadog_api_client import ApiClient, Configuration +from datadog_api_client.v2.api.feature_flags_api import FeatureFlagsApi +from datadog_api_client.v2.model.allocation_data_request import AllocationDataRequest +from datadog_api_client.v2.model.allocation_data_type import AllocationDataType +from datadog_api_client.v2.model.allocation_type import AllocationType +from datadog_api_client.v2.model.create_allocations_request import CreateAllocationsRequest +from datadog_api_client.v2.model.upsert_allocation_request import UpsertAllocationRequest +from datadog_api_client.v2.model.variant_weight_request import VariantWeightRequest + +# there is a valid "feature_flag" in the system +FEATURE_FLAG_DATA_ATTRIBUTES_VARIANTS_0_ID = environ["FEATURE_FLAG_DATA_ATTRIBUTES_VARIANTS_0_ID"] +FEATURE_FLAG_DATA_ID = environ["FEATURE_FLAG_DATA_ID"] + +# there is a valid "environment" in the system +ENVIRONMENT_DATA_ID = environ["ENVIRONMENT_DATA_ID"] + +body = CreateAllocationsRequest( + data=AllocationDataRequest( + type=AllocationDataType.ALLOCATIONS, + attributes=UpsertAllocationRequest( + name="New targeting rule Example-Feature-Flag", + key="new-targeting-rule-example-feature-flag", + targeting_rules=[], + variant_weights=[ + VariantWeightRequest( + variant_id=FEATURE_FLAG_DATA_ATTRIBUTES_VARIANTS_0_ID, + value=100.0, + ), + ], + guardrail_metrics=[], + type=AllocationType.CANARY, + ), + ), +) + +configuration = Configuration() +with ApiClient(configuration) as api_client: + api_instance = FeatureFlagsApi(api_client) + response = api_instance.create_allocations_for_feature_flag_in_environment( + feature_flag_id=FEATURE_FLAG_DATA_ID, environment_id=ENVIRONMENT_DATA_ID, body=body + ) + + print(response) diff --git a/examples/v2/feature-flags/PauseExposureSchedule.py b/examples/v2/feature-flags/PauseExposureSchedule.py new file mode 100644 index 0000000000..92064a39d8 --- /dev/null +++ b/examples/v2/feature-flags/PauseExposureSchedule.py @@ -0,0 +1,16 @@ +""" +Pause a progressive rollout returns "OK" response +""" + +from datadog_api_client import ApiClient, Configuration +from datadog_api_client.v2.api.feature_flags_api import FeatureFlagsApi +from uuid import UUID + +configuration = Configuration() +with ApiClient(configuration) as api_client: + api_instance = FeatureFlagsApi(api_client) + response = api_instance.pause_exposure_schedule( + exposure_schedule_id=UUID("550e8400-e29b-41d4-a716-446655440010"), + ) + + print(response) diff --git a/examples/v2/feature-flags/ResumeExposureSchedule.py b/examples/v2/feature-flags/ResumeExposureSchedule.py new file mode 100644 index 0000000000..e062abefb7 --- /dev/null +++ b/examples/v2/feature-flags/ResumeExposureSchedule.py @@ -0,0 +1,16 @@ +""" +Resume a progressive rollout returns "OK" response +""" + +from datadog_api_client import ApiClient, Configuration +from datadog_api_client.v2.api.feature_flags_api import FeatureFlagsApi +from uuid import UUID + +configuration = Configuration() +with ApiClient(configuration) as api_client: + api_instance = FeatureFlagsApi(api_client) + response = api_instance.resume_exposure_schedule( + exposure_schedule_id=UUID("550e8400-e29b-41d4-a716-446655440010"), + ) + + print(response) diff --git a/examples/v2/feature-flags/StartExposureSchedule.py b/examples/v2/feature-flags/StartExposureSchedule.py new file mode 100644 index 0000000000..2c2cc0af49 --- /dev/null +++ b/examples/v2/feature-flags/StartExposureSchedule.py @@ -0,0 +1,16 @@ +""" +Start a progressive rollout returns "OK" response +""" + +from datadog_api_client import ApiClient, Configuration +from datadog_api_client.v2.api.feature_flags_api import FeatureFlagsApi +from uuid import UUID + +configuration = Configuration() +with ApiClient(configuration) as api_client: + api_instance = FeatureFlagsApi(api_client) + response = api_instance.start_exposure_schedule( + exposure_schedule_id=UUID("550e8400-e29b-41d4-a716-446655440010"), + ) + + print(response) diff --git a/examples/v2/feature-flags/StopExposureSchedule.py b/examples/v2/feature-flags/StopExposureSchedule.py new file mode 100644 index 0000000000..8d255f91dd --- /dev/null +++ b/examples/v2/feature-flags/StopExposureSchedule.py @@ -0,0 +1,16 @@ +""" +Stop a progressive rollout returns "OK" response +""" + +from datadog_api_client import ApiClient, Configuration +from datadog_api_client.v2.api.feature_flags_api import FeatureFlagsApi +from uuid import UUID + +configuration = Configuration() +with ApiClient(configuration) as api_client: + api_instance = FeatureFlagsApi(api_client) + response = api_instance.stop_exposure_schedule( + exposure_schedule_id=UUID("550e8400-e29b-41d4-a716-446655440010"), + ) + + print(response) diff --git a/examples/v2/feature-flags/UpdateAllocationsForFeatureFlagInEnvironment.py b/examples/v2/feature-flags/UpdateAllocationsForFeatureFlagInEnvironment.py new file mode 100644 index 0000000000..2675d19564 --- /dev/null +++ b/examples/v2/feature-flags/UpdateAllocationsForFeatureFlagInEnvironment.py @@ -0,0 +1,97 @@ +""" +Update targeting rules for a flag returns "OK" response +""" + +from datadog_api_client import ApiClient, Configuration +from datadog_api_client.v2.api.feature_flags_api import FeatureFlagsApi +from datadog_api_client.v2.model.allocation_data_request import AllocationDataRequest +from datadog_api_client.v2.model.allocation_data_type import AllocationDataType +from datadog_api_client.v2.model.allocation_type import AllocationType +from datadog_api_client.v2.model.condition_operator import ConditionOperator +from datadog_api_client.v2.model.condition_request import ConditionRequest +from datadog_api_client.v2.model.exposure_rollout_step_request import ExposureRolloutStepRequest +from datadog_api_client.v2.model.exposure_schedule_request import ExposureScheduleRequest +from datadog_api_client.v2.model.guardrail_metric_request import GuardrailMetricRequest +from datadog_api_client.v2.model.guardrail_trigger_action import GuardrailTriggerAction +from datadog_api_client.v2.model.overwrite_allocations_request import OverwriteAllocationsRequest +from datadog_api_client.v2.model.rollout_options_request import RolloutOptionsRequest +from datadog_api_client.v2.model.rollout_strategy import RolloutStrategy +from datadog_api_client.v2.model.targeting_rule_request import TargetingRuleRequest +from datadog_api_client.v2.model.upsert_allocation_request import UpsertAllocationRequest +from datadog_api_client.v2.model.variant_weight_request import VariantWeightRequest +from datetime import datetime +from dateutil.tz import tzutc +from uuid import UUID + +body = OverwriteAllocationsRequest( + data=[ + AllocationDataRequest( + attributes=UpsertAllocationRequest( + experiment_id="550e8400-e29b-41d4-a716-446655440030", + exposure_schedule=ExposureScheduleRequest( + absolute_start_time=datetime(2025, 6, 13, 12, 0, tzinfo=tzutc()), + control_variant_id="550e8400-e29b-41d4-a716-446655440012", + control_variant_key="control", + id=UUID("550e8400-e29b-41d4-a716-446655440010"), + rollout_options=RolloutOptionsRequest( + autostart=False, + selection_interval_ms=3600000, + strategy=RolloutStrategy.UNIFORM_INTERVALS, + ), + rollout_steps=[ + ExposureRolloutStepRequest( + exposure_ratio=0.5, + grouped_step_index=1, + id=UUID("550e8400-e29b-41d4-a716-446655440040"), + interval_ms=3600000, + is_pause_record=False, + ), + ], + ), + guardrail_metrics=[ + GuardrailMetricRequest( + metric_id="metric-error-rate", + trigger_action=GuardrailTriggerAction.PAUSE, + ), + ], + id=UUID("550e8400-e29b-41d4-a716-446655440020"), + key="prod-rollout", + name="Production Rollout", + targeting_rules=[ + TargetingRuleRequest( + conditions=[ + ConditionRequest( + attribute="user_tier", + operator=ConditionOperator.ONE_OF, + value=[ + "premium", + "enterprise", + ], + ), + ], + ), + ], + type=AllocationType.FEATURE_GATE, + variant_weights=[ + VariantWeightRequest( + value=50.0, + variant_id=UUID("550e8400-e29b-41d4-a716-446655440001"), + variant_key="control", + ), + ], + ), + type=AllocationDataType.ALLOCATIONS, + ), + ], +) + +configuration = Configuration() +with ApiClient(configuration) as api_client: + api_instance = FeatureFlagsApi(api_client) + response = api_instance.update_allocations_for_feature_flag_in_environment( + feature_flag_id=UUID("550e8400-e29b-41d4-a716-446655440000"), + environment_id=UUID("550e8400-e29b-41d4-a716-446655440001"), + body=body, + ) + + print(response) diff --git a/examples/v2/feature-flags/UpdateAllocationsForFeatureFlagInEnvironment_3789036209.py b/examples/v2/feature-flags/UpdateAllocationsForFeatureFlagInEnvironment_3789036209.py new file mode 100644 index 0000000000..8382c5a5db --- /dev/null +++ b/examples/v2/feature-flags/UpdateAllocationsForFeatureFlagInEnvironment_3789036209.py @@ -0,0 +1,81 @@ +""" +Update targeting rules for a flag in an environment returns "OK" response +""" + +from os import environ +from datadog_api_client import ApiClient, Configuration +from datadog_api_client.v2.api.feature_flags_api import FeatureFlagsApi +from datadog_api_client.v2.model.allocation_data_request import AllocationDataRequest +from datadog_api_client.v2.model.allocation_data_type import AllocationDataType +from datadog_api_client.v2.model.allocation_type import AllocationType +from datadog_api_client.v2.model.exposure_rollout_step_request import ExposureRolloutStepRequest +from datadog_api_client.v2.model.exposure_schedule_request import ExposureScheduleRequest +from datadog_api_client.v2.model.overwrite_allocations_request import OverwriteAllocationsRequest +from datadog_api_client.v2.model.rollout_options_request import RolloutOptionsRequest +from datadog_api_client.v2.model.rollout_strategy import RolloutStrategy +from datadog_api_client.v2.model.upsert_allocation_request import UpsertAllocationRequest +from datadog_api_client.v2.model.variant_weight_request import VariantWeightRequest + +# there is a valid "feature_flag" in the system +FEATURE_FLAG_DATA_ATTRIBUTES_VARIANTS_0_ID = environ["FEATURE_FLAG_DATA_ATTRIBUTES_VARIANTS_0_ID"] +FEATURE_FLAG_DATA_ID = environ["FEATURE_FLAG_DATA_ID"] + +# there is a valid "environment" in the system +ENVIRONMENT_DATA_ID = environ["ENVIRONMENT_DATA_ID"] + +body = OverwriteAllocationsRequest( + data=[ + AllocationDataRequest( + type=AllocationDataType.ALLOCATIONS, + attributes=UpsertAllocationRequest( + key="overwrite-allocation-example-feature-flag", + name="New targeting rule Example-Feature-Flag", + targeting_rules=[], + variant_weights=[ + VariantWeightRequest( + variant_id=FEATURE_FLAG_DATA_ATTRIBUTES_VARIANTS_0_ID, + value=100.0, + ), + ], + exposure_schedule=ExposureScheduleRequest( + rollout_options=RolloutOptionsRequest( + strategy=RolloutStrategy.UNIFORM_INTERVALS, + autostart=False, + selection_interval_ms=86400000, + ), + rollout_steps=[ + ExposureRolloutStepRequest( + exposure_ratio=0.05, + interval_ms=None, + is_pause_record=False, + grouped_step_index=0, + ), + ExposureRolloutStepRequest( + exposure_ratio=0.25, + interval_ms=None, + is_pause_record=False, + grouped_step_index=1, + ), + ExposureRolloutStepRequest( + exposure_ratio=1.0, + interval_ms=None, + is_pause_record=False, + grouped_step_index=2, + ), + ], + ), + guardrail_metrics=[], + type=AllocationType.CANARY, + ), + ), + ], +) + +configuration = Configuration() +with ApiClient(configuration) as api_client: + api_instance = FeatureFlagsApi(api_client) + response = api_instance.update_allocations_for_feature_flag_in_environment( + feature_flag_id=FEATURE_FLAG_DATA_ID, environment_id=ENVIRONMENT_DATA_ID, body=body + ) + + print(response) diff --git a/src/datadog_api_client/v2/api/feature_flags_api.py b/src/datadog_api_client/v2/api/feature_flags_api.py index 333f5a9201..a51a2811e3 100644 --- a/src/datadog_api_client/v2/api/feature_flags_api.py +++ b/src/datadog_api_client/v2/api/feature_flags_api.py @@ -19,7 +19,12 @@ from datadog_api_client.v2.model.environment_response import EnvironmentResponse from datadog_api_client.v2.model.create_environment_request import CreateEnvironmentRequest from datadog_api_client.v2.model.update_environment_request import UpdateEnvironmentRequest +from datadog_api_client.v2.model.allocation_exposure_schedule_response import AllocationExposureScheduleResponse from datadog_api_client.v2.model.update_feature_flag_request import UpdateFeatureFlagRequest +from datadog_api_client.v2.model.allocation_response import AllocationResponse +from datadog_api_client.v2.model.create_allocations_request import CreateAllocationsRequest +from datadog_api_client.v2.model.list_allocations_response import ListAllocationsResponse +from datadog_api_client.v2.model.overwrite_allocations_request import OverwriteAllocationsRequest class FeatureFlagsApi: @@ -55,6 +60,38 @@ def __init__(self, api_client=None): api_client=api_client, ) + self._create_allocations_for_feature_flag_in_environment_endpoint = _Endpoint( + settings={ + "response_type": (AllocationResponse,), + "auth": ["apiKeyAuth", "appKeyAuth"], + "endpoint_path": "/api/v2/feature-flags/{feature_flag_id}/environments/{environment_id}/allocations", + "operation_id": "create_allocations_for_feature_flag_in_environment", + "http_method": "POST", + "version": "v2", + }, + params_map={ + "feature_flag_id": { + "required": True, + "openapi_types": (UUID,), + "attribute": "feature_flag_id", + "location": "path", + }, + "environment_id": { + "required": True, + "openapi_types": (UUID,), + "attribute": "environment_id", + "location": "path", + }, + "body": { + "required": True, + "openapi_types": (CreateAllocationsRequest,), + "location": "body", + }, + }, + headers_map={"accept": ["application/json"], "content_type": ["application/json"]}, + api_client=api_client, + ) + self._create_feature_flag_endpoint = _Endpoint( settings={ "response_type": (FeatureFlagResponse,), @@ -310,6 +347,98 @@ def __init__(self, api_client=None): api_client=api_client, ) + self._pause_exposure_schedule_endpoint = _Endpoint( + settings={ + "response_type": (AllocationExposureScheduleResponse,), + "auth": ["apiKeyAuth", "appKeyAuth"], + "endpoint_path": "/api/v2/feature-flags/exposure-schedules/{exposure_schedule_id}/pause", + "operation_id": "pause_exposure_schedule", + "http_method": "POST", + "version": "v2", + }, + params_map={ + "exposure_schedule_id": { + "required": True, + "openapi_types": (UUID,), + "attribute": "exposure_schedule_id", + "location": "path", + }, + }, + headers_map={ + "accept": ["application/json"], + }, + api_client=api_client, + ) + + self._resume_exposure_schedule_endpoint = _Endpoint( + settings={ + "response_type": (AllocationExposureScheduleResponse,), + "auth": ["apiKeyAuth", "appKeyAuth"], + "endpoint_path": "/api/v2/feature-flags/exposure-schedules/{exposure_schedule_id}/resume", + "operation_id": "resume_exposure_schedule", + "http_method": "POST", + "version": "v2", + }, + params_map={ + "exposure_schedule_id": { + "required": True, + "openapi_types": (UUID,), + "attribute": "exposure_schedule_id", + "location": "path", + }, + }, + headers_map={ + "accept": ["application/json"], + }, + api_client=api_client, + ) + + self._start_exposure_schedule_endpoint = _Endpoint( + settings={ + "response_type": (AllocationExposureScheduleResponse,), + "auth": ["apiKeyAuth", "appKeyAuth"], + "endpoint_path": "/api/v2/feature-flags/exposure-schedules/{exposure_schedule_id}/start", + "operation_id": "start_exposure_schedule", + "http_method": "POST", + "version": "v2", + }, + params_map={ + "exposure_schedule_id": { + "required": True, + "openapi_types": (UUID,), + "attribute": "exposure_schedule_id", + "location": "path", + }, + }, + headers_map={ + "accept": ["application/json"], + }, + api_client=api_client, + ) + + self._stop_exposure_schedule_endpoint = _Endpoint( + settings={ + "response_type": (AllocationExposureScheduleResponse,), + "auth": ["apiKeyAuth", "appKeyAuth"], + "endpoint_path": "/api/v2/feature-flags/exposure-schedules/{exposure_schedule_id}/stop", + "operation_id": "stop_exposure_schedule", + "http_method": "POST", + "version": "v2", + }, + params_map={ + "exposure_schedule_id": { + "required": True, + "openapi_types": (UUID,), + "attribute": "exposure_schedule_id", + "location": "path", + }, + }, + headers_map={ + "accept": ["application/json"], + }, + api_client=api_client, + ) + self._unarchive_feature_flag_endpoint = _Endpoint( settings={ "response_type": (FeatureFlagResponse,), @@ -333,6 +462,38 @@ def __init__(self, api_client=None): api_client=api_client, ) + self._update_allocations_for_feature_flag_in_environment_endpoint = _Endpoint( + settings={ + "response_type": (ListAllocationsResponse,), + "auth": ["apiKeyAuth", "appKeyAuth"], + "endpoint_path": "/api/v2/feature-flags/{feature_flag_id}/environments/{environment_id}/allocations", + "operation_id": "update_allocations_for_feature_flag_in_environment", + "http_method": "PUT", + "version": "v2", + }, + params_map={ + "feature_flag_id": { + "required": True, + "openapi_types": (UUID,), + "attribute": "feature_flag_id", + "location": "path", + }, + "environment_id": { + "required": True, + "openapi_types": (UUID,), + "attribute": "environment_id", + "location": "path", + }, + "body": { + "required": True, + "openapi_types": (OverwriteAllocationsRequest,), + "location": "body", + }, + }, + headers_map={"accept": ["application/json"], "content_type": ["application/json"]}, + api_client=api_client, + ) + self._update_feature_flag_endpoint = _Endpoint( settings={ "response_type": (FeatureFlagResponse,), @@ -403,6 +564,32 @@ def archive_feature_flag( return self._archive_feature_flag_endpoint.call_with_http_info(**kwargs) + def create_allocations_for_feature_flag_in_environment( + self, + feature_flag_id: UUID, + environment_id: UUID, + body: CreateAllocationsRequest, + ) -> AllocationResponse: + """Create targeting rules for a flag env. + + Creates a new targeting rule (allocation) for a specific feature flag in a specific environment. + + :param feature_flag_id: The ID of the feature flag. + :type feature_flag_id: UUID + :param environment_id: The ID of the environment. + :type environment_id: UUID + :type body: CreateAllocationsRequest + :rtype: AllocationResponse + """ + kwargs: Dict[str, Any] = {} + kwargs["feature_flag_id"] = feature_flag_id + + kwargs["environment_id"] = environment_id + + kwargs["body"] = body + + return self._create_allocations_for_feature_flag_in_environment_endpoint.call_with_http_info(**kwargs) + def create_feature_flag( self, body: CreateFeatureFlagRequest, @@ -607,6 +794,74 @@ def list_feature_flags_environments( return self._list_feature_flags_environments_endpoint.call_with_http_info(**kwargs) + def pause_exposure_schedule( + self, + exposure_schedule_id: UUID, + ) -> AllocationExposureScheduleResponse: + """Pause a progressive rollout. + + Pauses a progressive rollout while preserving rollout state. + + :param exposure_schedule_id: The ID of the exposure schedule. + :type exposure_schedule_id: UUID + :rtype: AllocationExposureScheduleResponse + """ + kwargs: Dict[str, Any] = {} + kwargs["exposure_schedule_id"] = exposure_schedule_id + + return self._pause_exposure_schedule_endpoint.call_with_http_info(**kwargs) + + def resume_exposure_schedule( + self, + exposure_schedule_id: UUID, + ) -> AllocationExposureScheduleResponse: + """Resume a progressive rollout. + + Resumes progression for a previously paused progressive rollout. + + :param exposure_schedule_id: The ID of the exposure schedule. + :type exposure_schedule_id: UUID + :rtype: AllocationExposureScheduleResponse + """ + kwargs: Dict[str, Any] = {} + kwargs["exposure_schedule_id"] = exposure_schedule_id + + return self._resume_exposure_schedule_endpoint.call_with_http_info(**kwargs) + + def start_exposure_schedule( + self, + exposure_schedule_id: UUID, + ) -> AllocationExposureScheduleResponse: + """Start a progressive rollout. + + Starts a progressive rollout and begins progression. + + :param exposure_schedule_id: The ID of the exposure schedule. + :type exposure_schedule_id: UUID + :rtype: AllocationExposureScheduleResponse + """ + kwargs: Dict[str, Any] = {} + kwargs["exposure_schedule_id"] = exposure_schedule_id + + return self._start_exposure_schedule_endpoint.call_with_http_info(**kwargs) + + def stop_exposure_schedule( + self, + exposure_schedule_id: UUID, + ) -> AllocationExposureScheduleResponse: + """Stop a progressive rollout. + + Stops a progressive rollout and marks it as aborted. + + :param exposure_schedule_id: The ID of the exposure schedule. + :type exposure_schedule_id: UUID + :rtype: AllocationExposureScheduleResponse + """ + kwargs: Dict[str, Any] = {} + kwargs["exposure_schedule_id"] = exposure_schedule_id + + return self._stop_exposure_schedule_endpoint.call_with_http_info(**kwargs) + def unarchive_feature_flag( self, feature_flag_id: UUID, @@ -625,6 +880,33 @@ def unarchive_feature_flag( return self._unarchive_feature_flag_endpoint.call_with_http_info(**kwargs) + def update_allocations_for_feature_flag_in_environment( + self, + feature_flag_id: UUID, + environment_id: UUID, + body: OverwriteAllocationsRequest, + ) -> ListAllocationsResponse: + """Update targeting rules for a flag. + + Updates targeting rules (allocations) for a specific feature flag in a specific environment. + This operation replaces the existing allocation set with the request payload. + + :param feature_flag_id: The ID of the feature flag. + :type feature_flag_id: UUID + :param environment_id: The ID of the environment. + :type environment_id: UUID + :type body: OverwriteAllocationsRequest + :rtype: ListAllocationsResponse + """ + kwargs: Dict[str, Any] = {} + kwargs["feature_flag_id"] = feature_flag_id + + kwargs["environment_id"] = environment_id + + kwargs["body"] = body + + return self._update_allocations_for_feature_flag_in_environment_endpoint.call_with_http_info(**kwargs) + def update_feature_flag( self, feature_flag_id: UUID, diff --git a/src/datadog_api_client/v2/model/allocation.py b/src/datadog_api_client/v2/model/allocation.py new file mode 100644 index 0000000000..5df89b58cd --- /dev/null +++ b/src/datadog_api_client/v2/model/allocation.py @@ -0,0 +1,144 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import List, Union, TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, + datetime, + none_type, + unset, + UnsetType, + UUID, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.allocation_exposure_schedule import AllocationExposureSchedule + from datadog_api_client.v2.model.guardrail_metric import GuardrailMetric + from datadog_api_client.v2.model.targeting_rule import TargetingRule + from datadog_api_client.v2.model.allocation_type import AllocationType + from datadog_api_client.v2.model.variant_weight import VariantWeight + + +class Allocation(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.allocation_exposure_schedule import AllocationExposureSchedule + from datadog_api_client.v2.model.guardrail_metric import GuardrailMetric + from datadog_api_client.v2.model.targeting_rule import TargetingRule + from datadog_api_client.v2.model.allocation_type import AllocationType + from datadog_api_client.v2.model.variant_weight import VariantWeight + + return { + "created_at": (datetime,), + "environment_ids": ([UUID],), + "experiment_id": (str, none_type), + "exposure_schedule": (AllocationExposureSchedule,), + "guardrail_metrics": ([GuardrailMetric],), + "id": (UUID,), + "key": (str,), + "name": (str,), + "order_position": (int,), + "targeting_rules": ([TargetingRule],), + "type": (AllocationType,), + "updated_at": (datetime,), + "variant_weights": ([VariantWeight],), + } + + attribute_map = { + "created_at": "created_at", + "environment_ids": "environment_ids", + "experiment_id": "experiment_id", + "exposure_schedule": "exposure_schedule", + "guardrail_metrics": "guardrail_metrics", + "id": "id", + "key": "key", + "name": "name", + "order_position": "order_position", + "targeting_rules": "targeting_rules", + "type": "type", + "updated_at": "updated_at", + "variant_weights": "variant_weights", + } + + def __init__( + self_, + created_at: datetime, + environment_ids: List[UUID], + guardrail_metrics: List[GuardrailMetric], + key: str, + name: str, + order_position: int, + targeting_rules: List[TargetingRule], + type: AllocationType, + updated_at: datetime, + variant_weights: List[VariantWeight], + experiment_id: Union[str, none_type, UnsetType] = unset, + exposure_schedule: Union[AllocationExposureSchedule, UnsetType] = unset, + id: Union[UUID, UnsetType] = unset, + **kwargs, + ): + """ + Targeting rule (allocation) details for a feature flag environment. + + :param created_at: The timestamp when the targeting rule allocation was created. + :type created_at: datetime + + :param environment_ids: Environment IDs associated with this targeting rule allocation. + :type environment_ids: [UUID] + + :param experiment_id: The experiment ID linked to this targeting rule allocation. + :type experiment_id: str, none_type, optional + + :param exposure_schedule: Progressive release details for a targeting rule allocation. + :type exposure_schedule: AllocationExposureSchedule, optional + + :param guardrail_metrics: Guardrail metrics associated with this targeting rule allocation. + :type guardrail_metrics: [GuardrailMetric] + + :param id: The unique identifier of the targeting rule allocation. + :type id: UUID, optional + + :param key: The unique key of the targeting rule allocation. + :type key: str + + :param name: The display name of the targeting rule. + :type name: str + + :param order_position: Sort order position within the environment. + :type order_position: int + + :param targeting_rules: Conditions associated with this targeting rule allocation. + :type targeting_rules: [TargetingRule] + + :param type: The type of targeting rule (called allocation in the API model). + :type type: AllocationType + + :param updated_at: The timestamp when the targeting rule allocation was last updated. + :type updated_at: datetime + + :param variant_weights: Weighted variant assignments for this targeting rule allocation. + :type variant_weights: [VariantWeight] + """ + if experiment_id is not unset: + kwargs["experiment_id"] = experiment_id + if exposure_schedule is not unset: + kwargs["exposure_schedule"] = exposure_schedule + if id is not unset: + kwargs["id"] = id + super().__init__(kwargs) + + self_.created_at = created_at + self_.environment_ids = environment_ids + self_.guardrail_metrics = guardrail_metrics + self_.key = key + self_.name = name + self_.order_position = order_position + self_.targeting_rules = targeting_rules + self_.type = type + self_.updated_at = updated_at + self_.variant_weights = variant_weights diff --git a/src/datadog_api_client/v2/model/allocation_data_request.py b/src/datadog_api_client/v2/model/allocation_data_request.py new file mode 100644 index 0000000000..a507f4f56d --- /dev/null +++ b/src/datadog_api_client/v2/model/allocation_data_request.py @@ -0,0 +1,48 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.upsert_allocation_request import UpsertAllocationRequest + from datadog_api_client.v2.model.allocation_data_type import AllocationDataType + + +class AllocationDataRequest(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.upsert_allocation_request import UpsertAllocationRequest + from datadog_api_client.v2.model.allocation_data_type import AllocationDataType + + return { + "attributes": (UpsertAllocationRequest,), + "type": (AllocationDataType,), + } + + attribute_map = { + "attributes": "attributes", + "type": "type", + } + + def __init__(self_, attributes: UpsertAllocationRequest, type: AllocationDataType, **kwargs): + """ + Data wrapper for allocation request payloads. + + :param attributes: Request to create or update a targeting rule (allocation) for a feature flag environment. + :type attributes: UpsertAllocationRequest + + :param type: The resource type. + :type type: AllocationDataType + """ + super().__init__(kwargs) + + self_.attributes = attributes + self_.type = type diff --git a/src/datadog_api_client/v2/model/allocation_data_response.py b/src/datadog_api_client/v2/model/allocation_data_response.py new file mode 100644 index 0000000000..b9def0b8a9 --- /dev/null +++ b/src/datadog_api_client/v2/model/allocation_data_response.py @@ -0,0 +1,55 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, + UUID, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.allocation import Allocation + from datadog_api_client.v2.model.allocation_data_type import AllocationDataType + + +class AllocationDataResponse(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.allocation import Allocation + from datadog_api_client.v2.model.allocation_data_type import AllocationDataType + + return { + "attributes": (Allocation,), + "id": (UUID,), + "type": (AllocationDataType,), + } + + attribute_map = { + "attributes": "attributes", + "id": "id", + "type": "type", + } + + def __init__(self_, attributes: Allocation, id: UUID, type: AllocationDataType, **kwargs): + """ + Data wrapper for targeting rule allocation responses. + + :param attributes: Targeting rule (allocation) details for a feature flag environment. + :type attributes: Allocation + + :param id: The unique identifier of the targeting rule allocation. + :type id: UUID + + :param type: The resource type. + :type type: AllocationDataType + """ + super().__init__(kwargs) + + self_.attributes = attributes + self_.id = id + self_.type = type diff --git a/src/datadog_api_client/v2/model/allocation_data_type.py b/src/datadog_api_client/v2/model/allocation_data_type.py new file mode 100644 index 0000000000..9b58dfe0c4 --- /dev/null +++ b/src/datadog_api_client/v2/model/allocation_data_type.py @@ -0,0 +1,35 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + + +from datadog_api_client.model_utils import ( + ModelSimple, + cached_property, +) + +from typing import ClassVar + + +class AllocationDataType(ModelSimple): + """ + The resource type. + + :param value: If omitted defaults to "allocations". Must be one of ["allocations"]. + :type value: str + """ + + allowed_values = { + "allocations", + } + ALLOCATIONS: ClassVar["AllocationDataType"] + + @cached_property + def openapi_types(_): + return { + "value": (str,), + } + + +AllocationDataType.ALLOCATIONS = AllocationDataType("allocations") diff --git a/src/datadog_api_client/v2/model/allocation_exposure_guardrail_trigger.py b/src/datadog_api_client/v2/model/allocation_exposure_guardrail_trigger.py new file mode 100644 index 0000000000..3ce961a0bd --- /dev/null +++ b/src/datadog_api_client/v2/model/allocation_exposure_guardrail_trigger.py @@ -0,0 +1,81 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, + datetime, + UUID, +) + + +class AllocationExposureGuardrailTrigger(ModelNormal): + @cached_property + def openapi_types(_): + return { + "allocation_exposure_schedule_id": (UUID,), + "created_at": (datetime,), + "flagging_variant_id": (UUID,), + "id": (UUID,), + "metric_id": (str,), + "triggered_action": (str,), + "updated_at": (datetime,), + } + + attribute_map = { + "allocation_exposure_schedule_id": "allocation_exposure_schedule_id", + "created_at": "created_at", + "flagging_variant_id": "flagging_variant_id", + "id": "id", + "metric_id": "metric_id", + "triggered_action": "triggered_action", + "updated_at": "updated_at", + } + + def __init__( + self_, + allocation_exposure_schedule_id: UUID, + created_at: datetime, + flagging_variant_id: UUID, + id: UUID, + metric_id: str, + triggered_action: str, + updated_at: datetime, + **kwargs, + ): + """ + Guardrail trigger details for a progressive rollout. + + :param allocation_exposure_schedule_id: The progressive rollout ID this trigger belongs to. + :type allocation_exposure_schedule_id: UUID + + :param created_at: The timestamp when this trigger was created. + :type created_at: datetime + + :param flagging_variant_id: The variant ID that triggered this event. + :type flagging_variant_id: UUID + + :param id: The unique identifier of the guardrail trigger. + :type id: UUID + + :param metric_id: The metric ID associated with the trigger. + :type metric_id: str + + :param triggered_action: The action that was triggered. + :type triggered_action: str + + :param updated_at: The timestamp when this trigger was last updated. + :type updated_at: datetime + """ + super().__init__(kwargs) + + self_.allocation_exposure_schedule_id = allocation_exposure_schedule_id + self_.created_at = created_at + self_.flagging_variant_id = flagging_variant_id + self_.id = id + self_.metric_id = metric_id + self_.triggered_action = triggered_action + self_.updated_at = updated_at diff --git a/src/datadog_api_client/v2/model/allocation_exposure_rollout_step.py b/src/datadog_api_client/v2/model/allocation_exposure_rollout_step.py new file mode 100644 index 0000000000..b792b3a1a5 --- /dev/null +++ b/src/datadog_api_client/v2/model/allocation_exposure_rollout_step.py @@ -0,0 +1,110 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import Union + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, + datetime, + none_type, + unset, + UnsetType, + UUID, +) + + +class AllocationExposureRolloutStep(ModelNormal): + validations = { + "exposure_ratio": { + "inclusive_maximum": 1, + "inclusive_minimum": 0, + }, + "grouped_step_index": { + "inclusive_minimum": 0, + }, + } + + @cached_property + def openapi_types(_): + return { + "allocation_exposure_schedule_id": (UUID,), + "created_at": (datetime,), + "exposure_ratio": (float,), + "grouped_step_index": (int,), + "id": (UUID,), + "interval_ms": (int, none_type), + "is_pause_record": (bool,), + "order_position": (int,), + "updated_at": (datetime,), + } + + attribute_map = { + "allocation_exposure_schedule_id": "allocation_exposure_schedule_id", + "created_at": "created_at", + "exposure_ratio": "exposure_ratio", + "grouped_step_index": "grouped_step_index", + "id": "id", + "interval_ms": "interval_ms", + "is_pause_record": "is_pause_record", + "order_position": "order_position", + "updated_at": "updated_at", + } + + def __init__( + self_, + allocation_exposure_schedule_id: UUID, + created_at: datetime, + exposure_ratio: float, + grouped_step_index: int, + id: UUID, + is_pause_record: bool, + order_position: int, + updated_at: datetime, + interval_ms: Union[int, none_type, UnsetType] = unset, + **kwargs, + ): + """ + Exposure progression step details. + + :param allocation_exposure_schedule_id: The progressive rollout ID this step belongs to. + :type allocation_exposure_schedule_id: UUID + + :param created_at: The timestamp when the progression step was created. + :type created_at: datetime + + :param exposure_ratio: The exposure ratio for this step. + :type exposure_ratio: float + + :param grouped_step_index: Logical index grouping related steps. + :type grouped_step_index: int + + :param id: The unique identifier of the progression step. + :type id: UUID + + :param interval_ms: Step duration in milliseconds. + :type interval_ms: int, none_type, optional + + :param is_pause_record: Whether this step represents a pause record. + :type is_pause_record: bool + + :param order_position: Sort order for the progression step. + :type order_position: int + + :param updated_at: The timestamp when the progression step was last updated. + :type updated_at: datetime + """ + if interval_ms is not unset: + kwargs["interval_ms"] = interval_ms + super().__init__(kwargs) + + self_.allocation_exposure_schedule_id = allocation_exposure_schedule_id + self_.created_at = created_at + self_.exposure_ratio = exposure_ratio + self_.grouped_step_index = grouped_step_index + self_.id = id + self_.is_pause_record = is_pause_record + self_.order_position = order_position + self_.updated_at = updated_at diff --git a/src/datadog_api_client/v2/model/allocation_exposure_schedule.py b/src/datadog_api_client/v2/model/allocation_exposure_schedule.py new file mode 100644 index 0000000000..6f63bc2bf3 --- /dev/null +++ b/src/datadog_api_client/v2/model/allocation_exposure_schedule.py @@ -0,0 +1,120 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import List, Union, TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, + datetime, + none_type, + unset, + UnsetType, + UUID, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.allocation_exposure_guardrail_trigger import AllocationExposureGuardrailTrigger + from datadog_api_client.v2.model.rollout_options import RolloutOptions + from datadog_api_client.v2.model.allocation_exposure_rollout_step import AllocationExposureRolloutStep + + +class AllocationExposureSchedule(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.allocation_exposure_guardrail_trigger import AllocationExposureGuardrailTrigger + from datadog_api_client.v2.model.rollout_options import RolloutOptions + from datadog_api_client.v2.model.allocation_exposure_rollout_step import AllocationExposureRolloutStep + + return { + "absolute_start_time": (datetime, none_type), + "allocation_id": (UUID,), + "control_variant_id": (str, none_type), + "created_at": (datetime,), + "guardrail_triggered_action": (str, none_type), + "guardrail_triggers": ([AllocationExposureGuardrailTrigger],), + "id": (UUID,), + "rollout_options": (RolloutOptions,), + "rollout_steps": ([AllocationExposureRolloutStep],), + "updated_at": (datetime,), + } + + attribute_map = { + "absolute_start_time": "absolute_start_time", + "allocation_id": "allocation_id", + "control_variant_id": "control_variant_id", + "created_at": "created_at", + "guardrail_triggered_action": "guardrail_triggered_action", + "guardrail_triggers": "guardrail_triggers", + "id": "id", + "rollout_options": "rollout_options", + "rollout_steps": "rollout_steps", + "updated_at": "updated_at", + } + + def __init__( + self_, + allocation_id: UUID, + created_at: datetime, + guardrail_triggers: List[AllocationExposureGuardrailTrigger], + rollout_options: RolloutOptions, + rollout_steps: List[AllocationExposureRolloutStep], + updated_at: datetime, + absolute_start_time: Union[datetime, none_type, UnsetType] = unset, + control_variant_id: Union[str, none_type, UnsetType] = unset, + guardrail_triggered_action: Union[str, none_type, UnsetType] = unset, + id: Union[UUID, UnsetType] = unset, + **kwargs, + ): + """ + Progressive release details for a targeting rule allocation. + + :param absolute_start_time: The absolute UTC start time for this schedule. + :type absolute_start_time: datetime, none_type, optional + + :param allocation_id: The targeting rule allocation ID this progressive rollout belongs to. + :type allocation_id: UUID + + :param control_variant_id: The control variant ID used for experiment comparisons. + :type control_variant_id: str, none_type, optional + + :param created_at: The timestamp when the schedule was created. + :type created_at: datetime + + :param guardrail_triggered_action: Last guardrail action triggered for this schedule. + :type guardrail_triggered_action: str, none_type, optional + + :param guardrail_triggers: Guardrail trigger records for this schedule. + :type guardrail_triggers: [AllocationExposureGuardrailTrigger] + + :param id: The unique identifier of the progressive rollout. + :type id: UUID, optional + + :param rollout_options: Applied progression options for a progressive rollout. + :type rollout_options: RolloutOptions + + :param rollout_steps: Ordered progression steps for exposure. + :type rollout_steps: [AllocationExposureRolloutStep] + + :param updated_at: The timestamp when the schedule was last updated. + :type updated_at: datetime + """ + if absolute_start_time is not unset: + kwargs["absolute_start_time"] = absolute_start_time + if control_variant_id is not unset: + kwargs["control_variant_id"] = control_variant_id + if guardrail_triggered_action is not unset: + kwargs["guardrail_triggered_action"] = guardrail_triggered_action + if id is not unset: + kwargs["id"] = id + super().__init__(kwargs) + + self_.allocation_id = allocation_id + self_.created_at = created_at + self_.guardrail_triggers = guardrail_triggers + self_.rollout_options = rollout_options + self_.rollout_steps = rollout_steps + self_.updated_at = updated_at diff --git a/src/datadog_api_client/v2/model/allocation_exposure_schedule_data.py b/src/datadog_api_client/v2/model/allocation_exposure_schedule_data.py new file mode 100644 index 0000000000..9aceada447 --- /dev/null +++ b/src/datadog_api_client/v2/model/allocation_exposure_schedule_data.py @@ -0,0 +1,59 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, + UUID, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.allocation_exposure_schedule import AllocationExposureSchedule + from datadog_api_client.v2.model.allocation_exposure_schedule_data_type import AllocationExposureScheduleDataType + + +class AllocationExposureScheduleData(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.allocation_exposure_schedule import AllocationExposureSchedule + from datadog_api_client.v2.model.allocation_exposure_schedule_data_type import ( + AllocationExposureScheduleDataType, + ) + + return { + "attributes": (AllocationExposureSchedule,), + "id": (UUID,), + "type": (AllocationExposureScheduleDataType,), + } + + attribute_map = { + "attributes": "attributes", + "id": "id", + "type": "type", + } + + def __init__( + self_, attributes: AllocationExposureSchedule, id: UUID, type: AllocationExposureScheduleDataType, **kwargs + ): + """ + Data wrapper for progressive rollout schedule responses. + + :param attributes: Progressive release details for a targeting rule allocation. + :type attributes: AllocationExposureSchedule + + :param id: The unique identifier of the progressive rollout. + :type id: UUID + + :param type: The resource type for progressive rollout schedules. + :type type: AllocationExposureScheduleDataType + """ + super().__init__(kwargs) + + self_.attributes = attributes + self_.id = id + self_.type = type diff --git a/src/datadog_api_client/v2/model/allocation_exposure_schedule_data_type.py b/src/datadog_api_client/v2/model/allocation_exposure_schedule_data_type.py new file mode 100644 index 0000000000..c3f9b3f570 --- /dev/null +++ b/src/datadog_api_client/v2/model/allocation_exposure_schedule_data_type.py @@ -0,0 +1,37 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + + +from datadog_api_client.model_utils import ( + ModelSimple, + cached_property, +) + +from typing import ClassVar + + +class AllocationExposureScheduleDataType(ModelSimple): + """ + The resource type for progressive rollout schedules. + + :param value: If omitted defaults to "allocation_exposure_schedules". Must be one of ["allocation_exposure_schedules"]. + :type value: str + """ + + allowed_values = { + "allocation_exposure_schedules", + } + ALLOCATION_EXPOSURE_SCHEDULES: ClassVar["AllocationExposureScheduleDataType"] + + @cached_property + def openapi_types(_): + return { + "value": (str,), + } + + +AllocationExposureScheduleDataType.ALLOCATION_EXPOSURE_SCHEDULES = AllocationExposureScheduleDataType( + "allocation_exposure_schedules" +) diff --git a/src/datadog_api_client/v2/model/allocation_exposure_schedule_response.py b/src/datadog_api_client/v2/model/allocation_exposure_schedule_response.py new file mode 100644 index 0000000000..c1074345d0 --- /dev/null +++ b/src/datadog_api_client/v2/model/allocation_exposure_schedule_response.py @@ -0,0 +1,40 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.allocation_exposure_schedule_data import AllocationExposureScheduleData + + +class AllocationExposureScheduleResponse(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.allocation_exposure_schedule_data import AllocationExposureScheduleData + + return { + "data": (AllocationExposureScheduleData,), + } + + attribute_map = { + "data": "data", + } + + def __init__(self_, data: AllocationExposureScheduleData, **kwargs): + """ + Response containing a progressive rollout schedule. + + :param data: Data wrapper for progressive rollout schedule responses. + :type data: AllocationExposureScheduleData + """ + super().__init__(kwargs) + + self_.data = data diff --git a/src/datadog_api_client/v2/model/allocation_response.py b/src/datadog_api_client/v2/model/allocation_response.py new file mode 100644 index 0000000000..55597f207a --- /dev/null +++ b/src/datadog_api_client/v2/model/allocation_response.py @@ -0,0 +1,40 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.allocation_data_response import AllocationDataResponse + + +class AllocationResponse(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.allocation_data_response import AllocationDataResponse + + return { + "data": (AllocationDataResponse,), + } + + attribute_map = { + "data": "data", + } + + def __init__(self_, data: AllocationDataResponse, **kwargs): + """ + Response containing a single targeting rule (allocation). + + :param data: Data wrapper for targeting rule allocation responses. + :type data: AllocationDataResponse + """ + super().__init__(kwargs) + + self_.data = data diff --git a/src/datadog_api_client/v2/model/allocation_type.py b/src/datadog_api_client/v2/model/allocation_type.py new file mode 100644 index 0000000000..dfbf610883 --- /dev/null +++ b/src/datadog_api_client/v2/model/allocation_type.py @@ -0,0 +1,38 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + + +from datadog_api_client.model_utils import ( + ModelSimple, + cached_property, +) + +from typing import ClassVar + + +class AllocationType(ModelSimple): + """ + The type of targeting rule (called allocation in the API model). + + :param value: Must be one of ["FEATURE_GATE", "CANARY"]. + :type value: str + """ + + allowed_values = { + "FEATURE_GATE", + "CANARY", + } + FEATURE_GATE: ClassVar["AllocationType"] + CANARY: ClassVar["AllocationType"] + + @cached_property + def openapi_types(_): + return { + "value": (str,), + } + + +AllocationType.FEATURE_GATE = AllocationType("FEATURE_GATE") +AllocationType.CANARY = AllocationType("CANARY") diff --git a/src/datadog_api_client/v2/model/condition.py b/src/datadog_api_client/v2/model/condition.py new file mode 100644 index 0000000000..aabf0ca1ee --- /dev/null +++ b/src/datadog_api_client/v2/model/condition.py @@ -0,0 +1,81 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import List, TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, + datetime, + UUID, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.condition_operator import ConditionOperator + + +class Condition(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.condition_operator import ConditionOperator + + return { + "attribute": (str,), + "created_at": (datetime,), + "id": (UUID,), + "operator": (ConditionOperator,), + "updated_at": (datetime,), + "value": ([str],), + } + + attribute_map = { + "attribute": "attribute", + "created_at": "created_at", + "id": "id", + "operator": "operator", + "updated_at": "updated_at", + "value": "value", + } + + def __init__( + self_, + attribute: str, + created_at: datetime, + id: UUID, + operator: ConditionOperator, + updated_at: datetime, + value: List[str], + **kwargs, + ): + """ + Targeting condition details. + + :param attribute: The user or request attribute to evaluate. + :type attribute: str + + :param created_at: The timestamp when the condition was created. + :type created_at: datetime + + :param id: The unique identifier of the condition. + :type id: UUID + + :param operator: The operator used in a targeting condition. + :type operator: ConditionOperator + + :param updated_at: The timestamp when the condition was last updated. + :type updated_at: datetime + + :param value: Values used by the selected operator. + :type value: [str] + """ + super().__init__(kwargs) + + self_.attribute = attribute + self_.created_at = created_at + self_.id = id + self_.operator = operator + self_.updated_at = updated_at + self_.value = value diff --git a/src/datadog_api_client/v2/model/condition_operator.py b/src/datadog_api_client/v2/model/condition_operator.py new file mode 100644 index 0000000000..fbfecee605 --- /dev/null +++ b/src/datadog_api_client/v2/model/condition_operator.py @@ -0,0 +1,62 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + + +from datadog_api_client.model_utils import ( + ModelSimple, + cached_property, +) + +from typing import ClassVar + + +class ConditionOperator(ModelSimple): + """ + The operator used in a targeting condition. + + :param value: Must be one of ["LT", "LTE", "GT", "GTE", "MATCHES", "NOT_MATCHES", "ONE_OF", "NOT_ONE_OF", "IS_NULL", "EQUALS"]. + :type value: str + """ + + allowed_values = { + "LT", + "LTE", + "GT", + "GTE", + "MATCHES", + "NOT_MATCHES", + "ONE_OF", + "NOT_ONE_OF", + "IS_NULL", + "EQUALS", + } + LT: ClassVar["ConditionOperator"] + LTE: ClassVar["ConditionOperator"] + GT: ClassVar["ConditionOperator"] + GTE: ClassVar["ConditionOperator"] + MATCHES: ClassVar["ConditionOperator"] + NOT_MATCHES: ClassVar["ConditionOperator"] + ONE_OF: ClassVar["ConditionOperator"] + NOT_ONE_OF: ClassVar["ConditionOperator"] + IS_NULL: ClassVar["ConditionOperator"] + EQUALS: ClassVar["ConditionOperator"] + + @cached_property + def openapi_types(_): + return { + "value": (str,), + } + + +ConditionOperator.LT = ConditionOperator("LT") +ConditionOperator.LTE = ConditionOperator("LTE") +ConditionOperator.GT = ConditionOperator("GT") +ConditionOperator.GTE = ConditionOperator("GTE") +ConditionOperator.MATCHES = ConditionOperator("MATCHES") +ConditionOperator.NOT_MATCHES = ConditionOperator("NOT_MATCHES") +ConditionOperator.ONE_OF = ConditionOperator("ONE_OF") +ConditionOperator.NOT_ONE_OF = ConditionOperator("NOT_ONE_OF") +ConditionOperator.IS_NULL = ConditionOperator("IS_NULL") +ConditionOperator.EQUALS = ConditionOperator("EQUALS") diff --git a/src/datadog_api_client/v2/model/condition_request.py b/src/datadog_api_client/v2/model/condition_request.py new file mode 100644 index 0000000000..314b8b3eda --- /dev/null +++ b/src/datadog_api_client/v2/model/condition_request.py @@ -0,0 +1,52 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import List, TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.condition_operator import ConditionOperator + + +class ConditionRequest(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.condition_operator import ConditionOperator + + return { + "attribute": (str,), + "operator": (ConditionOperator,), + "value": ([str],), + } + + attribute_map = { + "attribute": "attribute", + "operator": "operator", + "value": "value", + } + + def __init__(self_, attribute: str, operator: ConditionOperator, value: List[str], **kwargs): + """ + Condition request payload for targeting rules. + + :param attribute: The user or request attribute to evaluate. + :type attribute: str + + :param operator: The operator used in a targeting condition. + :type operator: ConditionOperator + + :param value: Values used by the selected operator. + :type value: [str] + """ + super().__init__(kwargs) + + self_.attribute = attribute + self_.operator = operator + self_.value = value diff --git a/src/datadog_api_client/v2/model/create_allocations_request.py b/src/datadog_api_client/v2/model/create_allocations_request.py new file mode 100644 index 0000000000..0b74fe8960 --- /dev/null +++ b/src/datadog_api_client/v2/model/create_allocations_request.py @@ -0,0 +1,40 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.allocation_data_request import AllocationDataRequest + + +class CreateAllocationsRequest(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.allocation_data_request import AllocationDataRequest + + return { + "data": (AllocationDataRequest,), + } + + attribute_map = { + "data": "data", + } + + def __init__(self_, data: AllocationDataRequest, **kwargs): + """ + Request to create targeting rules (allocations) for a feature flag in an environment. + + :param data: Data wrapper for allocation request payloads. + :type data: AllocationDataRequest + """ + super().__init__(kwargs) + + self_.data = data diff --git a/src/datadog_api_client/v2/model/exposure_rollout_step_request.py b/src/datadog_api_client/v2/model/exposure_rollout_step_request.py new file mode 100644 index 0000000000..3f89f49fe1 --- /dev/null +++ b/src/datadog_api_client/v2/model/exposure_rollout_step_request.py @@ -0,0 +1,82 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import Union + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, + none_type, + unset, + UnsetType, + UUID, +) + + +class ExposureRolloutStepRequest(ModelNormal): + validations = { + "exposure_ratio": { + "inclusive_maximum": 1, + "inclusive_minimum": 0, + }, + "grouped_step_index": { + "inclusive_minimum": 0, + }, + } + + @cached_property + def openapi_types(_): + return { + "exposure_ratio": (float,), + "grouped_step_index": (int,), + "id": (UUID,), + "interval_ms": (int, none_type), + "is_pause_record": (bool,), + } + + attribute_map = { + "exposure_ratio": "exposure_ratio", + "grouped_step_index": "grouped_step_index", + "id": "id", + "interval_ms": "interval_ms", + "is_pause_record": "is_pause_record", + } + + def __init__( + self_, + exposure_ratio: float, + grouped_step_index: int, + is_pause_record: bool, + id: Union[UUID, UnsetType] = unset, + interval_ms: Union[int, none_type, UnsetType] = unset, + **kwargs, + ): + """ + Rollout step request payload. + + :param exposure_ratio: The exposure ratio for this step. + :type exposure_ratio: float + + :param grouped_step_index: Logical index grouping related steps. + :type grouped_step_index: int + + :param id: The unique identifier of the progression step. + :type id: UUID, optional + + :param interval_ms: Step duration in milliseconds. + :type interval_ms: int, none_type, optional + + :param is_pause_record: Whether this step represents a pause record. + :type is_pause_record: bool + """ + if id is not unset: + kwargs["id"] = id + if interval_ms is not unset: + kwargs["interval_ms"] = interval_ms + super().__init__(kwargs) + + self_.exposure_ratio = exposure_ratio + self_.grouped_step_index = grouped_step_index + self_.is_pause_record = is_pause_record diff --git a/src/datadog_api_client/v2/model/exposure_schedule_request.py b/src/datadog_api_client/v2/model/exposure_schedule_request.py new file mode 100644 index 0000000000..daa27b78b1 --- /dev/null +++ b/src/datadog_api_client/v2/model/exposure_schedule_request.py @@ -0,0 +1,96 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import List, Union, TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, + datetime, + none_type, + unset, + UnsetType, + UUID, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.rollout_options_request import RolloutOptionsRequest + from datadog_api_client.v2.model.exposure_rollout_step_request import ExposureRolloutStepRequest + + +class ExposureScheduleRequest(ModelNormal): + validations = { + "rollout_steps": { + "min_items": 1, + }, + } + + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.rollout_options_request import RolloutOptionsRequest + from datadog_api_client.v2.model.exposure_rollout_step_request import ExposureRolloutStepRequest + + return { + "absolute_start_time": (datetime, none_type), + "control_variant_id": (str, none_type), + "control_variant_key": (str, none_type), + "id": (UUID,), + "rollout_options": (RolloutOptionsRequest,), + "rollout_steps": ([ExposureRolloutStepRequest],), + } + + attribute_map = { + "absolute_start_time": "absolute_start_time", + "control_variant_id": "control_variant_id", + "control_variant_key": "control_variant_key", + "id": "id", + "rollout_options": "rollout_options", + "rollout_steps": "rollout_steps", + } + + def __init__( + self_, + rollout_options: RolloutOptionsRequest, + rollout_steps: List[ExposureRolloutStepRequest], + absolute_start_time: Union[datetime, none_type, UnsetType] = unset, + control_variant_id: Union[str, none_type, UnsetType] = unset, + control_variant_key: Union[str, none_type, UnsetType] = unset, + id: Union[UUID, UnsetType] = unset, + **kwargs, + ): + """ + Progressive release request payload. + + :param absolute_start_time: The absolute UTC start time for this schedule. + :type absolute_start_time: datetime, none_type, optional + + :param control_variant_id: The control variant ID used for experiment comparisons. + :type control_variant_id: str, none_type, optional + + :param control_variant_key: The control variant key used during creation workflows. + :type control_variant_key: str, none_type, optional + + :param id: The unique identifier of the progressive rollout. + :type id: UUID, optional + + :param rollout_options: Rollout options request payload. + :type rollout_options: RolloutOptionsRequest + + :param rollout_steps: Ordered progression steps for exposure. + :type rollout_steps: [ExposureRolloutStepRequest] + """ + if absolute_start_time is not unset: + kwargs["absolute_start_time"] = absolute_start_time + if control_variant_id is not unset: + kwargs["control_variant_id"] = control_variant_id + if control_variant_key is not unset: + kwargs["control_variant_key"] = control_variant_key + if id is not unset: + kwargs["id"] = id + super().__init__(kwargs) + + self_.rollout_options = rollout_options + self_.rollout_steps = rollout_steps diff --git a/src/datadog_api_client/v2/model/feature_flag_attributes.py b/src/datadog_api_client/v2/model/feature_flag_attributes.py index dd400d299c..882f268265 100644 --- a/src/datadog_api_client/v2/model/feature_flag_attributes.py +++ b/src/datadog_api_client/v2/model/feature_flag_attributes.py @@ -41,6 +41,7 @@ def openapi_types(_): "last_updated_by": (UUID,), "name": (str,), "require_approval": (bool,), + "tags": ([str],), "updated_at": (datetime,), "value_type": (ValueType,), "variants": ([Variant],), @@ -58,6 +59,7 @@ def openapi_types(_): "last_updated_by": "last_updated_by", "name": "name", "require_approval": "require_approval", + "tags": "tags", "updated_at": "updated_at", "value_type": "value_type", "variants": "variants", @@ -78,6 +80,7 @@ def __init__( json_schema: Union[str, none_type, UnsetType] = unset, last_updated_by: Union[UUID, UnsetType] = unset, require_approval: Union[bool, UnsetType] = unset, + tags: Union[List[str], UnsetType] = unset, updated_at: Union[datetime, UnsetType] = unset, **kwargs, ): @@ -117,6 +120,9 @@ def __init__( :param require_approval: Indicates whether this feature flag requires approval for changes. :type require_approval: bool, optional + :param tags: Tags associated with the feature flag. + :type tags: [str], optional + :param updated_at: The timestamp when the feature flag was last updated. :type updated_at: datetime, optional @@ -142,6 +148,8 @@ def __init__( kwargs["last_updated_by"] = last_updated_by if require_approval is not unset: kwargs["require_approval"] = require_approval + if tags is not unset: + kwargs["tags"] = tags if updated_at is not unset: kwargs["updated_at"] = updated_at super().__init__(kwargs) diff --git a/src/datadog_api_client/v2/model/feature_flag_environment.py b/src/datadog_api_client/v2/model/feature_flag_environment.py index fab1907d12..2a51faddda 100644 --- a/src/datadog_api_client/v2/model/feature_flag_environment.py +++ b/src/datadog_api_client/v2/model/feature_flag_environment.py @@ -57,6 +57,7 @@ def openapi_types(_): "default_variant_id": (str, none_type), "environment_id": (UUID,), "environment_name": (str,), + "environment_queries": ([str],), "is_production": (bool,), "override_allocation_key": (str,), "override_variant_id": (str, none_type), @@ -73,6 +74,7 @@ def openapi_types(_): "default_variant_id": "default_variant_id", "environment_id": "environment_id", "environment_name": "environment_name", + "environment_queries": "environment_queries", "is_production": "is_production", "override_allocation_key": "override_allocation_key", "override_variant_id": "override_variant_id", @@ -91,6 +93,7 @@ def __init__( default_allocation_key: Union[str, UnsetType] = unset, default_variant_id: Union[str, none_type, UnsetType] = unset, environment_name: Union[str, UnsetType] = unset, + environment_queries: Union[List[str], UnsetType] = unset, is_production: Union[bool, UnsetType] = unset, override_allocation_key: Union[str, UnsetType] = unset, override_variant_id: Union[str, none_type, UnsetType] = unset, @@ -118,6 +121,9 @@ def __init__( :param environment_name: The name of the environment. :type environment_name: str, optional + :param environment_queries: Queries that target this environment. + :type environment_queries: [str], optional + :param is_production: Indicates whether the environment is production. :type is_production: bool, optional @@ -150,6 +156,8 @@ def __init__( kwargs["default_variant_id"] = default_variant_id if environment_name is not unset: kwargs["environment_name"] = environment_name + if environment_queries is not unset: + kwargs["environment_queries"] = environment_queries if is_production is not unset: kwargs["is_production"] = is_production if override_allocation_key is not unset: diff --git a/src/datadog_api_client/v2/model/guardrail_metric.py b/src/datadog_api_client/v2/model/guardrail_metric.py new file mode 100644 index 0000000000..9a66e9bfe0 --- /dev/null +++ b/src/datadog_api_client/v2/model/guardrail_metric.py @@ -0,0 +1,62 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import Union, TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, + none_type, + unset, + UnsetType, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.guardrail_trigger_action import GuardrailTriggerAction + + +class GuardrailMetric(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.guardrail_trigger_action import GuardrailTriggerAction + + return { + "metric_id": (str,), + "trigger_action": (GuardrailTriggerAction,), + "triggered_by": (str, none_type), + } + + attribute_map = { + "metric_id": "metric_id", + "trigger_action": "trigger_action", + "triggered_by": "triggered_by", + } + + def __init__( + self_, + metric_id: str, + trigger_action: GuardrailTriggerAction, + triggered_by: Union[str, none_type, UnsetType] = unset, + **kwargs, + ): + """ + Guardrail metric details. + + :param metric_id: The metric ID to monitor. + :type metric_id: str + + :param trigger_action: Action to perform when a guardrail threshold is triggered. + :type trigger_action: GuardrailTriggerAction + + :param triggered_by: The signal or system that triggered the action. + :type triggered_by: str, none_type, optional + """ + if triggered_by is not unset: + kwargs["triggered_by"] = triggered_by + super().__init__(kwargs) + + self_.metric_id = metric_id + self_.trigger_action = trigger_action diff --git a/src/datadog_api_client/v2/model/guardrail_metric_request.py b/src/datadog_api_client/v2/model/guardrail_metric_request.py new file mode 100644 index 0000000000..97c29f528f --- /dev/null +++ b/src/datadog_api_client/v2/model/guardrail_metric_request.py @@ -0,0 +1,46 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.guardrail_trigger_action import GuardrailTriggerAction + + +class GuardrailMetricRequest(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.guardrail_trigger_action import GuardrailTriggerAction + + return { + "metric_id": (str,), + "trigger_action": (GuardrailTriggerAction,), + } + + attribute_map = { + "metric_id": "metric_id", + "trigger_action": "trigger_action", + } + + def __init__(self_, metric_id: str, trigger_action: GuardrailTriggerAction, **kwargs): + """ + Guardrail metric request payload. + + :param metric_id: The metric ID to monitor. + :type metric_id: str + + :param trigger_action: Action to perform when a guardrail threshold is triggered. + :type trigger_action: GuardrailTriggerAction + """ + super().__init__(kwargs) + + self_.metric_id = metric_id + self_.trigger_action = trigger_action diff --git a/src/datadog_api_client/v2/model/guardrail_trigger_action.py b/src/datadog_api_client/v2/model/guardrail_trigger_action.py new file mode 100644 index 0000000000..1f7ef1cbf8 --- /dev/null +++ b/src/datadog_api_client/v2/model/guardrail_trigger_action.py @@ -0,0 +1,38 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + + +from datadog_api_client.model_utils import ( + ModelSimple, + cached_property, +) + +from typing import ClassVar + + +class GuardrailTriggerAction(ModelSimple): + """ + Action to perform when a guardrail threshold is triggered. + + :param value: Must be one of ["PAUSE", "ABORT"]. + :type value: str + """ + + allowed_values = { + "PAUSE", + "ABORT", + } + PAUSE: ClassVar["GuardrailTriggerAction"] + ABORT: ClassVar["GuardrailTriggerAction"] + + @cached_property + def openapi_types(_): + return { + "value": (str,), + } + + +GuardrailTriggerAction.PAUSE = GuardrailTriggerAction("PAUSE") +GuardrailTriggerAction.ABORT = GuardrailTriggerAction("ABORT") diff --git a/src/datadog_api_client/v2/model/list_allocations_response.py b/src/datadog_api_client/v2/model/list_allocations_response.py new file mode 100644 index 0000000000..8d718de269 --- /dev/null +++ b/src/datadog_api_client/v2/model/list_allocations_response.py @@ -0,0 +1,40 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import List, TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.allocation_data_response import AllocationDataResponse + + +class ListAllocationsResponse(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.allocation_data_response import AllocationDataResponse + + return { + "data": ([AllocationDataResponse],), + } + + attribute_map = { + "data": "data", + } + + def __init__(self_, data: List[AllocationDataResponse], **kwargs): + """ + Response containing a list of targeting rules (allocations). + + :param data: List of targeting rules (allocations). + :type data: [AllocationDataResponse] + """ + super().__init__(kwargs) + + self_.data = data diff --git a/src/datadog_api_client/v2/model/overwrite_allocations_request.py b/src/datadog_api_client/v2/model/overwrite_allocations_request.py new file mode 100644 index 0000000000..8a273113ff --- /dev/null +++ b/src/datadog_api_client/v2/model/overwrite_allocations_request.py @@ -0,0 +1,40 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import List, TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.allocation_data_request import AllocationDataRequest + + +class OverwriteAllocationsRequest(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.allocation_data_request import AllocationDataRequest + + return { + "data": ([AllocationDataRequest],), + } + + attribute_map = { + "data": "data", + } + + def __init__(self_, data: List[AllocationDataRequest], **kwargs): + """ + Request to overwrite targeting rules (allocations) for a feature flag in an environment. + + :param data: Targeting rules (allocations) to replace existing ones with. + :type data: [AllocationDataRequest] + """ + super().__init__(kwargs) + + self_.data = data diff --git a/src/datadog_api_client/v2/model/rollout_options.py b/src/datadog_api_client/v2/model/rollout_options.py new file mode 100644 index 0000000000..df22801786 --- /dev/null +++ b/src/datadog_api_client/v2/model/rollout_options.py @@ -0,0 +1,52 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.rollout_strategy import RolloutStrategy + + +class RolloutOptions(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.rollout_strategy import RolloutStrategy + + return { + "autostart": (bool,), + "selection_interval_ms": (int,), + "strategy": (RolloutStrategy,), + } + + attribute_map = { + "autostart": "autostart", + "selection_interval_ms": "selection_interval_ms", + "strategy": "strategy", + } + + def __init__(self_, autostart: bool, selection_interval_ms: int, strategy: RolloutStrategy, **kwargs): + """ + Applied progression options for a progressive rollout. + + :param autostart: Whether the schedule starts automatically. + :type autostart: bool + + :param selection_interval_ms: Interval in milliseconds for uniform interval strategies. + :type selection_interval_ms: int + + :param strategy: The progression strategy used by a progressive rollout. + :type strategy: RolloutStrategy + """ + super().__init__(kwargs) + + self_.autostart = autostart + self_.selection_interval_ms = selection_interval_ms + self_.strategy = strategy diff --git a/src/datadog_api_client/v2/model/rollout_options_request.py b/src/datadog_api_client/v2/model/rollout_options_request.py new file mode 100644 index 0000000000..407695eb7a --- /dev/null +++ b/src/datadog_api_client/v2/model/rollout_options_request.py @@ -0,0 +1,63 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import Union, TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, + none_type, + unset, + UnsetType, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.rollout_strategy import RolloutStrategy + + +class RolloutOptionsRequest(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.rollout_strategy import RolloutStrategy + + return { + "autostart": (bool, none_type), + "selection_interval_ms": (int,), + "strategy": (RolloutStrategy,), + } + + attribute_map = { + "autostart": "autostart", + "selection_interval_ms": "selection_interval_ms", + "strategy": "strategy", + } + + def __init__( + self_, + strategy: RolloutStrategy, + autostart: Union[bool, none_type, UnsetType] = unset, + selection_interval_ms: Union[int, UnsetType] = unset, + **kwargs, + ): + """ + Rollout options request payload. + + :param autostart: Whether the schedule should begin automatically. + :type autostart: bool, none_type, optional + + :param selection_interval_ms: Interval in milliseconds for uniform interval strategies. + :type selection_interval_ms: int, optional + + :param strategy: The progression strategy used by a progressive rollout. + :type strategy: RolloutStrategy + """ + if autostart is not unset: + kwargs["autostart"] = autostart + if selection_interval_ms is not unset: + kwargs["selection_interval_ms"] = selection_interval_ms + super().__init__(kwargs) + + self_.strategy = strategy diff --git a/src/datadog_api_client/v2/model/rollout_strategy.py b/src/datadog_api_client/v2/model/rollout_strategy.py new file mode 100644 index 0000000000..0e506745c4 --- /dev/null +++ b/src/datadog_api_client/v2/model/rollout_strategy.py @@ -0,0 +1,38 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + + +from datadog_api_client.model_utils import ( + ModelSimple, + cached_property, +) + +from typing import ClassVar + + +class RolloutStrategy(ModelSimple): + """ + The progression strategy used by a progressive rollout. + + :param value: Must be one of ["UNIFORM_INTERVALS", "NO_ROLLOUT"]. + :type value: str + """ + + allowed_values = { + "UNIFORM_INTERVALS", + "NO_ROLLOUT", + } + UNIFORM_INTERVALS: ClassVar["RolloutStrategy"] + NO_ROLLOUT: ClassVar["RolloutStrategy"] + + @cached_property + def openapi_types(_): + return { + "value": (str,), + } + + +RolloutStrategy.UNIFORM_INTERVALS = RolloutStrategy("UNIFORM_INTERVALS") +RolloutStrategy.NO_ROLLOUT = RolloutStrategy("NO_ROLLOUT") diff --git a/src/datadog_api_client/v2/model/targeting_rule.py b/src/datadog_api_client/v2/model/targeting_rule.py new file mode 100644 index 0000000000..21eb8d587c --- /dev/null +++ b/src/datadog_api_client/v2/model/targeting_rule.py @@ -0,0 +1,60 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import List, TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, + datetime, + UUID, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.condition import Condition + + +class TargetingRule(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.condition import Condition + + return { + "conditions": ([Condition],), + "created_at": (datetime,), + "id": (UUID,), + "updated_at": (datetime,), + } + + attribute_map = { + "conditions": "conditions", + "created_at": "created_at", + "id": "id", + "updated_at": "updated_at", + } + + def __init__(self_, conditions: List[Condition], created_at: datetime, id: UUID, updated_at: datetime, **kwargs): + """ + Targeting rule details. + + :param conditions: Conditions evaluated by this targeting rule. + :type conditions: [Condition] + + :param created_at: The timestamp when the targeting rule was created. + :type created_at: datetime + + :param id: The unique identifier of the targeting rule. + :type id: UUID + + :param updated_at: The timestamp when the targeting rule was last updated. + :type updated_at: datetime + """ + super().__init__(kwargs) + + self_.conditions = conditions + self_.created_at = created_at + self_.id = id + self_.updated_at = updated_at diff --git a/src/datadog_api_client/v2/model/targeting_rule_request.py b/src/datadog_api_client/v2/model/targeting_rule_request.py new file mode 100644 index 0000000000..2d5baa967a --- /dev/null +++ b/src/datadog_api_client/v2/model/targeting_rule_request.py @@ -0,0 +1,46 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import List, TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.condition_request import ConditionRequest + + +class TargetingRuleRequest(ModelNormal): + validations = { + "conditions": { + "min_items": 1, + }, + } + + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.condition_request import ConditionRequest + + return { + "conditions": ([ConditionRequest],), + } + + attribute_map = { + "conditions": "conditions", + } + + def __init__(self_, conditions: List[ConditionRequest], **kwargs): + """ + Targeting rule request payload. + + :param conditions: Conditions that must match for this rule. + :type conditions: [ConditionRequest] + """ + super().__init__(kwargs) + + self_.conditions = conditions diff --git a/src/datadog_api_client/v2/model/upsert_allocation_request.py b/src/datadog_api_client/v2/model/upsert_allocation_request.py new file mode 100644 index 0000000000..8385061495 --- /dev/null +++ b/src/datadog_api_client/v2/model/upsert_allocation_request.py @@ -0,0 +1,118 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import List, Union, TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, + none_type, + unset, + UnsetType, + UUID, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.exposure_schedule_request import ExposureScheduleRequest + from datadog_api_client.v2.model.guardrail_metric_request import GuardrailMetricRequest + from datadog_api_client.v2.model.targeting_rule_request import TargetingRuleRequest + from datadog_api_client.v2.model.allocation_type import AllocationType + from datadog_api_client.v2.model.variant_weight_request import VariantWeightRequest + + +class UpsertAllocationRequest(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.exposure_schedule_request import ExposureScheduleRequest + from datadog_api_client.v2.model.guardrail_metric_request import GuardrailMetricRequest + from datadog_api_client.v2.model.targeting_rule_request import TargetingRuleRequest + from datadog_api_client.v2.model.allocation_type import AllocationType + from datadog_api_client.v2.model.variant_weight_request import VariantWeightRequest + + return { + "experiment_id": (str, none_type), + "exposure_schedule": (ExposureScheduleRequest,), + "guardrail_metrics": ([GuardrailMetricRequest],), + "id": (UUID,), + "key": (str,), + "name": (str,), + "targeting_rules": ([TargetingRuleRequest],), + "type": (AllocationType,), + "variant_weights": ([VariantWeightRequest],), + } + + attribute_map = { + "experiment_id": "experiment_id", + "exposure_schedule": "exposure_schedule", + "guardrail_metrics": "guardrail_metrics", + "id": "id", + "key": "key", + "name": "name", + "targeting_rules": "targeting_rules", + "type": "type", + "variant_weights": "variant_weights", + } + + def __init__( + self_, + key: str, + name: str, + type: AllocationType, + experiment_id: Union[str, none_type, UnsetType] = unset, + exposure_schedule: Union[ExposureScheduleRequest, UnsetType] = unset, + guardrail_metrics: Union[List[GuardrailMetricRequest], UnsetType] = unset, + id: Union[UUID, UnsetType] = unset, + targeting_rules: Union[List[TargetingRuleRequest], UnsetType] = unset, + variant_weights: Union[List[VariantWeightRequest], UnsetType] = unset, + **kwargs, + ): + """ + Request to create or update a targeting rule (allocation) for a feature flag environment. + + :param experiment_id: The experiment ID for experiment-linked allocations. + :type experiment_id: str, none_type, optional + + :param exposure_schedule: Progressive release request payload. + :type exposure_schedule: ExposureScheduleRequest, optional + + :param guardrail_metrics: Guardrail metrics used to monitor and auto-pause or abort. + :type guardrail_metrics: [GuardrailMetricRequest], optional + + :param id: The unique identifier of the targeting rule allocation. + :type id: UUID, optional + + :param key: The unique key of the targeting rule allocation. + :type key: str + + :param name: The display name of the targeting rule. + :type name: str + + :param targeting_rules: Targeting rules that determine audience eligibility. + :type targeting_rules: [TargetingRuleRequest], optional + + :param type: The type of targeting rule (called allocation in the API model). + :type type: AllocationType + + :param variant_weights: Variant distribution weights. + :type variant_weights: [VariantWeightRequest], optional + """ + if experiment_id is not unset: + kwargs["experiment_id"] = experiment_id + if exposure_schedule is not unset: + kwargs["exposure_schedule"] = exposure_schedule + if guardrail_metrics is not unset: + kwargs["guardrail_metrics"] = guardrail_metrics + if id is not unset: + kwargs["id"] = id + if targeting_rules is not unset: + kwargs["targeting_rules"] = targeting_rules + if variant_weights is not unset: + kwargs["variant_weights"] = variant_weights + super().__init__(kwargs) + + self_.key = key + self_.name = name + self_.type = type diff --git a/src/datadog_api_client/v2/model/variant_weight.py b/src/datadog_api_client/v2/model/variant_weight.py new file mode 100644 index 0000000000..e455051a90 --- /dev/null +++ b/src/datadog_api_client/v2/model/variant_weight.py @@ -0,0 +1,87 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import Union, TYPE_CHECKING + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, + datetime, + unset, + UnsetType, + UUID, +) + + +if TYPE_CHECKING: + from datadog_api_client.v2.model.variant import Variant + + +class VariantWeight(ModelNormal): + @cached_property + def openapi_types(_): + from datadog_api_client.v2.model.variant import Variant + + return { + "created_at": (datetime,), + "id": (UUID,), + "updated_at": (datetime,), + "value": (float,), + "variant": (Variant,), + "variant_id": (UUID,), + } + + attribute_map = { + "created_at": "created_at", + "id": "id", + "updated_at": "updated_at", + "value": "value", + "variant": "variant", + "variant_id": "variant_id", + } + + def __init__( + self_, + value: float, + variant_id: UUID, + created_at: Union[datetime, UnsetType] = unset, + id: Union[UUID, UnsetType] = unset, + updated_at: Union[datetime, UnsetType] = unset, + variant: Union[Variant, UnsetType] = unset, + **kwargs, + ): + """ + Variant weight details. + + :param created_at: The timestamp when the variant weight was created. + :type created_at: datetime, optional + + :param id: Unique identifier of the variant weight assignment. + :type id: UUID, optional + + :param updated_at: The timestamp when the variant weight was last updated. + :type updated_at: datetime, optional + + :param value: The percentage weight for the variant. + :type value: float + + :param variant: A variant of a feature flag. + :type variant: Variant, optional + + :param variant_id: The variant ID. + :type variant_id: UUID + """ + if created_at is not unset: + kwargs["created_at"] = created_at + if id is not unset: + kwargs["id"] = id + if updated_at is not unset: + kwargs["updated_at"] = updated_at + if variant is not unset: + kwargs["variant"] = variant + super().__init__(kwargs) + + self_.value = value + self_.variant_id = variant_id diff --git a/src/datadog_api_client/v2/model/variant_weight_request.py b/src/datadog_api_client/v2/model/variant_weight_request.py new file mode 100644 index 0000000000..7776dcc9fc --- /dev/null +++ b/src/datadog_api_client/v2/model/variant_weight_request.py @@ -0,0 +1,57 @@ +# Unless explicitly stated otherwise all files in this repository are licensed under the Apache-2.0 License. +# This product includes software developed at Datadog (https://www.datadoghq.com/). +# Copyright 2019-Present Datadog, Inc. +from __future__ import annotations + +from typing import Union + +from datadog_api_client.model_utils import ( + ModelNormal, + cached_property, + unset, + UnsetType, + UUID, +) + + +class VariantWeightRequest(ModelNormal): + @cached_property + def openapi_types(_): + return { + "value": (float,), + "variant_id": (UUID,), + "variant_key": (str,), + } + + attribute_map = { + "value": "value", + "variant_id": "variant_id", + "variant_key": "variant_key", + } + + def __init__( + self_, + value: float, + variant_id: Union[UUID, UnsetType] = unset, + variant_key: Union[str, UnsetType] = unset, + **kwargs, + ): + """ + Variant weight request payload. + + :param value: The percentage weight for this variant. + :type value: float + + :param variant_id: The variant ID to assign weight to. + :type variant_id: UUID, optional + + :param variant_key: The variant key to assign weight to. + :type variant_key: str, optional + """ + if variant_id is not unset: + kwargs["variant_id"] = variant_id + if variant_key is not unset: + kwargs["variant_key"] = variant_key + super().__init__(kwargs) + + self_.value = value diff --git a/src/datadog_api_client/v2/models/__init__.py b/src/datadog_api_client/v2/models/__init__.py index 50b1f6b750..22f4a4d800 100644 --- a/src/datadog_api_client/v2/models/__init__.py +++ b/src/datadog_api_client/v2/models/__init__.py @@ -168,6 +168,18 @@ ) from datadog_api_client.v2.model.alert_event_custom_attributes_priority import AlertEventCustomAttributesPriority from datadog_api_client.v2.model.alert_event_custom_attributes_status import AlertEventCustomAttributesStatus +from datadog_api_client.v2.model.allocation import Allocation +from datadog_api_client.v2.model.allocation_data_request import AllocationDataRequest +from datadog_api_client.v2.model.allocation_data_response import AllocationDataResponse +from datadog_api_client.v2.model.allocation_data_type import AllocationDataType +from datadog_api_client.v2.model.allocation_exposure_guardrail_trigger import AllocationExposureGuardrailTrigger +from datadog_api_client.v2.model.allocation_exposure_rollout_step import AllocationExposureRolloutStep +from datadog_api_client.v2.model.allocation_exposure_schedule import AllocationExposureSchedule +from datadog_api_client.v2.model.allocation_exposure_schedule_data import AllocationExposureScheduleData +from datadog_api_client.v2.model.allocation_exposure_schedule_data_type import AllocationExposureScheduleDataType +from datadog_api_client.v2.model.allocation_exposure_schedule_response import AllocationExposureScheduleResponse +from datadog_api_client.v2.model.allocation_response import AllocationResponse +from datadog_api_client.v2.model.allocation_type import AllocationType from datadog_api_client.v2.model.annotation import Annotation from datadog_api_client.v2.model.annotation_display import AnnotationDisplay from datadog_api_client.v2.model.annotation_display_bounds import AnnotationDisplayBounds @@ -1007,6 +1019,9 @@ from datadog_api_client.v2.model.component_properties_is_visible import ComponentPropertiesIsVisible from datadog_api_client.v2.model.component_recommendation import ComponentRecommendation from datadog_api_client.v2.model.component_type import ComponentType +from datadog_api_client.v2.model.condition import Condition +from datadog_api_client.v2.model.condition_operator import ConditionOperator +from datadog_api_client.v2.model.condition_request import ConditionRequest from datadog_api_client.v2.model.config_cat_credentials import ConfigCatCredentials from datadog_api_client.v2.model.config_cat_credentials_update import ConfigCatCredentialsUpdate from datadog_api_client.v2.model.config_cat_integration import ConfigCatIntegration @@ -1112,6 +1127,7 @@ from datadog_api_client.v2.model.cpu import Cpu from datadog_api_client.v2.model.create_action_connection_request import CreateActionConnectionRequest from datadog_api_client.v2.model.create_action_connection_response import CreateActionConnectionResponse +from datadog_api_client.v2.model.create_allocations_request import CreateAllocationsRequest from datadog_api_client.v2.model.create_app_request import CreateAppRequest from datadog_api_client.v2.model.create_app_request_data import CreateAppRequestData from datadog_api_client.v2.model.create_app_request_data_attributes import CreateAppRequestDataAttributes @@ -2080,6 +2096,8 @@ from datadog_api_client.v2.model.events_sort_type import EventsSortType from datadog_api_client.v2.model.events_timeseries_query import EventsTimeseriesQuery from datadog_api_client.v2.model.events_warning import EventsWarning +from datadog_api_client.v2.model.exposure_rollout_step_request import ExposureRolloutStepRequest +from datadog_api_client.v2.model.exposure_schedule_request import ExposureScheduleRequest from datadog_api_client.v2.model.facet_info_request import FacetInfoRequest from datadog_api_client.v2.model.facet_info_request_data import FacetInfoRequestData from datadog_api_client.v2.model.facet_info_request_data_attributes import FacetInfoRequestDataAttributes @@ -2457,6 +2475,9 @@ from datadog_api_client.v2.model.grey_noise_integration_update import GreyNoiseIntegrationUpdate from datadog_api_client.v2.model.group_scalar_column import GroupScalarColumn from datadog_api_client.v2.model.group_tags import GroupTags +from datadog_api_client.v2.model.guardrail_metric import GuardrailMetric +from datadog_api_client.v2.model.guardrail_metric_request import GuardrailMetricRequest +from datadog_api_client.v2.model.guardrail_trigger_action import GuardrailTriggerAction from datadog_api_client.v2.model.http_body import HTTPBody from datadog_api_client.v2.model.httpcd_gates_bad_request_response import HTTPCDGatesBadRequestResponse from datadog_api_client.v2.model.httpcd_gates_not_found_response import HTTPCDGatesNotFoundResponse @@ -3056,6 +3077,7 @@ from datadog_api_client.v2.model.list_apis_response_data_attributes import ListAPIsResponseDataAttributes from datadog_api_client.v2.model.list_apis_response_meta import ListAPIsResponseMeta from datadog_api_client.v2.model.list_apis_response_meta_pagination import ListAPIsResponseMetaPagination +from datadog_api_client.v2.model.list_allocations_response import ListAllocationsResponse from datadog_api_client.v2.model.list_app_key_registrations_response import ListAppKeyRegistrationsResponse from datadog_api_client.v2.model.list_app_key_registrations_response_meta import ListAppKeyRegistrationsResponseMeta from datadog_api_client.v2.model.list_application_keys_response import ListApplicationKeysResponse @@ -4431,6 +4453,7 @@ from datadog_api_client.v2.model.output_schema import OutputSchema from datadog_api_client.v2.model.output_schema_parameters import OutputSchemaParameters from datadog_api_client.v2.model.output_schema_parameters_type import OutputSchemaParametersType +from datadog_api_client.v2.model.overwrite_allocations_request import OverwriteAllocationsRequest from datadog_api_client.v2.model.page_urgency import PageUrgency from datadog_api_client.v2.model.pagination import Pagination from datadog_api_client.v2.model.pagination_meta import PaginationMeta @@ -4944,6 +4967,9 @@ from datadog_api_client.v2.model.roles_response import RolesResponse from datadog_api_client.v2.model.roles_sort import RolesSort from datadog_api_client.v2.model.roles_type import RolesType +from datadog_api_client.v2.model.rollout_options import RolloutOptions +from datadog_api_client.v2.model.rollout_options_request import RolloutOptionsRequest +from datadog_api_client.v2.model.rollout_strategy import RolloutStrategy from datadog_api_client.v2.model.routing_rule import RoutingRule from datadog_api_client.v2.model.routing_rule_action import RoutingRuleAction from datadog_api_client.v2.model.routing_rule_attributes import RoutingRuleAttributes @@ -6221,6 +6247,8 @@ from datadog_api_client.v2.model.table_row_resource_data_type import TableRowResourceDataType from datadog_api_client.v2.model.table_row_resource_identifier import TableRowResourceIdentifier from datadog_api_client.v2.model.tags_event_attribute import TagsEventAttribute +from datadog_api_client.v2.model.targeting_rule import TargetingRule +from datadog_api_client.v2.model.targeting_rule_request import TargetingRuleRequest from datadog_api_client.v2.model.team import Team from datadog_api_client.v2.model.team_attributes import TeamAttributes from datadog_api_client.v2.model.team_connection import TeamConnection @@ -6609,6 +6637,7 @@ from datadog_api_client.v2.model.update_tenancy_config_request import UpdateTenancyConfigRequest from datadog_api_client.v2.model.update_workflow_request import UpdateWorkflowRequest from datadog_api_client.v2.model.update_workflow_response import UpdateWorkflowResponse +from datadog_api_client.v2.model.upsert_allocation_request import UpsertAllocationRequest from datadog_api_client.v2.model.upsert_catalog_entity_request import UpsertCatalogEntityRequest from datadog_api_client.v2.model.upsert_catalog_entity_response import UpsertCatalogEntityResponse from datadog_api_client.v2.model.upsert_catalog_entity_response_included_item import ( @@ -6686,6 +6715,8 @@ from datadog_api_client.v2.model.validation_response import ValidationResponse from datadog_api_client.v2.model.value_type import ValueType from datadog_api_client.v2.model.variant import Variant +from datadog_api_client.v2.model.variant_weight import VariantWeight +from datadog_api_client.v2.model.variant_weight_request import VariantWeightRequest from datadog_api_client.v2.model.version_history_update import VersionHistoryUpdate from datadog_api_client.v2.model.version_history_update_type import VersionHistoryUpdateType from datadog_api_client.v2.model.viewership_history_session_array import ViewershipHistorySessionArray @@ -6920,6 +6951,18 @@ "AlertEventCustomAttributesLinksItemsCategory", "AlertEventCustomAttributesPriority", "AlertEventCustomAttributesStatus", + "Allocation", + "AllocationDataRequest", + "AllocationDataResponse", + "AllocationDataType", + "AllocationExposureGuardrailTrigger", + "AllocationExposureRolloutStep", + "AllocationExposureSchedule", + "AllocationExposureScheduleData", + "AllocationExposureScheduleDataType", + "AllocationExposureScheduleResponse", + "AllocationResponse", + "AllocationType", "Annotation", "AnnotationDisplay", "AnnotationDisplayBounds", @@ -7521,6 +7564,9 @@ "ComponentPropertiesIsVisible", "ComponentRecommendation", "ComponentType", + "Condition", + "ConditionOperator", + "ConditionRequest", "ConfigCatCredentials", "ConfigCatCredentialsUpdate", "ConfigCatIntegration", @@ -7618,6 +7664,7 @@ "Cpu", "CreateActionConnectionRequest", "CreateActionConnectionResponse", + "CreateAllocationsRequest", "CreateAppRequest", "CreateAppRequestData", "CreateAppRequestDataAttributes", @@ -8282,6 +8329,8 @@ "EventsSortType", "EventsTimeseriesQuery", "EventsWarning", + "ExposureRolloutStepRequest", + "ExposureScheduleRequest", "FacetInfoRequest", "FacetInfoRequestData", "FacetInfoRequestDataAttributes", @@ -8595,6 +8644,9 @@ "GreyNoiseIntegrationUpdate", "GroupScalarColumn", "GroupTags", + "GuardrailMetric", + "GuardrailMetricRequest", + "GuardrailTriggerAction", "HTTPBody", "HTTPCDGatesBadRequestResponse", "HTTPCDGatesNotFoundResponse", @@ -9080,6 +9132,7 @@ "ListAPIsResponseDataAttributes", "ListAPIsResponseMeta", "ListAPIsResponseMetaPagination", + "ListAllocationsResponse", "ListAppKeyRegistrationsResponse", "ListAppKeyRegistrationsResponseMeta", "ListApplicationKeysResponse", @@ -9849,6 +9902,7 @@ "OutputSchema", "OutputSchemaParameters", "OutputSchemaParametersType", + "OverwriteAllocationsRequest", "PageUrgency", "Pagination", "PaginationMeta", @@ -10260,6 +10314,9 @@ "RolesResponse", "RolesSort", "RolesType", + "RolloutOptions", + "RolloutOptionsRequest", + "RolloutStrategy", "RoutingRule", "RoutingRuleAction", "RoutingRuleAttributes", @@ -11117,6 +11174,8 @@ "TableRowResourceDataType", "TableRowResourceIdentifier", "TagsEventAttribute", + "TargetingRule", + "TargetingRuleRequest", "Team", "TeamAttributes", "TeamConnection", @@ -11401,6 +11460,7 @@ "UpdateTenancyConfigRequest", "UpdateWorkflowRequest", "UpdateWorkflowResponse", + "UpsertAllocationRequest", "UpsertCatalogEntityRequest", "UpsertCatalogEntityResponse", "UpsertCatalogEntityResponseIncludedItem", @@ -11474,6 +11534,8 @@ "ValidationResponse", "ValueType", "Variant", + "VariantWeight", + "VariantWeightRequest", "VersionHistoryUpdate", "VersionHistoryUpdateType", "ViewershipHistorySessionArray", diff --git a/tests/v2/cassettes/test_scenarios/test_create_allocation_for_a_flag_in_an_environment_returns_created_response.frozen b/tests/v2/cassettes/test_scenarios/test_create_allocation_for_a_flag_in_an_environment_returns_created_response.frozen new file mode 100644 index 0000000000..7f87fe7c2d --- /dev/null +++ b/tests/v2/cassettes/test_scenarios/test_create_allocation_for_a_flag_in_an_environment_returns_created_response.frozen @@ -0,0 +1 @@ +2026-04-01T20:36:45.896Z \ No newline at end of file diff --git a/tests/v2/cassettes/test_scenarios/test_create_allocation_for_a_flag_in_an_environment_returns_created_response.yaml b/tests/v2/cassettes/test_scenarios/test_create_allocation_for_a_flag_in_an_environment_returns_created_response.yaml new file mode 100644 index 0000000000..ff47159abc --- /dev/null +++ b/tests/v2/cassettes/test_scenarios/test_create_allocation_for_a_flag_in_an_environment_returns_created_response.yaml @@ -0,0 +1,118 @@ +interactions: +- request: + body: '{"data":{"attributes":{"description":"Test feature flag for BDD scenarios","key":"test-feature-flag-Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805","name":"Test + Feature Flag Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805","value_type":"BOOLEAN","variants":[{"key":"variant-Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805-1","name":"Variant + Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805 + A","value":"true"},{"key":"variant-Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805-2","name":"Variant + Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805 + B","value":"false"}]},"type":"feature-flags"}}' + headers: + accept: + - application/json + content-type: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v2/feature-flags + response: + body: + string: '{"data":{"id":"449ff1d1-7a4f-416f-a6ce-be1abd3031c1","type":"feature-flags","attributes":{"archived_at":null,"created_at":"2026-04-01T20:36:46.153578Z","created_by":"3ad549bf-eba0-11e9-a77a-0705486660d0","description":"Test + feature flag for BDD scenarios","distribution_channel":"ALL","feature_flag_environments":[{"environment_id":"592600c2-8327-424d-960f-608c327ee96d","environment_name":"Test + Environment Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774470658","environment_queries":["test-Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774470658","env-Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774470658"],"status":"DISABLED","default_variant_id":"4fda6911-d77b-4ca7-ba8d-daa41622e051","override_variant_id":null,"default_allocation_key":"allocation-default-9bfe74798563","override_allocation_key":"allocation-override-9bfe74798563","rules":[],"rollout_percentage":0,"allocations":null,"is_production":false,"require_feature_flag_approval":false,"pending_suggestion_id":null},{"environment_id":"809cd83d-51ac-4f60-9ce5-cfad4d662114","environment_name":"Test + Environment Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774471346","environment_queries":["test-Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774471346","env-Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774471346"],"status":"DISABLED","default_variant_id":"4fda6911-d77b-4ca7-ba8d-daa41622e051","override_variant_id":null,"default_allocation_key":"allocation-default-04b9843f6754","override_allocation_key":"allocation-override-04b9843f6754","rules":[],"rollout_percentage":0,"allocations":null,"is_production":false,"require_feature_flag_approval":false,"pending_suggestion_id":null},{"environment_id":"21c84268-9fc7-4b6d-82ea-bb2090469aba","environment_name":"Test + Environment Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774472385","environment_queries":["test-Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774472385","env-Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774472385"],"status":"DISABLED","default_variant_id":"4fda6911-d77b-4ca7-ba8d-daa41622e051","override_variant_id":null,"default_allocation_key":"allocation-default-ac33b80880b1","override_allocation_key":"allocation-override-ac33b80880b1","rules":[],"rollout_percentage":0,"allocations":null,"is_production":false,"require_feature_flag_approval":false,"pending_suggestion_id":null},{"environment_id":"0b94dbaa-9efb-419d-8bd7-ef56f3828986","environment_name":"Test + Environment Test-Typescript-Create_an_environment_returns_Created_response-1773321543","environment_queries":["staging","test"],"status":"DISABLED","default_variant_id":"4fda6911-d77b-4ca7-ba8d-daa41622e051","override_variant_id":null,"default_allocation_key":"allocation-default-1018a5595c76","override_allocation_key":"allocation-override-1018a5595c76","rules":[],"rollout_percentage":0,"allocations":null,"is_production":false,"require_feature_flag_approval":false,"pending_suggestion_id":null},{"environment_id":"afdaa512-6307-4965-bf92-62cc6bea5d00","environment_name":"Test + Environment Test-Typescript-Create_an_environment_returns_Created_response-1773322166","environment_queries":["test-Test-Typescript-Create_an_environment_returns_Created_response-1773322166","env-Test-Typescript-Create_an_environment_returns_Created_response-1773322166"],"status":"DISABLED","default_variant_id":"4fda6911-d77b-4ca7-ba8d-daa41622e051","override_variant_id":null,"default_allocation_key":"allocation-default-9cf98d18b2bc","override_allocation_key":"allocation-override-9cf98d18b2bc","rules":[],"rollout_percentage":0,"allocations":null,"is_production":false,"require_feature_flag_approval":false,"pending_suggestion_id":null}],"key":"test-feature-flag-Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805","last_updated_by":"3ad549bf-eba0-11e9-a77a-0705486660d0","name":"Test + Feature Flag Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805","require_approval":false,"tags":[],"updated_at":"2026-04-01T20:36:46.153578Z","value_type":"BOOLEAN","variants":[{"id":"4fda6911-d77b-4ca7-ba8d-daa41622e051","key":"variant-Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805-1","name":"Variant + Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805 + A","value":"true","created_at":"2026-04-01T20:36:46.172226Z","updated_at":"2026-04-01T20:36:46.172226Z"},{"id":"b8079ed4-249a-42fb-b9ec-ff95900c37af","key":"variant-Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805-2","name":"Variant + Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805 + B","value":"false","created_at":"2026-04-01T20:36:46.181731Z","updated_at":"2026-04-01T20:36:46.181731Z"}]}}}' + headers: + content-type: + - application/vnd.api+json + status: + code: 201 + message: Created +- request: + body: '{"data":{"attributes":{"name":"Test Environment Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805","queries":["test-Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805","env-Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805"]},"type":"environments"}}' + headers: + accept: + - application/json + content-type: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v2/feature-flags/environments + response: + body: + string: '{"data":{"id":"927d4fe0-11f9-4a08-8859-ae044a4e04f0","type":"environments","attributes":{"is_production":false,"name":"Test + Environment Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805","queries":["test-Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805","env-Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805"],"require_feature_flag_approval":false}}}' + headers: + content-type: + - application/vnd.api+json + status: + code: 201 + message: Created +- request: + body: '{"data":{"attributes":{"guardrail_metrics":[],"key":"new-targeting-rule-test-create_allocation_for_a_flag_in_an_environment_returns_created_response-1775075805","name":"New + targeting rule Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805","targeting_rules":[],"type":"CANARY","variant_weights":[{"value":100,"variant_id":"4fda6911-d77b-4ca7-ba8d-daa41622e051"}]},"type":"allocations"}}' + headers: + accept: + - application/json + content-type: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v2/feature-flags/449ff1d1-7a4f-416f-a6ce-be1abd3031c1/environments/927d4fe0-11f9-4a08-8859-ae044a4e04f0/allocations + response: + body: + string: '{"data":{"id":"adb0e4b9-2c9f-4ce0-bc77-68c11d5e1ba2","type":"allocations","attributes":{"created_at":"2026-04-01T20:36:47.111398323Z","environment_ids":["927d4fe0-11f9-4a08-8859-ae044a4e04f0"],"experiment_id":null,"guardrail_metrics":[],"key":"new-targeting-rule-test-create_allocation_for_a_flag_in_an_environment_returns_created_response-1775075805","name":"New + targeting rule Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805","order_position":0,"targeting_rules":[],"type":"CANARY","updated_at":"2026-04-01T20:36:47.111398323Z","variant_weights":[{"id":"9c5fccaf-ca32-49dd-8a48-5a47a6204cc4","created_at":"2026-04-01T20:36:47.119918Z","updated_at":"2026-04-01T20:36:47.119918Z","value":100,"variant_id":"4fda6911-d77b-4ca7-ba8d-daa41622e051","variant":{"id":"4fda6911-d77b-4ca7-ba8d-daa41622e051","key":"variant-Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805-1","name":"Variant + Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805 + A","value":"true","created_at":"2026-04-01T20:36:46.172226Z","updated_at":"2026-04-01T20:36:46.172226Z"}}]}}}' + headers: + content-type: + - application/vnd.api+json + status: + code: 201 + message: Created +- request: + body: null + headers: + accept: + - '*/*' + method: DELETE + uri: https://api.datadoghq.com/api/v2/feature-flags/environments/927d4fe0-11f9-4a08-8859-ae044a4e04f0 + response: + body: + string: '' + headers: {} + status: + code: 204 + message: No Content +- request: + body: null + headers: + accept: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v2/feature-flags/449ff1d1-7a4f-416f-a6ce-be1abd3031c1/archive + response: + body: + string: '{"data":{"id":"449ff1d1-7a4f-416f-a6ce-be1abd3031c1","type":"feature-flags","attributes":{"archived_at":"2026-04-01T20:36:47.922174Z","created_at":"2026-04-01T20:36:46.153578Z","created_by":"3ad549bf-eba0-11e9-a77a-0705486660d0","description":"Test + feature flag for BDD scenarios","distribution_channel":"ALL","feature_flag_environments":[{"environment_id":"592600c2-8327-424d-960f-608c327ee96d","environment_name":"Test + Environment Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774470658","environment_queries":["test-Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774470658","env-Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774470658"],"status":"DISABLED","default_variant_id":"4fda6911-d77b-4ca7-ba8d-daa41622e051","override_variant_id":null,"default_allocation_key":"allocation-default-9bfe74798563","override_allocation_key":"allocation-override-9bfe74798563","rules":[],"rollout_percentage":0,"allocations":null,"is_production":false,"require_feature_flag_approval":false,"pending_suggestion_id":null},{"environment_id":"809cd83d-51ac-4f60-9ce5-cfad4d662114","environment_name":"Test + Environment Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774471346","environment_queries":["test-Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774471346","env-Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774471346"],"status":"DISABLED","default_variant_id":"4fda6911-d77b-4ca7-ba8d-daa41622e051","override_variant_id":null,"default_allocation_key":"allocation-default-04b9843f6754","override_allocation_key":"allocation-override-04b9843f6754","rules":[],"rollout_percentage":0,"allocations":null,"is_production":false,"require_feature_flag_approval":false,"pending_suggestion_id":null},{"environment_id":"21c84268-9fc7-4b6d-82ea-bb2090469aba","environment_name":"Test + Environment Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774472385","environment_queries":["test-Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774472385","env-Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774472385"],"status":"DISABLED","default_variant_id":"4fda6911-d77b-4ca7-ba8d-daa41622e051","override_variant_id":null,"default_allocation_key":"allocation-default-ac33b80880b1","override_allocation_key":"allocation-override-ac33b80880b1","rules":[],"rollout_percentage":0,"allocations":null,"is_production":false,"require_feature_flag_approval":false,"pending_suggestion_id":null},{"environment_id":"0b94dbaa-9efb-419d-8bd7-ef56f3828986","environment_name":"Test + Environment Test-Typescript-Create_an_environment_returns_Created_response-1773321543","environment_queries":["staging","test"],"status":"DISABLED","default_variant_id":"4fda6911-d77b-4ca7-ba8d-daa41622e051","override_variant_id":null,"default_allocation_key":"allocation-default-1018a5595c76","override_allocation_key":"allocation-override-1018a5595c76","rules":[],"rollout_percentage":0,"allocations":null,"is_production":false,"require_feature_flag_approval":false,"pending_suggestion_id":null},{"environment_id":"afdaa512-6307-4965-bf92-62cc6bea5d00","environment_name":"Test + Environment Test-Typescript-Create_an_environment_returns_Created_response-1773322166","environment_queries":["test-Test-Typescript-Create_an_environment_returns_Created_response-1773322166","env-Test-Typescript-Create_an_environment_returns_Created_response-1773322166"],"status":"DISABLED","default_variant_id":"4fda6911-d77b-4ca7-ba8d-daa41622e051","override_variant_id":null,"default_allocation_key":"allocation-default-9cf98d18b2bc","override_allocation_key":"allocation-override-9cf98d18b2bc","rules":[],"rollout_percentage":0,"allocations":null,"is_production":false,"require_feature_flag_approval":false,"pending_suggestion_id":null}],"key":"test-feature-flag-Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805","last_updated_by":"3ad549bf-eba0-11e9-a77a-0705486660d0","name":"Test + Feature Flag Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805","require_approval":false,"tags":[],"updated_at":"2026-04-01T20:36:47.922174Z","value_type":"BOOLEAN","variants":[{"id":"4fda6911-d77b-4ca7-ba8d-daa41622e051","key":"variant-Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805-1","name":"Variant + Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805 + A","value":"true","created_at":"2026-04-01T20:36:46.172226Z","updated_at":"2026-04-01T20:36:46.172226Z"},{"id":"b8079ed4-249a-42fb-b9ec-ff95900c37af","key":"variant-Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805-2","name":"Variant + Test-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1775075805 + B","value":"false","created_at":"2026-04-01T20:36:46.181731Z","updated_at":"2026-04-01T20:36:46.181731Z"}]}}}' + headers: + content-type: + - application/vnd.api+json + status: + code: 200 + message: OK +version: 1 diff --git a/tests/v2/cassettes/test_scenarios/test_update_targeting_rules_for_a_flag_in_an_environment_returns_ok_response.frozen b/tests/v2/cassettes/test_scenarios/test_update_targeting_rules_for_a_flag_in_an_environment_returns_ok_response.frozen new file mode 100644 index 0000000000..c59070e48b --- /dev/null +++ b/tests/v2/cassettes/test_scenarios/test_update_targeting_rules_for_a_flag_in_an_environment_returns_ok_response.frozen @@ -0,0 +1 @@ +2026-04-01T20:36:50.944Z \ No newline at end of file diff --git a/tests/v2/cassettes/test_scenarios/test_update_targeting_rules_for_a_flag_in_an_environment_returns_ok_response.yaml b/tests/v2/cassettes/test_scenarios/test_update_targeting_rules_for_a_flag_in_an_environment_returns_ok_response.yaml new file mode 100644 index 0000000000..ecaa3ad0a2 --- /dev/null +++ b/tests/v2/cassettes/test_scenarios/test_update_targeting_rules_for_a_flag_in_an_environment_returns_ok_response.yaml @@ -0,0 +1,118 @@ +interactions: +- request: + body: '{"data":{"attributes":{"description":"Test feature flag for BDD scenarios","key":"test-feature-flag-Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810","name":"Test + Feature Flag Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810","value_type":"BOOLEAN","variants":[{"key":"variant-Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810-1","name":"Variant + Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810 + A","value":"true"},{"key":"variant-Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810-2","name":"Variant + Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810 + B","value":"false"}]},"type":"feature-flags"}}' + headers: + accept: + - application/json + content-type: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v2/feature-flags + response: + body: + string: '{"data":{"id":"ede225ed-3a62-4cb5-b678-73851d56c700","type":"feature-flags","attributes":{"archived_at":null,"created_at":"2026-04-01T20:36:51.103987Z","created_by":"3ad549bf-eba0-11e9-a77a-0705486660d0","description":"Test + feature flag for BDD scenarios","distribution_channel":"ALL","feature_flag_environments":[{"environment_id":"592600c2-8327-424d-960f-608c327ee96d","environment_name":"Test + Environment Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774470658","environment_queries":["test-Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774470658","env-Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774470658"],"status":"DISABLED","default_variant_id":"73ffe05f-ba09-46c0-ba5e-9d14b1da564f","override_variant_id":null,"default_allocation_key":"allocation-default-2950ef4bf91c","override_allocation_key":"allocation-override-2950ef4bf91c","rules":[],"rollout_percentage":0,"allocations":null,"is_production":false,"require_feature_flag_approval":false,"pending_suggestion_id":null},{"environment_id":"809cd83d-51ac-4f60-9ce5-cfad4d662114","environment_name":"Test + Environment Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774471346","environment_queries":["test-Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774471346","env-Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774471346"],"status":"DISABLED","default_variant_id":"73ffe05f-ba09-46c0-ba5e-9d14b1da564f","override_variant_id":null,"default_allocation_key":"allocation-default-f27ec0d632e1","override_allocation_key":"allocation-override-f27ec0d632e1","rules":[],"rollout_percentage":0,"allocations":null,"is_production":false,"require_feature_flag_approval":false,"pending_suggestion_id":null},{"environment_id":"21c84268-9fc7-4b6d-82ea-bb2090469aba","environment_name":"Test + Environment Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774472385","environment_queries":["test-Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774472385","env-Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774472385"],"status":"DISABLED","default_variant_id":"73ffe05f-ba09-46c0-ba5e-9d14b1da564f","override_variant_id":null,"default_allocation_key":"allocation-default-7c7249a02089","override_allocation_key":"allocation-override-7c7249a02089","rules":[],"rollout_percentage":0,"allocations":null,"is_production":false,"require_feature_flag_approval":false,"pending_suggestion_id":null},{"environment_id":"0b94dbaa-9efb-419d-8bd7-ef56f3828986","environment_name":"Test + Environment Test-Typescript-Create_an_environment_returns_Created_response-1773321543","environment_queries":["staging","test"],"status":"DISABLED","default_variant_id":"73ffe05f-ba09-46c0-ba5e-9d14b1da564f","override_variant_id":null,"default_allocation_key":"allocation-default-c915dfafd596","override_allocation_key":"allocation-override-c915dfafd596","rules":[],"rollout_percentage":0,"allocations":null,"is_production":false,"require_feature_flag_approval":false,"pending_suggestion_id":null},{"environment_id":"afdaa512-6307-4965-bf92-62cc6bea5d00","environment_name":"Test + Environment Test-Typescript-Create_an_environment_returns_Created_response-1773322166","environment_queries":["test-Test-Typescript-Create_an_environment_returns_Created_response-1773322166","env-Test-Typescript-Create_an_environment_returns_Created_response-1773322166"],"status":"DISABLED","default_variant_id":"73ffe05f-ba09-46c0-ba5e-9d14b1da564f","override_variant_id":null,"default_allocation_key":"allocation-default-af80336ddd7c","override_allocation_key":"allocation-override-af80336ddd7c","rules":[],"rollout_percentage":0,"allocations":null,"is_production":false,"require_feature_flag_approval":false,"pending_suggestion_id":null}],"key":"test-feature-flag-Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810","last_updated_by":"3ad549bf-eba0-11e9-a77a-0705486660d0","name":"Test + Feature Flag Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810","require_approval":false,"tags":[],"updated_at":"2026-04-01T20:36:51.103987Z","value_type":"BOOLEAN","variants":[{"id":"73ffe05f-ba09-46c0-ba5e-9d14b1da564f","key":"variant-Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810-1","name":"Variant + Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810 + A","value":"true","created_at":"2026-04-01T20:36:51.109817Z","updated_at":"2026-04-01T20:36:51.109817Z"},{"id":"209acfa7-b3d6-4373-bcb7-162bbe4460c9","key":"variant-Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810-2","name":"Variant + Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810 + B","value":"false","created_at":"2026-04-01T20:36:51.115427Z","updated_at":"2026-04-01T20:36:51.115427Z"}]}}}' + headers: + content-type: + - application/vnd.api+json + status: + code: 201 + message: Created +- request: + body: '{"data":{"attributes":{"name":"Test Environment Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810","queries":["test-Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810","env-Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810"]},"type":"environments"}}' + headers: + accept: + - application/json + content-type: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v2/feature-flags/environments + response: + body: + string: '{"data":{"id":"73900c64-e4c9-46a3-ac5b-d5fa80be2b49","type":"environments","attributes":{"is_production":false,"name":"Test + Environment Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810","queries":["test-Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810","env-Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810"],"require_feature_flag_approval":false}}}' + headers: + content-type: + - application/vnd.api+json + status: + code: 201 + message: Created +- request: + body: '{"data":[{"attributes":{"exposure_schedule":{"rollout_options":{"autostart":false,"selection_interval_ms":86400000,"strategy":"UNIFORM_INTERVALS"},"rollout_steps":[{"exposure_ratio":0.05,"grouped_step_index":0,"interval_ms":null,"is_pause_record":false},{"exposure_ratio":0.25,"grouped_step_index":1,"interval_ms":null,"is_pause_record":false},{"exposure_ratio":1,"grouped_step_index":2,"interval_ms":null,"is_pause_record":false}]},"guardrail_metrics":[],"key":"overwrite-allocation-test-update_targeting_rules_for_a_flag_in_an_environment_returns_ok_response-1775075810","name":"New + targeting rule Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810","targeting_rules":[],"type":"CANARY","variant_weights":[{"value":100,"variant_id":"73ffe05f-ba09-46c0-ba5e-9d14b1da564f"}]},"type":"allocations"}]}' + headers: + accept: + - application/json + content-type: + - application/json + method: PUT + uri: https://api.datadoghq.com/api/v2/feature-flags/ede225ed-3a62-4cb5-b678-73851d56c700/environments/73900c64-e4c9-46a3-ac5b-d5fa80be2b49/allocations + response: + body: + string: '{"data":[{"id":"576deb88-9917-4848-87b1-f9ea276f6bf3","type":"allocations","attributes":{"created_at":"2026-04-01T20:36:51.950824558Z","environment_ids":["73900c64-e4c9-46a3-ac5b-d5fa80be2b49"],"experiment_id":null,"exposure_schedule":{"id":"871b9d47-219d-469d-89de-e9322ad135fd","allocation_id":"576deb88-9917-4848-87b1-f9ea276f6bf3","control_variant_id":null,"absolute_start_time":null,"rollout_options":{"strategy":"UNIFORM_INTERVALS","autostart":false,"selection_interval_ms":86400000},"rollout_steps":[{"id":"92089f1f-3065-447c-a674-a88d38641967","allocation_exposure_schedule_id":"871b9d47-219d-469d-89de-e9322ad135fd","order_position":0,"exposure_ratio":0.05,"interval_ms":86400000,"is_pause_record":false,"grouped_step_index":0,"created_at":"2026-04-01T20:36:51.958618Z","updated_at":"2026-04-01T20:36:51.958618Z"},{"id":"f471ec77-92d2-4d87-9983-e733d53bece5","allocation_exposure_schedule_id":"871b9d47-219d-469d-89de-e9322ad135fd","order_position":1,"exposure_ratio":0.25,"interval_ms":86400000,"is_pause_record":false,"grouped_step_index":1,"created_at":"2026-04-01T20:36:51.958618Z","updated_at":"2026-04-01T20:36:51.958618Z"},{"id":"c32bf3c7-1a30-40aa-811e-a5bcde7c10aa","allocation_exposure_schedule_id":"871b9d47-219d-469d-89de-e9322ad135fd","order_position":2,"exposure_ratio":1,"interval_ms":null,"is_pause_record":false,"grouped_step_index":2,"created_at":"2026-04-01T20:36:51.958618Z","updated_at":"2026-04-01T20:36:51.958618Z"}],"guardrail_triggers":[],"guardrail_triggered_action":null,"created_at":"2026-04-01T20:36:51.955888Z","updated_at":"2026-04-01T20:36:51.955888Z"},"guardrail_metrics":[],"key":"overwrite-allocation-test-update_targeting_rules_for_a_flag_in_an_environment_returns_ok_response-1775075810","name":"New + targeting rule Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810","order_position":0,"targeting_rules":[],"type":"CANARY","updated_at":"2026-04-01T20:36:51.950824558Z","variant_weights":[{"id":"1833845a-a5aa-45a5-a400-57b522edc42f","created_at":"2026-04-01T20:36:51.963476Z","updated_at":"2026-04-01T20:36:51.963476Z","value":100,"variant_id":"73ffe05f-ba09-46c0-ba5e-9d14b1da564f","variant":{"id":"73ffe05f-ba09-46c0-ba5e-9d14b1da564f","key":"variant-Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810-1","name":"Variant + Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810 + A","value":"true","created_at":"2026-04-01T20:36:51.109817Z","updated_at":"2026-04-01T20:36:51.109817Z"}}]}}]}' + headers: + content-type: + - application/vnd.api+json + status: + code: 200 + message: OK +- request: + body: null + headers: + accept: + - '*/*' + method: DELETE + uri: https://api.datadoghq.com/api/v2/feature-flags/environments/73900c64-e4c9-46a3-ac5b-d5fa80be2b49 + response: + body: + string: '' + headers: {} + status: + code: 204 + message: No Content +- request: + body: null + headers: + accept: + - application/json + method: POST + uri: https://api.datadoghq.com/api/v2/feature-flags/ede225ed-3a62-4cb5-b678-73851d56c700/archive + response: + body: + string: '{"data":{"id":"ede225ed-3a62-4cb5-b678-73851d56c700","type":"feature-flags","attributes":{"archived_at":"2026-04-01T20:36:52.682946Z","created_at":"2026-04-01T20:36:51.103987Z","created_by":"3ad549bf-eba0-11e9-a77a-0705486660d0","description":"Test + feature flag for BDD scenarios","distribution_channel":"ALL","feature_flag_environments":[{"environment_id":"592600c2-8327-424d-960f-608c327ee96d","environment_name":"Test + Environment Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774470658","environment_queries":["test-Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774470658","env-Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774470658"],"status":"DISABLED","default_variant_id":"73ffe05f-ba09-46c0-ba5e-9d14b1da564f","override_variant_id":null,"default_allocation_key":"allocation-default-2950ef4bf91c","override_allocation_key":"allocation-override-2950ef4bf91c","rules":[],"rollout_percentage":0,"allocations":null,"is_production":false,"require_feature_flag_approval":false,"pending_suggestion_id":null},{"environment_id":"809cd83d-51ac-4f60-9ce5-cfad4d662114","environment_name":"Test + Environment Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774471346","environment_queries":["test-Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774471346","env-Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774471346"],"status":"DISABLED","default_variant_id":"73ffe05f-ba09-46c0-ba5e-9d14b1da564f","override_variant_id":null,"default_allocation_key":"allocation-default-f27ec0d632e1","override_allocation_key":"allocation-override-f27ec0d632e1","rules":[],"rollout_percentage":0,"allocations":null,"is_production":false,"require_feature_flag_approval":false,"pending_suggestion_id":null},{"environment_id":"21c84268-9fc7-4b6d-82ea-bb2090469aba","environment_name":"Test + Environment Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774472385","environment_queries":["test-Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774472385","env-Test-Typescript-Create_allocation_for_a_flag_in_an_environment_returns_Created_response-1774472385"],"status":"DISABLED","default_variant_id":"73ffe05f-ba09-46c0-ba5e-9d14b1da564f","override_variant_id":null,"default_allocation_key":"allocation-default-7c7249a02089","override_allocation_key":"allocation-override-7c7249a02089","rules":[],"rollout_percentage":0,"allocations":null,"is_production":false,"require_feature_flag_approval":false,"pending_suggestion_id":null},{"environment_id":"0b94dbaa-9efb-419d-8bd7-ef56f3828986","environment_name":"Test + Environment Test-Typescript-Create_an_environment_returns_Created_response-1773321543","environment_queries":["staging","test"],"status":"DISABLED","default_variant_id":"73ffe05f-ba09-46c0-ba5e-9d14b1da564f","override_variant_id":null,"default_allocation_key":"allocation-default-c915dfafd596","override_allocation_key":"allocation-override-c915dfafd596","rules":[],"rollout_percentage":0,"allocations":null,"is_production":false,"require_feature_flag_approval":false,"pending_suggestion_id":null},{"environment_id":"afdaa512-6307-4965-bf92-62cc6bea5d00","environment_name":"Test + Environment Test-Typescript-Create_an_environment_returns_Created_response-1773322166","environment_queries":["test-Test-Typescript-Create_an_environment_returns_Created_response-1773322166","env-Test-Typescript-Create_an_environment_returns_Created_response-1773322166"],"status":"DISABLED","default_variant_id":"73ffe05f-ba09-46c0-ba5e-9d14b1da564f","override_variant_id":null,"default_allocation_key":"allocation-default-af80336ddd7c","override_allocation_key":"allocation-override-af80336ddd7c","rules":[],"rollout_percentage":0,"allocations":null,"is_production":false,"require_feature_flag_approval":false,"pending_suggestion_id":null}],"key":"test-feature-flag-Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810","last_updated_by":"3ad549bf-eba0-11e9-a77a-0705486660d0","name":"Test + Feature Flag Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810","require_approval":false,"tags":[],"updated_at":"2026-04-01T20:36:52.682946Z","value_type":"BOOLEAN","variants":[{"id":"73ffe05f-ba09-46c0-ba5e-9d14b1da564f","key":"variant-Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810-1","name":"Variant + Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810 + A","value":"true","created_at":"2026-04-01T20:36:51.109817Z","updated_at":"2026-04-01T20:36:51.109817Z"},{"id":"209acfa7-b3d6-4373-bcb7-162bbe4460c9","key":"variant-Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810-2","name":"Variant + Test-Update_targeting_rules_for_a_flag_in_an_environment_returns_OK_response-1775075810 + B","value":"false","created_at":"2026-04-01T20:36:51.115427Z","updated_at":"2026-04-01T20:36:51.115427Z"}]}}}' + headers: + content-type: + - application/vnd.api+json + status: + code: 200 + message: OK +version: 1 diff --git a/tests/v2/features/feature_flags.feature b/tests/v2/features/feature_flags.feature index fcf9045b9d..fd2ff16520 100644 --- a/tests/v2/features/feature_flags.feature +++ b/tests/v2/features/feature_flags.feature @@ -53,6 +53,17 @@ Feature: Feature Flags And the response "data.attributes.name" is equal to "Test Feature Flag {{ unique }}" And the response "data.attributes.value_type" is equal to "BOOLEAN" + @team:DataDog/feature-flags + Scenario: Create allocation for a flag in an environment returns "Created" response + Given there is a valid "feature_flag" in the system + And there is a valid "environment" in the system + And new "CreateAllocationsForFeatureFlagInEnvironment" request + And request contains "feature_flag_id" parameter from "feature_flag.data.id" + And request contains "environment_id" parameter from "environment.data.id" + And body with value {"data":{"type":"allocations","attributes":{"name":"New targeting rule {{ unique }}","key":"new-targeting-rule-{{ unique_lower }}","targeting_rules":[],"variant_weights":[{"variant_id":"{{ feature_flag.data.attributes.variants[0].id }}","value":100}],"guardrail_metrics":[],"type":"CANARY"}}} + When the request is sent + Then the response status is 201 Created + @skip @team:DataDog/feature-flags Scenario: Create an environment returns "Bad Request" response Given new "CreateFeatureFlagsEnvironment" request @@ -74,6 +85,51 @@ Feature: Feature Flags When the request is sent Then the response status is 201 Created + @generated @skip @team:DataDog/feature-flags + Scenario: Create targeting rules for a flag env returns "Accepted - Approval required for this change" response + Given new "CreateAllocationsForFeatureFlagInEnvironment" request + And request contains "feature_flag_id" parameter from "REPLACE.ME" + And request contains "environment_id" parameter from "REPLACE.ME" + And body with value {"data": {"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}} + When the request is sent + Then the response status is 202 Accepted - Approval required for this change + + @generated @skip @team:DataDog/feature-flags + Scenario: Create targeting rules for a flag env returns "Bad Request" response + Given new "CreateAllocationsForFeatureFlagInEnvironment" request + And request contains "feature_flag_id" parameter from "REPLACE.ME" + And request contains "environment_id" parameter from "REPLACE.ME" + And body with value {"data": {"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}} + When the request is sent + Then the response status is 400 Bad Request + + @generated @skip @team:DataDog/feature-flags + Scenario: Create targeting rules for a flag env returns "Conflict" response + Given new "CreateAllocationsForFeatureFlagInEnvironment" request + And request contains "feature_flag_id" parameter from "REPLACE.ME" + And request contains "environment_id" parameter from "REPLACE.ME" + And body with value {"data": {"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}} + When the request is sent + Then the response status is 409 Conflict + + @generated @skip @team:DataDog/feature-flags + Scenario: Create targeting rules for a flag env returns "Created" response + Given new "CreateAllocationsForFeatureFlagInEnvironment" request + And request contains "feature_flag_id" parameter from "REPLACE.ME" + And request contains "environment_id" parameter from "REPLACE.ME" + And body with value {"data": {"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}} + When the request is sent + Then the response status is 201 Created + + @generated @skip @team:DataDog/feature-flags + Scenario: Create targeting rules for a flag env returns "Not Found" response + Given new "CreateAllocationsForFeatureFlagInEnvironment" request + And request contains "feature_flag_id" parameter from "REPLACE.ME" + And request contains "environment_id" parameter from "REPLACE.ME" + And body with value {"data": {"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}} + When the request is sent + Then the response status is 404 Not Found + @skip @team:DataDog/feature-flags Scenario: Delete an environment returns "No Content" response Given there is a valid "environment" in the system @@ -190,6 +246,118 @@ Feature: Feature Flags When the request is sent Then the response status is 200 OK + @generated @skip @team:DataDog/feature-flags + Scenario: Pause a progressive rollout returns "Bad Request" response + Given new "PauseExposureSchedule" request + And request contains "exposure_schedule_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 400 Bad Request + + @generated @skip @team:DataDog/feature-flags + Scenario: Pause a progressive rollout returns "Conflict" response + Given new "PauseExposureSchedule" request + And request contains "exposure_schedule_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 409 Conflict + + @generated @skip @team:DataDog/feature-flags + Scenario: Pause a progressive rollout returns "Not Found" response + Given new "PauseExposureSchedule" request + And request contains "exposure_schedule_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 404 Not Found + + @generated @skip @team:DataDog/feature-flags + Scenario: Pause a progressive rollout returns "OK" response + Given new "PauseExposureSchedule" request + And request contains "exposure_schedule_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 200 OK + + @generated @skip @team:DataDog/feature-flags + Scenario: Resume a progressive rollout returns "Bad Request" response + Given new "ResumeExposureSchedule" request + And request contains "exposure_schedule_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 400 Bad Request + + @generated @skip @team:DataDog/feature-flags + Scenario: Resume a progressive rollout returns "Conflict" response + Given new "ResumeExposureSchedule" request + And request contains "exposure_schedule_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 409 Conflict + + @generated @skip @team:DataDog/feature-flags + Scenario: Resume a progressive rollout returns "Not Found" response + Given new "ResumeExposureSchedule" request + And request contains "exposure_schedule_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 404 Not Found + + @generated @skip @team:DataDog/feature-flags + Scenario: Resume a progressive rollout returns "OK" response + Given new "ResumeExposureSchedule" request + And request contains "exposure_schedule_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 200 OK + + @generated @skip @team:DataDog/feature-flags + Scenario: Start a progressive rollout returns "Bad Request" response + Given new "StartExposureSchedule" request + And request contains "exposure_schedule_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 400 Bad Request + + @generated @skip @team:DataDog/feature-flags + Scenario: Start a progressive rollout returns "Conflict" response + Given new "StartExposureSchedule" request + And request contains "exposure_schedule_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 409 Conflict + + @generated @skip @team:DataDog/feature-flags + Scenario: Start a progressive rollout returns "Not Found" response + Given new "StartExposureSchedule" request + And request contains "exposure_schedule_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 404 Not Found + + @generated @skip @team:DataDog/feature-flags + Scenario: Start a progressive rollout returns "OK" response + Given new "StartExposureSchedule" request + And request contains "exposure_schedule_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 200 OK + + @generated @skip @team:DataDog/feature-flags + Scenario: Stop a progressive rollout returns "Bad Request" response + Given new "StopExposureSchedule" request + And request contains "exposure_schedule_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 400 Bad Request + + @generated @skip @team:DataDog/feature-flags + Scenario: Stop a progressive rollout returns "Conflict" response + Given new "StopExposureSchedule" request + And request contains "exposure_schedule_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 409 Conflict + + @generated @skip @team:DataDog/feature-flags + Scenario: Stop a progressive rollout returns "Not Found" response + Given new "StopExposureSchedule" request + And request contains "exposure_schedule_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 404 Not Found + + @generated @skip @team:DataDog/feature-flags + Scenario: Stop a progressive rollout returns "OK" response + Given new "StopExposureSchedule" request + And request contains "exposure_schedule_id" parameter from "REPLACE.ME" + When the request is sent + Then the response status is 200 OK + @skip @team:DataDog/feature-flags Scenario: Unarchive a feature flag returns "Bad Request" response Given new "UnarchiveFeatureFlag" request @@ -263,3 +431,59 @@ Feature: Feature Flags And body with value {"data": {"type": "environments", "attributes": {"name": "Updated Test Environment {{ unique }}", "queries": ["updated-{{ unique }}", "live-{{ unique }}"]}}} When the request is sent Then the response status is 200 OK + + @team:DataDog/feature-flags + Scenario: Update targeting rules for a flag in an environment returns "OK" response + Given there is a valid "feature_flag" in the system + And there is a valid "environment" in the system + And new "UpdateAllocationsForFeatureFlagInEnvironment" request + And request contains "feature_flag_id" parameter from "feature_flag.data.id" + And request contains "environment_id" parameter from "environment.data.id" + And body with value {"data":[{"type":"allocations","attributes":{"key":"overwrite-allocation-{{ unique_lower }}","name":"New targeting rule {{ unique }}","targeting_rules":[],"variant_weights":[{"variant_id":"{{ feature_flag.data.attributes.variants[0].id }}","value":100}],"exposure_schedule":{"rollout_options":{"strategy":"UNIFORM_INTERVALS","autostart":false,"selection_interval_ms":86400000},"rollout_steps":[{"exposure_ratio":0.05,"interval_ms":null,"is_pause_record":false,"grouped_step_index":0},{"exposure_ratio":0.25,"interval_ms":null,"is_pause_record":false,"grouped_step_index":1},{"exposure_ratio":1,"interval_ms":null,"is_pause_record":false,"grouped_step_index":2}]},"guardrail_metrics":[],"type":"CANARY"}}]} + When the request is sent + Then the response status is 200 OK + + @generated @skip @team:DataDog/feature-flags + Scenario: Update targeting rules for a flag returns "Accepted - Approval required for this change" response + Given new "UpdateAllocationsForFeatureFlagInEnvironment" request + And request contains "feature_flag_id" parameter from "REPLACE.ME" + And request contains "environment_id" parameter from "REPLACE.ME" + And body with value {"data": [{"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}]} + When the request is sent + Then the response status is 202 Accepted - Approval required for this change + + @generated @skip @team:DataDog/feature-flags + Scenario: Update targeting rules for a flag returns "Bad Request" response + Given new "UpdateAllocationsForFeatureFlagInEnvironment" request + And request contains "feature_flag_id" parameter from "REPLACE.ME" + And request contains "environment_id" parameter from "REPLACE.ME" + And body with value {"data": [{"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}]} + When the request is sent + Then the response status is 400 Bad Request + + @generated @skip @team:DataDog/feature-flags + Scenario: Update targeting rules for a flag returns "Conflict" response + Given new "UpdateAllocationsForFeatureFlagInEnvironment" request + And request contains "feature_flag_id" parameter from "REPLACE.ME" + And request contains "environment_id" parameter from "REPLACE.ME" + And body with value {"data": [{"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}]} + When the request is sent + Then the response status is 409 Conflict + + @generated @skip @team:DataDog/feature-flags + Scenario: Update targeting rules for a flag returns "Not Found" response + Given new "UpdateAllocationsForFeatureFlagInEnvironment" request + And request contains "feature_flag_id" parameter from "REPLACE.ME" + And request contains "environment_id" parameter from "REPLACE.ME" + And body with value {"data": [{"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}]} + When the request is sent + Then the response status is 404 Not Found + + @generated @skip @team:DataDog/feature-flags + Scenario: Update targeting rules for a flag returns "OK" response + Given new "UpdateAllocationsForFeatureFlagInEnvironment" request + And request contains "feature_flag_id" parameter from "REPLACE.ME" + And request contains "environment_id" parameter from "REPLACE.ME" + And body with value {"data": [{"attributes": {"experiment_id": "550e8400-e29b-41d4-a716-446655440030", "exposure_schedule": {"absolute_start_time": "2025-06-13T12:00:00Z", "control_variant_id": "550e8400-e29b-41d4-a716-446655440012", "control_variant_key": "control", "id": "550e8400-e29b-41d4-a716-446655440010", "rollout_options": {"autostart": false, "selection_interval_ms": 3600000, "strategy": "UNIFORM_INTERVALS"}, "rollout_steps": [{"exposure_ratio": 0.5, "grouped_step_index": 1, "id": "550e8400-e29b-41d4-a716-446655440040", "interval_ms": 3600000, "is_pause_record": false}]}, "guardrail_metrics": [{"metric_id": "metric-error-rate", "trigger_action": "PAUSE"}], "id": "550e8400-e29b-41d4-a716-446655440020", "key": "prod-rollout", "name": "Production Rollout", "targeting_rules": [{"conditions": [{"attribute": "user_tier", "operator": "ONE_OF", "value": ["premium", "enterprise"]}]}], "type": "FEATURE_GATE", "variant_weights": [{"value": 50, "variant_id": "550e8400-e29b-41d4-a716-446655440001", "variant_key": "control"}]}, "type": "allocations"}]} + When the request is sent + Then the response status is 200 OK diff --git a/tests/v2/features/given.json b/tests/v2/features/given.json index 8413be265a..12e386bd8f 100644 --- a/tests/v2/features/given.json +++ b/tests/v2/features/given.json @@ -465,6 +465,27 @@ "tag": "Feature Flags", "operationId": "CreateFeatureFlagsEnvironment" }, + { + "parameters": [ + { + "name": "feature_flag_id", + "source": "feature_flag.data.id" + }, + { + "name": "environment_id", + "source": "environment.data.id" + }, + { + "name": "body", + "value": "{\"data\":[{\"type\":\"allocations\",\"attributes\":{\"name\":\"Exposure Schedule Allocation {{ unique }}\",\"key\":\"exposure-schedule-allocation-{{ unique_lower }}\",\"type\":\"CANARY\",\"targeting_rules\":[],\"variant_weights\":[{\"variant_id\":\"{{ feature_flag.data.attributes.variants[0].id }}\",\"value\":100}],\"exposure_schedule\":{\"rollout_options\":{\"strategy\":\"UNIFORM_INTERVALS\",\"autostart\":false,\"selection_interval_ms\":86400000},\"rollout_steps\":[{\"exposure_ratio\":0.5,\"interval_ms\":null,\"is_pause_record\":false,\"grouped_step_index\":0},{\"exposure_ratio\":1,\"interval_ms\":null,\"is_pause_record\":false,\"grouped_step_index\":1}]},\"guardrail_metrics\":[]}}]}" + } + ], + "source": "data[0].attributes.exposure_schedule", + "step": "there is a valid \"exposure_schedule\" in the system", + "key": "exposure_schedule", + "tag": "Feature Flags", + "operationId": "UpdateAllocationsForFeatureFlagInEnvironment" + }, { "parameters": [ { diff --git a/tests/v2/features/undo.json b/tests/v2/features/undo.json index 8b9940b568..1f11ffb7e7 100644 --- a/tests/v2/features/undo.json +++ b/tests/v2/features/undo.json @@ -1841,6 +1841,30 @@ "type": "idempotent" } }, + "PauseExposureSchedule": { + "tag": "Feature Flags", + "undo": { + "type": "idempotent" + } + }, + "ResumeExposureSchedule": { + "tag": "Feature Flags", + "undo": { + "type": "idempotent" + } + }, + "StartExposureSchedule": { + "tag": "Feature Flags", + "undo": { + "type": "idempotent" + } + }, + "StopExposureSchedule": { + "tag": "Feature Flags", + "undo": { + "type": "idempotent" + } + }, "GetFeatureFlag": { "tag": "Feature Flags", "undo": { @@ -1866,6 +1890,18 @@ "type": "unsafe" } }, + "CreateAllocationsForFeatureFlagInEnvironment": { + "tag": "Feature Flags", + "undo": { + "type": "idempotent" + } + }, + "UpdateAllocationsForFeatureFlagInEnvironment": { + "tag": "Feature Flags", + "undo": { + "type": "idempotent" + } + }, "DisableFeatureFlagEnvironment": { "tag": "Feature Flags", "undo": {