Migration de ressources Terraform

VérifiéSûr

Migrer des ressources Terraform existantes du fournisseur SDK vers Plugin Framework en maintenant la compatibilité d'état et la parité comportementale.

Spar Skills Guide Bot
DeveloppementAvancé
10/03/2026
Claude Code
#terraform#plugin-framework#migration#go#infrastructure-as-code

Recommandé pour

Synthèse automatique

Guide la migration des ressources Terraform existantes du SDK du provider Aiven vers le Plugin Framework via du code généré à partir de YAML, tout en préservant la compatibilité d'état.

Points forts

  • Fournit un workflow étape par étape pour analyser une ressource SDK, repérer les opérations API et cartographier le schéma vers YAML.
  • Inclut des tables de correspondance précises entre les types et attributs du SDK Terraform et leur équivalent YAML.
  • Met l'accent sur la parité de comportement, la compatibilité d'état et la vérification des sources de données qui peuvent utiliser une autre opération API.
  • S'appuie explicitement sur la skill tf-resource-generator pour la génération et les patterns de test.

Limites

  • Dépend fortement de l'organisation interne du dépôt Aiven et de la skill complémentaire tf-resource-generator ; elle n'est pas autonome.
  • Suppose une bonne maîtrise des internes des providers Terraform, de Go et des identifiants d'opérations OpenAPI.
  • Ne détaille pas ici l'implémentation complète des fonctions CRUD, des tests de non-régression ou des fonctions de mise à niveau d'état.
Quand l'utiliser

À utiliser lorsqu'il faut porter une ressource ou une source de données Terraform Aiven existante de terraform-plugin-sdk/v2 vers terraform-plugin-framework.

Quand l'éviter

Ne pas utiliser pour créer une ressource inédite ou pour un provider Terraform autre qu'Aiven ; préférer la skill de génération ou une documentation spécifique au provider.

Analyse de sécurité

Sûr
Score qualité85/100

The skill is a repo-scoped developer workflow (Aiven Terraform provider) with no network exfiltration, no curl|sh, no obfuscated payloads, and no safety-disabling instructions. Tool use (Bash/Grep/Glob/Edit/Write/Task) is appropriate and mostly read-only discovery plus standard build tasks. The only mildly destructive element is the instruction to delete legacy SDK resources after verification, which is a normal but irreversible refactor step and should be done with version control in place.

Points d'attention
  • •Step 'After Migration' instructs deleting SDK resource files and provider registrations (irreversible if uncommitted); scoped to the repo and gated on passing tests/changelog, but an agent should confirm VCS state before deleting
  • •Bash usage is limited to read-only discovery (find/grep/diff/task) plus `task generate`/`task build`, which run repo-defined tasks — acceptable but executes project build scripts
Comment cette analyse est faite

Exemples

Migrate an Aiven resource
Migrate the existing aiven_flink_application resource from internal/sdkprovider to the Plugin Framework. Analyze its schema and CRUD behavior first, then produce the YAML and generated code changes while preserving state compatibility.
Port a data source
Port the aiven_service_integration data source to the Plugin Framework. Check whether it uses a different API operation than the resource and map the SDK schema to YAML.
Map SDK attributes
Convert this legacy Terraform SDK resource to Plugin Framework: ensure forceNew, sensitive, conflictsWith, and nested set fields are mapped correctly, and identify the clientHandler from go-client-codegen.

name: tf-resource-migration description: Migrate existing Terraform resources from SDK provider (sdkprovider) to Plugin Framework. Use when converting legacy resources, ensuring state compatibility, or when the user asks to port/migrate existing resources. allowed-tools: Read, Grep, Glob, Bash, Edit, Write, Task

Terraform Resource Migration Skill

Migrate existing SDK-based resources to Plugin Framework while maintaining state compatibility and behavior parity.

Overview

This skill guides migration of resources from:

  • Source: internal/sdkprovider/ (terraform-plugin-sdk/v2)
  • Target: internal/plugin/ (terraform-plugin-framework) with YAML-generated code

Key Challenge: Preserve exact behavior and state compatibility so users don't experience breaking changes.

Prerequisites: This skill builds on tf-resource-generator. For YAML syntax, generation commands, and testing patterns, see that skill.

When to Use This Skill

Use this skill when:

  • Migrating existing aiven_* resources from SDK to Plugin Framework
  • User says: "migrate", "convert", "port", "move to Plugin Framework"
  • Modernizing legacy resources

Use tf-resource-generator skill when:

  • Creating brand new resources from scratch
  • Adding resources that don't exist yet

Migration Workflow

1. Analyze the Existing SDK Resource

Find the SDK resource:

# Find resource file
find internal/sdkprovider -name "*resource_*.go" | grep -i "resource_name"

# Find data source file
find internal/sdkprovider -name "*datasource_*.go" | grep -i "resource_name"

Read and document:

  • Schema definition (all fields, types, attributes)
  • CRUD functions (Create, Read, Update, Delete)
  • Custom logic and transformations
  • State upgrade functions (if any)
  • Existing tests (critical for parity)

2. Identify API Operations

Check what API operations the SDK resource uses:

# Search for API client calls in the resource
grep -A 5 "client\." internal/sdkprovider/service/resource_name.go

# IMPORTANT: Also check the data source — it may use a different API operation
grep -A 5 "client\." internal/sdkprovider/service/resource_name_data_source.go

Then find corresponding OpenAPI operation IDs. See tf-resource-generator for OpenAPI search patterns.

Determine clientHandler: The clientHandler YAML value is the Go package name under github.com/aiven/go-client-codegen/handler/. Find it by searching for the operation ID in the module cache:

grep -r "OperationID" $(go env GOMODCACHE)/github.com/aiven/go-client-codegen*/handler/

For example, ServiceFlinkCreateApplication lives in handler/flinkapplication/, so clientHandler: flinkapplication.

3. Map SDK Schema to YAML

SDK Type → YAML Type

| SDK Type | YAML Type | |----------|-----------| | schema.TypeString | type: string | | schema.TypeInt | type: integer | | schema.TypeFloat | type: number | | schema.TypeBool | type: boolean | | schema.TypeList | type: arrayOrdered | | schema.TypeSet | type: array (or arrayOrdered for performance) | | schema.TypeMap | additionalProperties: {type: string} |

SDK Attributes → YAML Attributes

| SDK Attribute | YAML Attribute | |---------------|----------------| | Required: true | required: true | | Optional: true | optional: true | | Computed: true | computed: true | | Sensitive: true | sensitive: true | | ForceNew: true | forceNew: true | | ConflictsWith: [] | conflictsWith: [] | | ExactlyOneOf: [] | exactlyOneOf: [] |

Nested Blocks

SDK Set of objects:

"tags": {
    Type:     schema.TypeSet,
    Elem: &schema.Resource{
        Schema: map[string]*schema.Schema{
            "key":   {Type: schema.TypeString},
            "value": {Type: schema.TypeString},
        },
    },
}

YAML (use arrayOrdered for performance):

schema:
  tags:
    type: arrayOrdered
    items:
      type: object
      properties:
        key:
          type: string
        value:
          type: string

4. Preserve ID Structure

CRITICAL: The ID format MUST stay the same for state compatibility.

Find the ID format in SDK code:

# Look for ResourceData.SetId calls
grep -A 2 "SetId" internal/sdkprovider/service/resource_name.go

# Look for ID builder functions
grep -B 5 "buildResourceID\|parseResourceID" internal/sdkprovider/service/resource_name.go

Common ID patterns:

  • Single field: project
  • Composite: project/service_name/database_name

Set in YAML:

idAttributeComposed: [project, service_name, database_name]

5. Handle Custom Logic

Identify in SDK code:

  • StateUpgraders → May need state upgrader in Plugin Framework
  • CustomizeDiff → Use planModifier: true
  • Flatten/Expand functions → Use expandModifier: true / flattenModifier: true

For modifier implementation details, see tf-resource-generator skill.

6. Create YAML Definition

Create definitions/resource_name.yml. For complete YAML syntax reference, see tf-resource-generator skill.

Focus on migration-specific concerns:

  • Match all SDK schema fields exactly
  • Preserve ID structure
  • Copy descriptions from SDK resource

7. Generate and Build

task generate
task build
task lint

8. State Compatibility Verification

CRITICAL: Ensure state is compatible between SDK and Plugin Framework versions.

Check schema version in SDK:

grep -A 3 "SchemaVersion" internal/sdkprovider/service/resource_name.go

If SDK has SchemaVersion > 0, you MUST handle state upgrades.

9. Backward Compatibility Testing

CRITICAL: Test that existing state from SDK version works with Plugin Framework version.

Use acc.BackwardCompatibilitySteps() helper:

func TestAccAivenResource_backwardCompat(t *testing.T) {
    resourceName := "aiven_resource_name.test"
    projectName := acc.ProjectName()

    resource.ParallelTest(t, resource.TestCase{
        PreCheck: func() { acc.TestAccPreCheck(t) },
        Steps: acc.BackwardCompatibilitySteps(t, acc.BackwardCompatConfig{
            TFConfig:           testAccResourceConfig(projectName),
            OldProviderVersion: "4.47.0", // Check CHANGELOG.md for latest
            Checks: resource.ComposeTestCheckFunc(
                resource.TestCheckResourceAttr(resourceName, "project", projectName),
                // Add all key attribute checks
            ),
        }),
    })
}

Find the latest version:

head -20 CHANGELOG.md

What this test does:

  1. Creates resource with OLD SDK provider version
  2. Applies with NEW Plugin Framework version
  3. Verifies state is compatible and attributes match

Example: See internal/plugin/service/mysql/database/database_test.go

10. Parity Testing

CRITICAL: Verify behavior matches SDK resource exactly.

Find SDK tests:

ls internal/sdkprovider/service/*resource_name*_test.go

Ensure Plugin Framework tests cover:

  • All CRUD operations from SDK tests
  • Edge cases
  • Error handling
  • Import functionality
  • Special field behaviors

State Compatibility Checklist

Before marking migration complete:

  • [ ] Resource ID format is identical
  • [ ] All schema fields are present (no removals)
  • [ ] Field types match exactly
  • [ ] Computed fields work the same way
  • [ ] Default values match
  • [ ] Required/Optional flags match
  • [ ] ForceNew behavior matches
  • [ ] Import works with existing IDs
  • [ ] Existing state can be used without migration
  • [ ] Backward compatibility test added using acc.BackwardCompatibilitySteps()
  • [ ] All SDK test scenarios pass with Plugin version
  • [ ] Changelog entry added to CHANGELOG.md

Common Migration Issues

| Issue | Solution | |-------|----------| | ID format changed accidentally | Verify idAttributeComposed matches SDK's ID builder | | Set ordering causes diffs | Use arrayOrdered instead of array | | Computed field becomes required | Keep as computed: true if API provides it | | Custom validation lost | Implement in custom modifier or use schema validation | | State upgrade needed | Implement state upgrader in Plugin Framework | | DiffSuppressFunc behavior | Implement plan modifier for custom diff logic | | Data source lookup key differs from resource ID | Override DataSourceOptions.Read and DataSourceOptions.Schema via init() (see below) | | DiffSuppressFunc behavior | Use planModifier: true for custom diff logic | | Renamed ID field missing in old state | Use planModifier: true to extract from composite ID (see tf-resource-generator skill) | | Read fails with 404 after migration | Likely a renamed ID field is empty — use planModifier to populate it before the API call |

Data Source Lookup Key Differs from Resource ID

The generator derives the data source schema from idAttributeComposed — ID fields become Required, everything else becomes Computed. This works when the data source looks up by the same fields as the resource ID.

Problem: The SDK data source may look up by a different field (e.g., name) than what's in the resource ID (e.g., application_id). The generator has no way to express "the resource ID uses application_id, but the data source should require name."

Detection: Always read the SDK data source implementation. If it uses a List endpoint and filters by a field that's NOT in idAttributeComposed, you need a custom override.

Solution: Create a non-generated file that overrides DataSourceOptions via init():

  1. Override DataSourceOptions.Schema — wrap the generated datasourceSchema() and swap only the attributes that differ (don't duplicate the whole schema)
  2. Override DataSourceOptions.Read — use the List endpoint to find by name, then Get by ID for full details

Key points:

  • Wrap the generated datasourceSchema() — don't duplicate it. Only override the attributes that differ.
  • The read function uses List + filter by name, then Get by ID for full details (same pattern the SDK data source used).
  • This preserves backward compatibility: existing configs using name keep working.

Reference: See internal/plugin/service/flink/application/application.go for a complete implementation.

Migration-Specific Commands

# Find SDK resource
find internal/sdkprovider -name "*resource_*.go" | grep -i "name"

# Analyze SDK schema
grep -A 20 "Schema:" internal/sdkprovider/service/resource.go

# Find SDK ID format
grep -A 2 "SetId" internal/sdkprovider/service/resource.go

# Compare implementations
diff internal/sdkprovider/service/resource.go internal/plugin/service/resource/zz_resource.go

# Run backward compatibility test
task test-acc -- -run TestAccAivenResource_backwardCompat

Key Principles

  1. State compatibility first - Users should not need to recreate resources
  2. Preserve exact behavior - Match SDK resource behavior precisely
  3. Test thoroughly - All SDK test scenarios must pass with Plugin version
  4. Remove SDK version - Once verified, delete SDK resource to avoid maintenance burden

After Migration

Once all tests pass and state compatibility is verified:

  1. Remove SDK resource - Delete from internal/sdkprovider/ and remove provider registration
  2. Update documentation - Ensure docs reflect the Plugin Framework version
  3. Add migration notes if needed - Document any unavoidable behavioral differences
  4. Add changelog entry - Add record to CHANGELOG.md under the unreleased section:
- Migrate `aiven_resource_name` to the Plugin Framework

Do not maintain both versions - this creates maintenance burden and user confusion.

Du fichier au premier essai

Le téléchargement contient exactement le contenu affiché sur cette fiche. Cette copie peut différer de la dernière version du dépôt source.

Consulter la source et ses fichiers annexes

Ce téléchargement contient uniquement SKILL.md. Les scripts, références, modèles et dépendances éventuels ne sont pas inclus. Récupérez les fichiers nécessaires depuis la source en conservant leur arborescence avant de poursuivre.

1. Télécharger le fichier

Télécharger SKILL.md

Depuis la racine d’un projet de test, enregistrez le fichier sous .skill-downloads/terraform-resource-migration-mmk3nhss/SKILL.md, ou utilisez la commande suivante. Ce dossier sert à examiner la skill avant son installation.

Commande pour macOS/Linux ou WSL : un shell POSIX et curl sont nécessaires. Sous Windows sans WSL, utilisez le bouton de téléchargement et créez le dossier manuellement.

mkdir -p '.skill-downloads/terraform-resource-migration-mmk3nhss' && curl --fail --show-error --location 'https://skills-guides.com/api/skills/terraform-resource-migration-mmk3nhss/download' --output '.skill-downloads/terraform-resource-migration-mmk3nhss/SKILL.md.part' && mv '.skill-downloads/terraform-resource-migration-mmk3nhss/SKILL.md.part' '.skill-downloads/terraform-resource-migration-mmk3nhss/SKILL.md'

2. Vérifier les prérequis

Lisez SKILL.md avant de l’utiliser. Si le fichier cite des scripts ou services externes, examinez-les et préparez les accès nécessaires dans votre environnement de test.

Outils déclarés par l’auteur (à vérifier dans votre agent) : Read, Grep, Glob, Bash, Edit, Write, Task

Aucune section de prérequis reconnue dans ce fichier. Cela ne signifie pas qu’il est autonome : les bibliothèques, outils et accès peuvent être cités ailleurs dans le contenu ou dans le dépôt source.

Les plateformes de la fiche sont des indications du catalogue. Les chemins ci-dessous suivent la documentation des outils ; ils ne prouvent pas que cette skill y a été exécutée. Aucune version minimale de ces outils n’est attestée pour cette fiche.

3. Charger la skill

Après vérification, copiez le dossier complet dans le projet avec l’une des commandes ci-dessous, puis ouvrez une nouvelle session de l’outil. La commande s’arrête si un dossier du même nom existe déjà : comparez les fichiers avant de le remplacer.

Claude Code
test -f '.skill-downloads/terraform-resource-migration-mmk3nhss/SKILL.md' && test -s '.skill-downloads/terraform-resource-migration-mmk3nhss/SKILL.md' && mkdir -p '.claude/skills' && test ! -e '.claude/skills/tf-resource-migration' && cp -R '.skill-downloads/terraform-resource-migration-mmk3nhss' '.claude/skills/tf-resource-migration'

OpenSkills

OpenSkills doit déjà être installé. La procédure locale install/read est contrôlée avec OpenSkills 1.5.0, qui exige Node.js ≥ 20.6.0. Aucun slug du catalogue n’est résolu automatiquement.

Installation officielle d’OpenSkills
openskills install './.skill-downloads/terraform-resource-migration-mmk3nhss'

openskills read 'terraform-resource-migration-mmk3nhss'

La lecture doit afficher le contenu du fichier installé et son dossier de base. Elle ne lance ni la skill ni ses dépendances.

Pour un agent qui lit AGENTS.md, synchronisez ensuite l’index. Cette commande modifie AGENTS.md : relisez le diff avant de l’utiliser.

openskills sync

Mode manuel ou autre outil : joignez SKILL.md à une conversation, ou ouvrez-le dans un agent capable de lire les fichiers. Ajoutez les ressources annexes nécessaires. Il n’existe pas de dossier universel reconnu par tous les outils.

4. Faire un premier essai

Utilisez une entrée courte et fictive : un endpoint d’API, un petit document ou un brief d’interface. Dans une nouvelle conversation, joignez le fichier ou donnez son chemin à l’agent, puis adaptez cette demande :

Lis .skill-downloads/terraform-resource-migration-mmk3nhss/SKILL.md et applique ses instructions à cet exemple : [décrire une entrée de test]. Indique les fichiers, dépendances ou accès qui manquent. Produis le résultat demandé par la skill sans inventer de données ni exécuter de script non examiné.

Résultat attendu : une sortie correspondant aux instructions de la skill, ou une liste précise des prérequis manquants. Une simple confirmation de lecture ne valide pas le premier usage. Si une ressource externe est indisponible, ce parcours reste à tester.

Skills similaires