5.10. Valider les opérateurs à l'aide de la carte de score
En tant qu'auteur de l'opérateur, vous pouvez utiliser l'outil de scorecard dans le SDK de l'opérateur pour effectuer les tâches suivantes :
- Validez que votre projet Operator ne contient pas d'erreurs de syntaxe et qu'il est correctement empaqueté
- Examinez les suggestions d'amélioration de votre opérateur
5.10.1. A propos de l'outil carte de score
Alors que la sous-commande Operator SDK bundle validate
peut valider le contenu et la structure des répertoires de bundle locaux et des images de bundle distantes, vous pouvez utiliser la commande scorecard
pour exécuter des tests sur votre Operator sur la base d'un fichier de configuration et d'images de test. Ces tests sont mis en œuvre dans des images de test qui sont configurées et construites pour être exécutées par le scorecard.
Le scorecard suppose qu'il est exécuté avec un accès à un cluster Kubernetes configuré, tel que OpenShift Container Platform. Le scorecard exécute chaque test dans un pod, à partir duquel les journaux du pod sont agrégés et les résultats des tests sont envoyés à la console. Le scorecard intègre des tests de base et des tests OLM (Operator Lifecycle Manager) et fournit également un moyen d'exécuter des définitions de test personnalisées.
Flux de travail du tableau de bord
- Créer toutes les ressources requises par les ressources personnalisées (RC) et l'opérateur
- Créer un conteneur proxy dans le déploiement de l'opérateur pour enregistrer les appels au serveur API et exécuter les tests
- Examiner les paramètres dans les CR
Les tests du tableau de bord ne font aucune supposition quant à l'état de l'opérateur testé. La création d'opérateurs et de CR pour un opérateur dépasse le champ d'application du tableau de bord lui-même. Les tests du tableau de bord peuvent toutefois créer toutes les ressources dont ils ont besoin si les tests sont conçus pour la création de ressources.
scorecard
syntaxe de la commande
$ operator-sdk scorecard <bundle_dir_ou_image> [flags] (drapeaux)
Le tableau de bord requiert un argument de position pour le chemin d'accès au disque de votre groupe d'opérateurs ou le nom d'une image de groupe.
Pour plus d'informations sur les drapeaux, cliquez ici :
$ operator-sdk scorecard -h
5.10.2. Configuration du tableau de bord
L'outil scorecard utilise une configuration qui vous permet de configurer des plugins internes, ainsi que plusieurs options de configuration globales. Les tests sont pilotés par un fichier de configuration nommé config.yaml
, qui est généré par la commande make bundle
, située dans votre répertoire bundle/
:
./bundle ... └── tests └── scorecard └── config.yaml
Exemple de fichier de configuration d'un scorecard
kind: Configuration apiversion: scorecard.operatorframework.io/v1alpha3 metadata: name: config stages: - parallel: true tests: - image: quay.io/operator-framework/scorecard-test:v1.25.4 entrypoint: - scorecard-test - basic-check-spec labels: suite: basic test: basic-check-spec-test - image: quay.io/operator-framework/scorecard-test:v1.25.4 entrypoint: - scorecard-test - olm-bundle-validation labels: suite: olm test: olm-bundle-validation-test
Le fichier de configuration définit chaque test que le scorecard peut exécuter. Les champs suivants du fichier de configuration du scorecard définissent le test comme suit :
Champ de configuration | Description |
---|---|
| Nom de l'image du conteneur de test qui met en œuvre un test |
| Commande et arguments invoqués dans l'image de test pour exécuter un test |
| Étiquettes personnalisées ou définies dans le tableau de bord permettant de sélectionner les tests à effectuer |
5.10.3. Tests de cartes de pointage intégrés
Le tableau de bord est livré avec des tests prédéfinis qui sont organisés en suites : la suite de tests de base et la suite Operator Lifecycle Manager (OLM).
Test | Description | Nom court |
---|---|---|
Existence d'un bloc de spécifications |
Ce test vérifie que toutes les ressources personnalisées (CR) créées dans le cluster disposent d'un bloc |
|
Test | Description | Nom court |
---|---|---|
Validation de l'offre groupée | Ce test valide les manifestes de la liasse trouvés dans la liasse qui est passée dans le scorecard. Si le contenu de la liasse contient des erreurs, le résultat du test comprend le journal du validateur ainsi que les messages d'erreur de la bibliothèque de validation. |
|
Les API fournies sont validées |
Ce test permet de vérifier que les définitions de ressources personnalisées (CRD) pour les CR fournis contiennent une section de validation et qu'il existe une validation pour chaque champ |
|
Les CRD possédés ont des ressources répertoriées |
Ce test vérifie que les CRD de chaque CR fourni via l'option |
|
Champs spécifiques avec descripteurs |
Ce test permet de vérifier que chaque champ des sections CRs |
|
Champs d'état avec descripteurs |
Ce test permet de vérifier que chaque champ des sections CRs |
|
5.10.4. Exécution de l'outil de tableau de bord
Un ensemble de fichiers Kustomize par défaut est généré par le SDK de l'opérateur après l'exécution de la commande init
. Le fichier par défaut bundle/tests/scorecard/config.yaml
qui est généré peut être immédiatement utilisé pour exécuter l'outil de scorecard avec votre opérateur, ou vous pouvez modifier ce fichier selon les spécifications de votre test.
Conditions préalables
- Projet d'opérateur généré à l'aide de l'Operator SDK
Procédure
Générer ou régénérer les manifestes et les métadonnées de vos bundles pour votre opérateur :
$ make bundle
Cette commande ajoute automatiquement des annotations de scorecard aux métadonnées de votre bundle, qui sont utilisées par la commande
scorecard
pour exécuter les tests.Exécutez le tableau de bord en fonction du chemin d'accès au disque de votre groupe d'opérateurs ou du nom d'une image de groupe :
$ operator-sdk scorecard <bundle_dir_or_image>
5.10.5. Résultats du tableau de bord
L'option --output
de la commande scorecard
spécifie le format de sortie des résultats de la carte de score : text
ou json
.
Exemple 5.15. Exemple d'extrait de sortie JSON
{ "apiVersion": "scorecard.operatorframework.io/v1alpha3", "kind": "TestList", "items": [ { "kind": "Test", "apiVersion": "scorecard.operatorframework.io/v1alpha3", "spec": { "image": "quay.io/operator-framework/scorecard-test:v1.25.4", "entrypoint": [ "scorecard-test", "olm-bundle-validation" ], "labels": { "suite": "olm", "test": "olm-bundle-validation-test" } }, "status": { "results": [ { "name": "olm-bundle-validation", "log": "time=\"2020-06-10T19:02:49Z\" level=debug msg=\"Found manifests directory\" name=bundle-test\ntime=\"2020-06-10T19:02:49Z\" level=debug msg=\"Found metadata directory\" name=bundle-test\ntime=\"2020-06-10T19:02:49Z\" level=debug msg=\"Getting mediaType info from manifests directory\" name=bundle-test\ntime=\"2020-06-10T19:02:49Z\" level=info msg=\"Found annotations file\" name=bundle-test\ntime=\"2020-06-10T19:02:49Z\" level=info msg=\"Could not find optional dependencies file\" name=bundle-test\n", "state": "pass" } ] } } ] }
Exemple 5.16. Exemple d'extrait de texte
-------------------------------------------------------------------------------- Image: quay.io/operator-framework/scorecard-test:v1.25.4 Entrypoint: [scorecard-test olm-bundle-validation] Labels: "suite":"olm" "test":"olm-bundle-validation-test" Results: Name: olm-bundle-validation State: pass Log: time="2020-07-15T03:19:02Z" level=debug msg="Found manifests directory" name=bundle-test time="2020-07-15T03:19:02Z" level=debug msg="Found metadata directory" name=bundle-test time="2020-07-15T03:19:02Z" level=debug msg="Getting mediaType info from manifests directory" name=bundle-test time="2020-07-15T03:19:02Z" level=info msg="Found annotations file" name=bundle-test time="2020-07-15T03:19:02Z" level=info msg="Could not find optional dependencies file" name=bundle-test
La spécification du format de sortie correspond à la présentation du type Test
de la présentation du type.
5.10.6. Sélection des tests
Les tests du tableau de bord sont sélectionnés en associant l'indicateur CLI --selector
à un ensemble de chaînes d'étiquettes. Si aucun drapeau de sélection n'est fourni, tous les tests contenus dans le fichier de configuration du tableau de bord sont exécutés.
Les tests sont exécutés en série, les résultats étant agrégés par le tableau de bord et écrits sur la sortie standard, ou stdout.
Procédure
Pour sélectionner un seul test, par exemple
basic-check-spec-test
, spécifiez le test en utilisant l'indicateur--selector
:$ operator-sdk scorecard <bundle_dir_or_image> \ -o text \ --selector=test=basic-check-spec-test
Pour sélectionner une série de tests, par exemple
olm
, indiquez une étiquette utilisée par tous les tests OLM :$ operator-sdk scorecard <bundle_dir_or_image> \ -o text \ --selector=suite=olm
Pour sélectionner plusieurs tests, spécifiez les noms des tests à l'aide de l'indicateur
selector
en utilisant la syntaxe suivante :$ operator-sdk scorecard <bundle_dir_or_image> \ -o text \ --selector='test in (basic-check-spec-test,olm-bundle-validation-test)'
5.10.7. Permettre des tests en parallèle
En tant qu'auteur d'un opérateur, vous pouvez définir des étapes distinctes pour vos tests à l'aide du fichier de configuration du tableau de bord. Les étapes s'exécutent séquentiellement dans l'ordre où elles sont définies dans le fichier de configuration. Une étape contient une liste de tests et un paramètre configurable parallel
.
Par défaut, ou lorsqu'une étape définit explicitement parallel
à false
, les tests d'une étape sont exécutés séquentiellement dans l'ordre où ils sont définis dans le fichier de configuration. L'exécution des tests un par un est utile pour garantir que deux tests n'interagissent pas et n'entrent pas en conflit l'un avec l'autre.
Toutefois, si les tests sont conçus pour être totalement isolés, ils peuvent être parallélisés.
Procédure
Pour exécuter un ensemble de tests isolés en parallèle, incluez-les dans la même étape et fixez
parallel
àtrue
:apiVersion: scorecard.operatorframework.io/v1alpha3 kind: Configuration metadata: name: config stages: - parallel: true 1 tests: - entrypoint: - scorecard-test - basic-check-spec image: quay.io/operator-framework/scorecard-test:v1.25.4 labels: suite: basic test: basic-check-spec-test - entrypoint: - scorecard-test - olm-bundle-validation image: quay.io/operator-framework/scorecard-test:v1.25.4 labels: suite: olm test: olm-bundle-validation-test
- 1
- Permet de réaliser des tests en parallèle
Tous les tests d'une étape parallèle sont exécutés simultanément, et Scorecard attend qu'ils soient tous terminés avant de passer à l'étape suivante. Vos tests peuvent ainsi s'exécuter beaucoup plus rapidement.
5.10.8. Tests personnalisés des cartes de pointage
L'outil de tableau de bord peut exécuter des tests personnalisés qui respectent ces conventions obligatoires :
- Les tests sont mis en œuvre dans une image conteneur
- Les tests acceptent un point d'entrée comprenant une commande et des arguments
-
Les tests produisent la carte de score
v1alpha3
au format JSON, sans journalisation superflue dans la sortie du test -
Les tests peuvent obtenir le contenu du paquet à un point de montage partagé de
/bundle
- Les tests peuvent accéder à l'API Kubernetes à l'aide d'une connexion client dans le cluster
Il est possible d'écrire des tests personnalisés dans d'autres langages de programmation si l'image de test suit les lignes directrices ci-dessus.
L'exemple suivant montre une image de test personnalisée écrite en Go :
Exemple 5.17. Exemple de test de scorecard personnalisé
// Copyright 2020 The Operator-SDK Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. package main import ( "encoding/json" "fmt" "log" "os" scapiv1alpha3 "github.com/operator-framework/api/pkg/apis/scorecard/v1alpha3" apimanifests "github.com/operator-framework/api/pkg/manifests" ) // This is the custom scorecard test example binary // As with the Redhat scorecard test image, the bundle that is under // test is expected to be mounted so that tests can inspect the // bundle contents as part of their test implementations. // The actual test is to be run is named and that name is passed // as an argument to this binary. This argument mechanism allows // this binary to run various tests all from within a single // test image. const PodBundleRoot = "/bundle" func main() { entrypoint := os.Args[1:] if len(entrypoint) == 0 { log.Fatal("Test name argument is required") } // Read the pod's untar'd bundle from a well-known path. cfg, err := apimanifests.GetBundleFromDir(PodBundleRoot) if err != nil { log.Fatal(err.Error()) } var result scapiv1alpha3.TestStatus // Names of the custom tests which would be passed in the // `operator-sdk` command. switch entrypoint[0] { case CustomTest1Name: result = CustomTest1(cfg) case CustomTest2Name: result = CustomTest2(cfg) default: result = printValidTests() } // Convert scapiv1alpha3.TestResult to json. prettyJSON, err := json.MarshalIndent(result, "", " ") if err != nil { log.Fatal("Failed to generate json", err) } fmt.Printf("%s\n", string(prettyJSON)) } // printValidTests will print out full list of test names to give a hint to the end user on what the valid tests are. func printValidTests() scapiv1alpha3.TestStatus { result := scapiv1alpha3.TestResult{} result.State = scapiv1alpha3.FailState result.Errors = make([]string, 0) result.Suggestions = make([]string, 0) str := fmt.Sprintf("Valid tests for this image include: %s %s", CustomTest1Name, CustomTest2Name) result.Errors = append(result.Errors, str) return scapiv1alpha3.TestStatus{ Results: []scapiv1alpha3.TestResult{result}, } } const ( CustomTest1Name = "customtest1" CustomTest2Name = "customtest2" ) // Define any operator specific custom tests here. // CustomTest1 and CustomTest2 are example test functions. Relevant operator specific // test logic is to be implemented in similarly. func CustomTest1(bundle *apimanifests.Bundle) scapiv1alpha3.TestStatus { r := scapiv1alpha3.TestResult{} r.Name = CustomTest1Name r.State = scapiv1alpha3.PassState r.Errors = make([]string, 0) r.Suggestions = make([]string, 0) almExamples := bundle.CSV.GetAnnotations()["alm-examples"] if almExamples == "" { fmt.Println("no alm-examples in the bundle CSV") } return wrapResult(r) } func CustomTest2(bundle *apimanifests.Bundle) scapiv1alpha3.TestStatus { r := scapiv1alpha3.TestResult{} r.Name = CustomTest2Name r.State = scapiv1alpha3.PassState r.Errors = make([]string, 0) r.Suggestions = make([]string, 0) almExamples := bundle.CSV.GetAnnotations()["alm-examples"] if almExamples == "" { fmt.Println("no alm-examples in the bundle CSV") } return wrapResult(r) } func wrapResult(r scapiv1alpha3.TestResult) scapiv1alpha3.TestStatus { return scapiv1alpha3.TestStatus{ Results: []scapiv1alpha3.TestResult{r}, } }