Aperçu
Nous travaillons toujours sur cette fonctionnalité, mais nous aimerions que vous l'essayiez !
Cette fonctionnalité est actuellement fournie dans le cadre d'un programme d'aperçu conformément à nos politiques de pré-sortie.
Cette page fournit une référence complète des actions AWS Systems Manager disponibles dans le catalogue des actions d'automatisation des workflows. Ces actions vous permettent d'automatiser Systems Manager et d'effectuer des opérations de documents.
Prérequis
Avant d'utiliser AWS Actions dans l'automatisation workflow, assurez-vous de disposer des éléments suivants :
- Un compte AWS disposant des autorisations appropriées.
- Informations d'identification AWS configurées (informations d'identification de l'utilisateur IAM, ARN du rôle IAM ou informations d'identification de session).
- Les autorisations IAM nécessaires pour les services AWS spécifiques que vous prévoyez d'utiliser.
Consultez la section Configurer les informations d'identification AWS pour savoir comment créer un utilisateur IAM et des rôles IAM, et comment configurer les informations d'identification AWS statiques et de session pour l'intégration avec les actions AWS d'automatisation workflow.
Écrivez un document SSM sur le compte AWS en fonction des informations d'identification AWS transmises dans l'entrée d'action. Consultez la Documentation AWS Systems Manager
Champ de saisie | optionnalité | Type | Exemple |
|---|---|---|---|
awsRoleArn | Facultatif | Chaîne |
|
awsAccessKeyId | Facultatif | Chaîne |
|
awsSecretAccessKey | Facultatif | Chaîne |
|
awsSessionToken | Facultatif | Chaîne |
|
région | Requis | Chaîne |
|
documentName | Requis | Chaîne |
|
documentType | Facultatif | Chaîne |
Vérifiez les valeurs valides à partir de ici. |
documentFormat | Facultatif | Chaîne |
Vérifiez les valeurs valides à partir de ici. |
documentContent | Requis | Chaîne | Voir l'exemple |
override | Facultatif | Booléen |
Lorsque Lorsque |
sélecteurs | Facultatif | liste |
|
Champ de sortie | Type | Description et exemple |
|---|---|---|
documentName | Chaîne |
|
documentVersion | Chaîne |
|
documentType | Chaîne |
|
documentStatus | Chaîne |
La valeur sera l'un des statuts de ici. |
succès | Booléen |
|
message d'erreur | Chaîne |
|
Important
- Dans l'entrée d'action, seuls
awsAccessKeyIdetawsSecretAccessKeypeuvent être fournis, mais il doit s'agir d'informations d'identification statiques d'un utilisateur IAM. - Si des informations d'identification de session doivent être utilisées,
awsAccessKeyId,awsSecretAccessKeyetawsSessionTokendoivent être transmises à l'entrée d'action. - Les sélecteurs permettant d'obtenir uniquement les paramètres spécifiés en sortie.
- Reportez-vous à Informations d'identification AWS pour obtenir des instructions.
Exemple 1: Un simple document SSM pour répertorier toutes les fonctions lambda
schemaVersion: '0.3' description: List all Lambda function names. mainSteps: - name: ExecuteAwsApi action: aws:executeAwsApi isEnd: true inputs: Service: lambda Api: ListFunctions outputs: - Name: resultFunctionName Selector: $..FunctionName Type: StringList outputs: - ExecuteAwsApi.resultFunctionNameDéfinition complète des flux automatiques avec les fonctions lambda de la liste SSM
name: aws-api
workflowInputs: key: type: String defaultValue: "${{ :secrets:11933347:USERNAME_AWS_ACCESS_KEY_ID }}" access: type: String defaultValue: "${{ :secrets:11933347:USERNAME_AWS_SECRET_ACCESS_KEY }}" token: type: String defaultValue: "${{ :secrets:11933347:USERNAME_AWS_SESSION_TOKEN }}" region: type: String defaultValue: us-east-2
steps: - name: createSsmDocument type: action action: aws.systemsManager.writeDocument version: 1 inputs: awsAccessKeyId: ${{ .workflowInputs.key }} awsSecretAccessKey: ${{ .workflowInputs.access }} awsSessionToken: ${{ .workflowInputs.token }} region: ${{ .workflowInputs.region }} selectors: - name: documentName expression: '.documentName' - name: documentType expression: '.documentType' - name: documentStatus expression: '.documentStatus' - name: success expression: '.success' documentName: "LambdaListFunctionNames" documentContent: | schemaVersion: '0.3' description: List all Lambda function names. mainSteps: - name: ExecuteAwsApi action: aws:executeAwsApi isEnd: true inputs: Service: lambda Api: ListFunctions outputs: - Name: resultFunctionName Selector: $..FunctionName Type: StringList outputs: - ExecuteAwsApi.resultFunctionName
- name: generateIdempotencyToken type: action action: utils.uuid.generate version: 1
- name: start1 type: action action: aws.systemsManager.startAutomation version: 1 inputs: awsAccessKeyId: ${{ .workflowInputs.key }} awsSecretAccessKey: ${{ .workflowInputs.access }} awsSessionToken: ${{ .workflowInputs.token }} region: ${{ .workflowInputs.region }} documentName: "${{ .steps.createSsmDocument.outputs.documentName }}" idempotencyToken: ${{ .steps.generateIdempotencyToken.outputs.uuid }}
- name: waitForCompletion type: action action: aws.systemsManager.waitForAutomationStatus version: 1 inputs: awsAccessKeyId: ${{ .workflowInputs.key }} awsSecretAccessKey: ${{ .workflowInputs.access }} awsSessionToken: ${{ .workflowInputs.token }} region: ${{ .workflowInputs.region }} automationExecutionId: ${{ .steps.start1.outputs.automationExecutionId }} # Optional, default is Success and Failed automationExecutionStatuses: - "Success" - "Failed" timeout: 60
- name: hasCompleted type: switch switch: - condition: ${{ .steps.waitForCompletion.outputs.automationExecutionStatus == "Failed" }} next: displayError - condition: ${{ .steps.waitForCompletion.outputs.automationExecutionStatus == "Success" }} next: displaySuccess next: displayUnexpected
- name: displayUnexpected type: action action: newrelic.instrumentation.log version: 1 inputs: message: "Unexpected status ${{ .steps.waitForCompletion.outputs.automationExecutionStatus | tojson }}" next: cleanupSsmDocument
- name: displaySuccess type: action action: newrelic.instrumentation.log version: 1 inputs: message: "This is all the lambda function names on the region ${{ .workflowInputs.region }}:${{ .steps.waitForCompletion.outputs.automationExecutionOutputs.ExecuteAwsApi.resultFunctionName | join(\",\") }}" next: cleanupSsmDocument
- name: displayError type: action action: newrelic.instrumentation.log version: 1 inputs: message: "Error while executing document ${{ .steps.createSsmDocument.outputs.documentName }}, detail: ${{ .steps.waitForCompletion.outputs.errorMessage }}" next: cleanupSsmDocument
- name: cleanupSsmDocument type: action action: aws.systemsManager.deleteDocument version: 1 inputs: awsAccessKeyId: ${{ .workflowInputs.key }} awsSecretAccessKey: ${{ .workflowInputs.access }} awsSessionToken: ${{ .workflowInputs.token }} region: ${{ .workflowInputs.region }} documentName: ${{ .steps.createSsmDocument.outputs.documentName }}Exemple 2 : Exécuter un script Python
En utilisant l'automatisation et l'action de document AWS SystemsManager, nous pouvons définir une définition de workflow qui exécute un script python.
Voici un bref exemple illustrant une simple application Hello World.
schemaVersion: '0.3' description: "Run a Python script that says 'Hello' to the username passed as input and capture the output." parameters: Username: type: String description: "The username to greet." default: "User" mainSteps: - action: aws:executeScript name: pythonStep inputs: Runtime: python3.8 Handler: script_handler Script: | def script_handler(event, context): username = event['username'] return f'Hello {username}' InputPayload: username: "{{ Username }}" outputs: - Name: scriptOutput Type: String Selector: $.Payload outputs: - pythonStep.scriptOutputCeci peut ensuite être utilisé dans le workflow ci-dessous :
name: aws-python-script
workflowInputs: key: type: String defaultValue: "${{ :secrets:11933347:USERNAME_AWS_ACCESS_KEY_ID }}" access: type: String defaultValue: "${{ :secrets:11933347:USERNAME_AWS_SECRET_ACCESS_KEY }}" token: type: String defaultValue: "${{ :secrets:11933347:USERNAME_AWS_SESSION_TOKEN }}" region: type: String defaultValue: us-west-2 name: type: String defaultValue: ExecuteHelloPythonScript username: type: String defaultValue: World!
steps: - name: generateIdempotencyToken type: action action: utils.uuid.generate version: 1
- name: createSsmDocument type: action action: aws.systemsManager.writeDocument version: 1 inputs: awsAccessKeyId: ${{ .workflowInputs.key }} awsSecretAccessKey: ${{ .workflowInputs.access }} awsSessionToken: ${{ .workflowInputs.token }} region: ${{ .workflowInputs.region }} documentName: ${{ .workflowInputs.name }} documentContent: | schemaVersion: '0.3' description: "Run a Python script that says 'Hello' to the username passed as input and capture the output." parameters: Username: type: String description: "The username to greet." default: "User" mainSteps: - action: aws:executeScript name: pythonStep inputs: Runtime: python3.8 Handler: script_handler Script: | def script_handler(event, context): username = event['username'] return f'Hello {username}' InputPayload: username: "{{ Username }}" outputs: - Name: scriptOutput Type: String Selector: $.Payload outputs: - pythonStep.scriptOutput
- name: start1 type: action action: aws.systemsManager.startAutomation version: 1 inputs: awsAccessKeyId: ${{ .workflowInputs.key }} awsSecretAccessKey: ${{ .workflowInputs.access }} awsSessionToken: ${{ .workflowInputs.token }} region: ${{ .workflowInputs.region }} documentName: "${{ .steps.createSsmDocument.outputs.documentName }}" idempotencyToken: ${{ .steps.generateIdempotencyToken.outputs.uuid }} parameters: Username: ${{ .workflowInputs.username }}
- name: waitForCompletion type: action action: aws.systemsManager.waitForAutomationStatus version: 1 inputs: awsAccessKeyId: ${{ .workflowInputs.key }} awsSecretAccessKey: ${{ .workflowInputs.access }} awsSessionToken: ${{ .workflowInputs.token }} region: ${{ .workflowInputs.region }} automationExecutionId: ${{ .steps.start1.outputs.automationExecutionId }} # Optional, default is Success and Failed automationExecutionStatuses: - "Success" - "Failed" timeout: 300
- name: hasCompleted type: switch switch: - condition: ${{ .steps.waitForCompletion.outputs.automationExecutionStatus == "Failed" }} next: displayError - condition: ${{ .steps.waitForCompletion.outputs.automationExecutionStatus == "Success" }} next: displaySuccess next: displayUnexpected
- name: displayUnexpected type: action action: newrelic.instrumentation.log version: 1 inputs: message: "Unexpected status ${{ .steps.waitForCompletion.outputs.automationExecutionStatus | tojson }}" next: cleanupSsmDocument
- name: displaySuccess type: action action: newrelic.instrumentation.log version: 1 inputs: message: "This is the results of the automation that was run on the region ${{ .workflowInputs.region }}:${{ .steps.waitForCompletion.outputs.automationExecutionOutputs.pythonStep.scriptOutput | tojson }}" next: cleanupSsmDocument
- name: displayError type: action action: newrelic.instrumentation.log version: 1 inputs: message: "Error while executing document ${{ .steps.createSsmDocument.outputs.documentName }}, detail: ${{ .steps.waitForCompletion.outputs | tojson }}" next: cleanupSsmDocument
- name: cleanupSsmDocument type: action action: aws.systemsManager.deleteDocument version: 1 inputs: awsAccessKeyId: ${{ .workflowInputs.key }} awsSecretAccessKey: ${{ .workflowInputs.access }} awsSessionToken: ${{ .workflowInputs.token }} region: ${{ .workflowInputs.region }} documentName: ${{ .steps.createSsmDocument.outputs.documentName }}Ceci peut être démarré avec la mutation NerdGraph suivante, en supposant que les secrets temporaires AWS ont été précédemment stockés avec les mutations secretsManagementCreateSecretNerdGraph.
mutation { autoflowsStartWorkflowRun(accountId: 11933347, definition: { name: "aws-python-script", }, workflowInputs: [ {key: "key" value: "${{ :secrets:testUser123_AWS_ACCESS_KEY_ID }}"} {key: "access" value: "${{ :secrets:testUser123_AWS_SECRET_ACCESS_KEY }}"} {key: "token" value: "${{ :secrets:testUser123_AWS_SESSION_TOKEN }}"} {key: "region" value:"us-west-2"} {key: "username" value: "Julien"} ]) { runId } }L'exécution de la mutation ci-dessus renvoie un runId, par exemple 207e8c23-2c89-4af2-a74f-3c9ea2ffd543. Ce runId peut ensuite être utilisé pour interroger les logs et voir la sortie suivante :

Exemple 3 : Un document SSM plus complexe
- Obtenir la liste des API REST du gateway API. Filtrer mon API (
Test API) et obtenir l'ID de l'API REST. - Obtenez la liste de toutes les ressources à l'intérieur de mon API (
Test API). Filtrez ma ressource spécifique en fonction de pathPart(/test) et obtenez l'ID de la ressource - Obtenez la liste des versions de ma fonction lambda (
ApiGwTestFn). Filtrez la version spécifique vers laquelle je souhaite revenir (version : 1) et obtenez le functionArn de cette version. - Mettre à jour l'intégration du gateway API avec la fonction lambdaArn acquise à l'étape ci-dessus.
- Créer un nouveau déploiement pour mon API REST (
Test API).
schemaVersion: '0.3' description: Test SSM for API gateway rollback mainSteps: - name: ExecuteAwsApi action: aws:executeAwsApi nextStep: ExecuteGetApiResources inputs: Service: apigateway Api: GetRestApis outputs: - Name: resultApiId Selector: $.items[?(@.name=='Test API')].id Type: String - name: ExecuteGetApiResources action: aws:executeAwsApi nextStep: ExecuteListVersionsByFunction inputs: Service: apigateway Api: GetResources restApiId: '{{ ExecuteAwsApi.resultApiId }}' outputs: - Name: resultResourceId Selector: $.items[?(@.pathPart=='test')].id Type: String - name: ExecuteListVersionsByFunction action: aws:executeAwsApi nextStep: ExecuteApiGwUpdateIntg inputs: Service: lambda Api: ListVersionsByFunction FunctionName: ApiGwTestFn outputs: - Name: resultLambdaVersionArn Selector: $.Versions[?(@.Version=='1')].FunctionArn Type: String - name: ExecuteApiGwUpdateIntg action: aws:executeAwsApi nextStep: ExecuteApiGwCreateDeployment inputs: Service: apigateway Api: UpdateIntegration restApiId: '{{ ExecuteAwsApi.resultApiId }}' resourceId: '{{ ExecuteGetApiResources.resultResourceId }}' httpMethod: GET patchOperations: - op: replace path: /uri value: arn:aws:apigateway:us-east-2:lambda:path/2015-03-31/functions/{{ ExecuteListVersionsByFunction.resultLambdaVersionArn }}/invocations - name: ExecuteApiGwCreateDeployment action: aws:executeAwsApi inputs: Service: apigateway Api: CreateDeployment restApiId: '{{ ExecuteAwsApi.resultApiId }}' outputs: - ExecuteGetApiResources.resultResourceId - ExecuteListVersionsByFunction.resultLambdaVersionArnLes exemples de sorties SSM ExecuteGetApiResources.resultResourceId et ExecuteListVersionsByFunction.resultLambdaVersionArn. Ces sorties peuvent être utilisées dans d'autres étapes de la définition du workflow.
Cette action permet de supprimer un document AWS SSM dans le compte AWS en fonction des identifiants passés dans l'entrée d'action. Voir Documentation AWS Systems Manager
Champ de saisie | optionnalité | Type | Exemple |
|---|---|---|---|
awsRoleArn | Facultatif | Chaîne |
|
awsAccessKeyId | Requis | Chaîne |
|
awsSecretAccessKey | Requis | Chaîne |
|
awsSessionToken | Facultatif | Chaîne |
|
région | Requis | Chaîne |
|
documentName | Requis | Chaîne |
|
sélecteurs | Facultatif | List |
|
Champ de sortie | Type | Exemple |
|---|---|---|
documentName | Chaîne |
|
succès | Booléen |
|
message d'erreur | Chaîne |
|
Important
- Dans l'entrée d'action, seuls
awsAccessKeyIdetawsSecretAccessKeypeuvent être fournis, mais il doit s'agir d'informations d'identification statiques d'un utilisateur IAM. - Si des informations d'identification de session doivent être utilisées,
awsAccessKeyId,awsSecretAccessKeyetawsSessionTokendoivent être transmises à l'entrée d'action. - Les sélecteurs permettant d'obtenir uniquement les paramètres spécifiés en sortie.
Un document SSM simple pour répertorier toutes les fonctions lambda
schemaVersion: '0.3' description: List all Lambda function names. mainSteps: - name: ExecuteAwsApi action: aws:executeAwsApi isEnd: true inputs: Service: lambda Api: ListFunctions outputs: - Name: resultFunctionName Selector: $..FunctionName Type: StringList outputs: - ExecuteAwsApi.resultFunctionNameLa définition complète du workflow avec SSM:
name: aws-api
workflowInputs: key: type: String defaultValue: "${{ :secrets:11933347:USERNAME_AWS_ACCESS_KEY_ID }}" access: type: String defaultValue: "${{ :secrets:11933347:USERNAME_AWS_SECRET_ACCESS_KEY }}" token: type: String defaultValue: "${{ :secrets:11933347:USERNAME_AWS_SESSION_TOKEN }}" region: type: String defaultValue: us-east-2
steps: - name: createSsmDocument type: action action: aws.systemsManager.writeDocument version: 1 inputs: awsAccessKeyId: ${{ .workflowInputs.key }} awsSecretAccessKey: ${{ .workflowInputs.access }} awsSessionToken: ${{ .workflowInputs.token }} region: ${{ .workflowInputs.region }} selectors: - name: documentName expression: '.documentName' - name: documentType expression: '.documentType' - name: documentStatus expression: '.documentStatus' - name: success expression: '.success' documentName: "LambdaListFunctionNames" documentContent: | schemaVersion: '0.3' description: List all Lambda function names. mainSteps: - name: ExecuteAwsApi action: aws:executeAwsApi isEnd: true inputs: Service: lambda Api: ListFunctions outputs: - Name: resultFunctionName Selector: $..FunctionName Type: StringList outputs: - ExecuteAwsApi.resultFunctionName
- name: generateIdempotencyToken type: action action: utils.uuid.generate version: 1
- name: start1 type: action action: aws.systemsManager.startAutomation version: 1 inputs: awsAccessKeyId: ${{ .workflowInputs.key }} awsSecretAccessKey: ${{ .workflowInputs.access }} awsSessionToken: ${{ .workflowInputs.token }} region: ${{ .workflowInputs.region }} documentName: "${{ .steps.createSsmDocument.outputs.documentName }}" idempotencyToken: ${{ .steps.generateIdempotencyToken.outputs.uuid }}
- name: waitForCompletion type: action action: aws.systemsManager.waitForAutomationStatus version: 1 inputs: awsAccessKeyId: ${{ .workflowInputs.key }} awsSecretAccessKey: ${{ .workflowInputs.access }} awsSessionToken: ${{ .workflowInputs.token }} region: ${{ .workflowInputs.region }} automationExecutionId: ${{ .steps.start1.outputs.automationExecutionId }} # Optional, default is Success and Failed automationExecutionStatuses: - "Success" - "Failed" timeout: 60
- name: hasCompleted type: switch switch: - condition: ${{ .steps.waitForCompletion.outputs.automationExecutionStatus == "Failed" }} next: displayError - condition: ${{ .steps.waitForCompletion.outputs.automationExecutionStatus == "Success" }} next: displaySuccess next: displayUnexpected
- name: displayUnexpected type: action action: newrelic.instrumentation.log version: 1 inputs: message: "Unexpected status ${{ .steps.waitForCompletion.outputs.automationExecutionStatus | tojson }}" next: cleanupSsmDocument
- name: displaySuccess type: action action: newrelic.instrumentation.log version: 1 inputs: message: "This is all the lambda function names on the region ${{ .workflowInputs.region }}:${{ .steps.waitForCompletion.outputs.automationExecutionOutputs.ExecuteAwsApi.resultFunctionName | join(\",\") }}" next: cleanupSsmDocument
- name: displayError type: action action: newrelic.instrumentation.log version: 1 inputs: message: "Error while executing document ${{ .steps.createSsmDocument.outputs.documentName }}, detail: ${{ .steps.waitForCompletion.outputs.errorMessage }}" next: cleanupSsmDocument
- name: cleanupSsmDocument type: action action: aws.systemsManager.deleteDocument version: 1 inputs: awsAccessKeyId: ${{ .workflowInputs.key }} awsSecretAccessKey: ${{ .workflowInputs.access }} awsSessionToken: ${{ .workflowInputs.token }} region: ${{ .workflowInputs.region }} documentName: ${{ .steps.createSsmDocument.outputs.documentName }}Démarre une automatisation à l'aide d'un document AWS SSM. Consultez Documentation AWS Systems Manager
Champ de saisie | optionnalité | Type | Exemple |
|---|---|---|---|
awsRoleArn | Facultatif | Chaîne |
|
awsAccessKeyId | Facultatif | Chaîne |
|
awsSecretAccessKey | Facultatif | Chaîne |
|
awsSessionToken | Facultatif | Chaîne |
|
région | Requis | Chaîne |
|
documentName | Requis | Chaîne |
|
paramètres | Facultatif | Carte |
|
idempotencyToken | Facultatif | UUID |
Ceci sera transmis en tant que jeton client pour l'idempotence afin de démarrer l'automatisation AWS SSM. |
sélecteurs | Facultatif | List |
|
Champ de sortie | Type | Exemple |
|---|---|---|
automationExecutionId | Chaîne |
|
succès | Booléen |
|
message d'erreur | Chaîne |
|
Important
- Dans l'entrée d'action, si
awsAccessKeyIdetawsSecretAccessKeydoivent être fournis, assurez-vous qu'il s'agit d'informations d'identification statiques d'un utilisateur IAM. - Si des informations d'identification de session doivent être utilisées,
awsAccessKeyId,awsSecretAccessKeyetawsSessionTokendoivent être transmises à l'entrée d'action. - Reportez-vous à Informations d'identification AWS pour obtenir des instructions.
- Utilisez des sélecteurs pour obtenir uniquement les paramètres spécifiés en sortie.
définition du flux de travail | Entrées | Sorties |
|---|---|---|
| | |
En attente d'une automatisation utilisant un document AWS. Consultez la documentation AWS système Manager pour plus d'informations.
Champ de saisie | optionnalité | Type | Exemple |
|---|---|---|---|
awsRoleArn | Facultatif | Chaîne |
|
awsAccessKeyId | Facultatif | Chaîne |
|
awsSecretAccessKey | Facultatif | Chaîne |
|
awsSessionToken | Facultatif | Chaîne |
|
région | Requis | Chaîne |
|
automationExecutionId | Requis | Chaîne |
. L'automatisation
pour laquelle nous devons attendre son achèvement. |
automationExecutionStatuses | Facultatif | List |
Liste des statuts d'exécution de l'automatisation à partir de AutomationExecution qui peuvent arrêter l'attente. Défaut: |
temps mort | Facultatif | int |
La durée en secondes pendant laquelle nous pouvons attendre que l'état de l'automatisation soit l'un des Si le délai d'attente est dépassé, la sortie contient |
sélecteurs | Facultatif | List |
. |
Champ de sortie | Type | Exemple |
|---|---|---|
automationExecutionId | Chaîne |
|
automationExecutionStatus | Chaîne |
Si l'action réussit, elle prendra l'une des valeurs transmises dans le champ de saisie Sinon, ce sera nul. |
automationExecutionOutputs | Carte | Le résultat sera une carte des valeurs de sortie du document. Toute donnée de sortie du document peut être collectée à l'aide de ce champ de sortie et utilisée dans les étapes suivantes de la définition de l'automatisation workflow. |
succès | Booléen |
|
message d'erreur | Chaîne |
|
Important
- Dans l'entrée d'action, seuls
awsAccessKeyIdetawsSecretAccessKeypeuvent être fournis, mais il doit s'agir d'informations d'identification statiques d'un utilisateur IAM. - Si des informations d'identification de session doivent être utilisées,
awsAccessKeyId,awsSecretAccessKeyetawsSessionTokendoivent être transmises à l'entrée d'action. - Consultez les instructions pour configurer les identifiants AWS.
- Utilisez des sélecteurs pour obtenir uniquement les paramètres spécifiés en sortie.
définition du flux de travail | Entrées | Sorties |
|---|---|---|
| | |