Utiliser les commutateurs de fonctionnalité App Lifecycle Manager avec Go

Ce guide explique comment intégrer vos applications Go aux indicateurs de fonctionnalité d'App Lifecycle Manager. Vous apprendrez à utiliser le SDK OpenFeature avec le fournisseur flagd pour évaluer les indicateurs gérés par App Lifecycle Manager. Vous pourrez ainsi contrôler de manière dynamique la disponibilité et le comportement des fonctionnalités dans vos services Go.

Ce guide suppose que vous avez déjà configuré les ressources App Lifecycle Manager nécessaires (comme les offres SaaS, les types d'unités, les unités, les indicateurs et les déploiements progressifs) en suivant l'un des guides de démarrage rapide suivants :

Prérequis

Avant de commencer, assurez-vous de disposer des éléments suivants :

  1. Go installé : version 1.23 ou ultérieure.
  2. Guide de démarrage rapide sur les indicateurs de fonctionnalité d'App Lifecycle Manager suivi
    • Vous avez suivi le guide de démarrage rapide sur les indicateurs de fonctionnalité intégrés ou autonomes pour provisionner votre unité cible.
    • Vous devez disposer de variables ou de valeurs d'environnement issues de ce guide de démarrage rapide, telles que PROJECT_ID, LOCATION_1 (la région de votre unité), UNIT_ID et FLAG_KEY.
  3. Authentifié gcloud pour les identifiants par défaut de l'application (ADC) : l'application Go utilise les ADC pour s'authentifier auprès des Google Cloud services. Si vous exécutez l'application localement (pour une utilisation autonome ou des tests Docker locaux), assurez-vous de vous être authentifié dans votre environnement :

    gcloud auth application-default login
    
  4. Autorisations IAM : l'identité qui exécute votre application Go doit disposer du rôle Identity and Access Management roles/saasconfig.viewer sur votre Google Cloud projet pour lire les configurations d'indicateur :

    gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
        --member="user:YOUR_EMAIL_ADDRESS" \
        --role="roles/saasconfig.viewer"
    

    Remplacez YOUR_PROJECT_ID et YOUR_EMAIL_ADDRESS en conséquence.

Comprendre les principales variables d'environnement

Votre application Go s'appuie sur des variables d'environnement pour se connecter à la configuration d'indicateur appropriée et évaluer l'indicateur prévu.

  • FLAGD_SOURCE_PROVIDER_ID: spécifie la configuration de flag de fonctionnalité à extraire du service App Lifecycle Manager. Il doit s'agir du nom complet de la ressource FeatureFlagConfig associée à votre unité.
    • Format: projects/PROJECT_ID/locations/LOCATION/featureFlagsConfigs/UNIT_ID
    • Exemple : projects/my-gcp-project/locations/us-central1/featureFlagsConfigs/my-app-instance-01

Configurer votre projet Go

Avant de pouvoir exécuter votre application, initialisez votre module et ajoutez la logique d'initialisation et d'évaluation nécessaire.

  1. Créez un répertoire de projet :

    mkdir go-featureflag-app
    cd go-featureflag-app
    go mod init go-featureflag-app
    
  2. Créez un code d'application : ajoutez un fichier nommé main.go avec le contenu suivant pour initialiser le fournisseur et évaluer un indicateur.

    package main
    
    import (
        "context"
        "fmt"
        "log"
        "os"
    
        flagd "github.com/open-feature/go-sdk-contrib/providers/flagd/pkg"
        "github.com/open-feature/go-sdk/openfeature"
        "google.golang.org/grpc"
        "google.golang.org/grpc/credentials"
        "google.golang.org/grpc/credentials/oauth"
        "google.golang.org/grpc/metadata"
    )
    
    // GetNewFlagdProvider initializes a flagd provider configured for  App Lifecycle Manager
    func GetNewFlagdProvider(ctx context.Context) (*flagd.Provider, error) {
        providerID := os.Getenv("FLAGD_SOURCE_PROVIDER_ID")
        if providerID == "" {
            return nil, fmt.Errorf("FLAGD_SOURCE_PROVIDER_ID environment variable is not set")
        }
    
        creds, err := oauth.NewApplicationDefault(ctx)
        if err != nil {
            return nil, err
        }
    
        // Interceptor to inject the Unit name into headers for regional routing
        routingInterceptor := func(ctx context.Context, desc *grpc.StreamDesc, cc *grpc.ClientConn, method string, streamer grpc.Streamer, opts ...grpc.CallOption) (grpc.ClientStream, error) {
            md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("name=%s", providerID))
            ctx = metadata.NewOutgoingContext(ctx, md)
            return streamer(ctx, desc, cc, method, opts...)
        }
    
        options := []flagd.ProviderOption{
            flagd.WithHost("saasconfig.googleapis.com"),
            flagd.WithPort(443),
            flagd.WithInProcessResolver(),
            flagd.WithProviderID(providerID),
            flagd.WithGrpcDialOptionsOverride([]grpc.DialOption{
                grpc.WithTransportCredentials(credentials.NewTLS(nil)),
                grpc.WithPerRPCCredentials(creds),
                grpc.WithStreamInterceptor(routingInterceptor),
            }),
        }
    
        return flagd.NewProvider(options...)
    }
    
    // InitializeFeatureManagement registers the provider globally
    func InitializeFeatureManagement(ctx context.Context) error {
        provider, err := GetNewFlagdProvider(ctx)
        if err != nil {
            return err
        }
        openfeature.SetProvider(provider)
        return nil
    }
    
    func main() {
    ctx := context.Background()
    InitializeFeatureManagement(ctx);
    
    // 1. Get Client
    client := openfeature.NewClient("simple-api")
    
    // 2. Create Evaluation Context
    evalCtx := openfeature.NewEvaluationContext()
    
    // 3. Evaluate Flag
    // Default to false if evaluation fails
    isEnhanced, err := client.BooleanValue(context.Background(), "enhanced-search", false, evalCtx)
    if err != nil {
    log.Printf("Flag evaluation failed: %v", err)
    }
    
    // 4. Return response
    if isEnhanced {
    fmt.Println("Enhanced search feature is enabled.")
    } else {
    fmt.Println("Enhanced search feature is disabled.")
    }
    
    }
    
  3. Créez go.mod : l'utilisation de versions spécifiques garantit la stabilité.

    module go-featureflag-app
    
    go 1.23
    
    require (
        github.com/open-feature/go-sdk v1.15.1
        github.com/open-feature/go-sdk-contrib/providers/flagd v0.3.0
        google.golang.org/grpc v1.74.2
        golang.org/x/oauth2 v0.22.0
    )
    
  4. Obtenez les dépendances :

    go mod tidy
    go mod download
    

Exécuter l'application Go

Vous pouvez exécuter l'application localement à l'aide de votre configuration autonome ou la déployer en tant que conteneur.

Exécuter de manière autonome (localement)

  1. Définissez les variables d'environnement :

    export PROJECT_ID="your-gcp-project-id"
    export LOCATION_1="us-central1"
    export UNIT_ID="my-app-instance-01"
    export FLAGD_SOURCE_PROVIDER_ID="projects/${PROJECT_ID}/locations/${LOCATION_1}/featureFlagsConfigs/${UNIT_ID}"
    
  2. Exécutez l'application :

    go run main.go
    

Exécuter de manière intégrée (conteneurisée)

  1. Créez un fichier Dockerfile :

    FROM golang:1.23 as builder
    WORKDIR /app
    COPY go.mod go.sum ./
    RUN go mod download
    COPY . .
    RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-s -w" -o /go-featureflag-app .
    
    FROM gcr.io/distroless/static-debian11
    WORKDIR /
    COPY --from=builder /go-featureflag-app /go-featureflag-app
    ENTRYPOINT ["/go-featureflag-app"]
    
  2. Créez et transférez l'image :

    export PROJECT_ID="your-gcp-project-id"
    docker build -t gcr.io/${PROJECT_ID}/my-go-app:latest .
    docker push gcr.io/${PROJECT_ID}/my-go-app:latest
    
  3. Déployez le service : mettez à jour le plan de votre unité pour référencer gcr.io/${PROJECT_ID}/my-go-app:latest et déployez la nouvelle version à l'aide d'un déploiement progressif App Lifecycle Manager.

Vérifier les modifications d'indicateur

Une fois votre application exécutée, vérifiez qu'elle évalue correctement les indicateurs.

  1. Observez la valeur initiale : vérifiez que la sortie enregistre la valeur correspondant à l'état initial.
  2. Mettez à jour l'indicateur dans App Lifecycle Manager : modifiez le comportement de l'indicateur à l'aide de Google Cloud la console ou de gcloud.
  3. Vérifiez la valeur mise à jour : réexécutez la compilation locale ou observez les journaux de conteneur pour afficher le résultat mis à jour.

Étape suivante