web-dev-qa-db-fra.com

Recherche de toutes les instances Amazon AWS ne comportant pas une balise donnée

J'essaie d'utiliser les outils de ligne de commande Amazon AWS pour rechercher toutes les instances pour lesquelles aucune balise n'est spécifiée.

La recherche de toutes les instances AVEC une balise est assez simple, par exemple.

ec2-describe-instances --filter "tag-key=Name"

Mais comment pourrais-je inverser ce filtre pour ne renvoyer que les instances qui n'ont pas de balise "Nom"?

26
A. Duff

Cela fera ce que vous demandez - trouvez toutes les instances qui ne contiennent pas de balise nommée "YOUR_KEY_NAME_HERE" (les filtres de la deuxième ligne pour les occurrences sans balise nommée "Nom"):

aws ec2 describe-instances | jq '.Reservations[].Instances[] | select(contains({Tags: [{Key: "YOUR_KEY_NAME_HERE"} ]}) | not)' 
aws ec2 describe-instances | jq '.Reservations[].Instances[] | select(contains({Tags: [{Key: "Name"} ]}) | not)' 

Si vous souhaitez filtrer la valeur de la balise au lieu du nom de la balise, cette requête répertorie toutes les instances ne contenant pas de balise nommée YOUR_KEY_NAME_HERE dont la valeur est EXCLUDE_ME. (La deuxième ligne répertorie les instances qui ne sont pas nommées "testbox1".)

aws ec2 describe-instances | jq '.Reservations[].Instances[] | select(contains({Tags: [{Key: "YOUR_KEY_NAME_HERE"}, {Value: "EXCLUDE_ME"}]}) | not)'
aws ec2 describe-instances | jq '.Reservations[].Instances[] | select(contains({Tags: [{Key: "Name"}, {Value: "testbox1"}]}) | not)'

Felipe a raison. L'analyse de la sortie est la seule solution, car l'API AWS ne fournit pas cette fonctionnalité, pas plus que les interfaces de ligne de commande AWS officielles. La sortie JSON est très analysable, en particulier si elle est comparée aux enregistrements de texte multilignes que l'ancienne CLI imprime par défaut.

http://docs.aws.Amazon.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeInstances.html

L'API elle-même renvoie JSON et le nouvel awscli imprime ce JSON en tant que format de sortie par défaut. Le programme "jq" est très utile pour l’analyser. Il peut même se colorier lorsqu’il est envoyé à un terminal. Vous pouvez également le texte en sortie pour le réduire en chaînes.

22
Jason2616321

Vous pouvez le faire avec jmespath (le moteur qui gère le paramètre --query) malgré ce que d'autres disent:

aws ec2 describe-instances \
  --query 'Reservations[].Instances[?!not_null(Tags[?Key == `Name`].Value)] | []'

Source: Utilisation de l'interface de ligne de commande Amazon Web Services (AWS CLI) pour rechercher des instances sans balise 'Nom' .

11
Nate Fox

Étant donné que le paramètre --filters ne semble pas prendre en charge le filtrage inverse, voici la solution à ce problème avec le paramètre --query:

aws ec2 describe-instances \
--query 'Reservations[].Instances[?!contains(Tags[].Key, `Name`)][].InstanceId'

Il examine un tableau de clés de balises pour chaque instance et filtre celles qui ne possèdent pas de balise 'Nom' dans le tableau. Ensuite, aplatit la sortie en un tableau d'identifiants d'instance.

  • Avantage par rapport aux réponses précédentes: pas besoin de jq ou d'une autre commande pour filtrer la sortie.
  • Inconvénient sur le filtre inverse vrai: susceptible d'être beaucoup plus lent sur un grand nombre d'instances.
3
Sergei

Malheureusement, l'appel d'api sous-jacent DescribeSnapshots ne prend pas en charge le filtrage de balise inverse, de même que la CLI. Vous pouvez toutefois effectuer un filtrage côté client avec le paramètre --query qui effectue un JMESPath search. Cela vous évitera d'avoir à utiliser des pipes comme avec la réponse de user2616321.

Par exemple:

aws ec2 describe-instances --query "Reservations[].Instances[?Tags[?Key == 'Name']][]"

Ajoutez .InstanceId à la fin pour obtenir uniquement les identifiants d'instance.

2
Jordon Phillips

J'avais le même problème et j'ai compris comment interroger Tag -Values. J'ai défini une clé de balise "MachineName" sur toutes mes instances et je souhaite filtrer par les valeurs du nom de clé de balise

Vous trouverez ci-dessous un exemple de filtrage où Name = Machine1

utiliser l'option

--filters "Name=tag-key,Values=MachineName" "Name=tag-values,Values=Machine1"

Cela fonctionne bien pour moi

1
DWGuru

Autant que je sache, directement à travers la CLI, vous ne pourrez pas le faire.

Par la syntaxe que vous utilisez, je suppose que vous utilisez l’ancienne CLI. Je vous suggère de télécharger le nouveau CLI http://aws.Amazon.com/cli/ et d'appeler 

aws ec2 describe-instances --output json

à partir de python, Ruby ou de n’importe quel langage de script, vous pouvez analyser le filtre de sortie JSON en utilisant l’expression régulière appropriée en fonction de vos besoins

0
Felipe Garcia

Moi aussi, j'ai été totalement choqué par la difficulté de le faire via la CLI. J'ai aimé la réponse de user2616321, mais je rencontrais un peu de difficulté à le faire afficher les champs exacts que je voulais par instance. Après avoir passé un certain temps à déconner et à échouer avec JMESPath dans la syntaxe de requête, j'ai fini par créer un petit script Ruby pour le faire. Au cas où quelqu'un voudrait gagner quelques minutes en écrivant l'un des leurs, le voici:

#!/usr/bin/env Ruby
require 'json'

# We'll output any instance that doesn't contain all of these tags
desired_tags = if ARGV.empty?
                 %w(Name)
               else
                 ARGV
               end

# Put the keys we want to output per instance/reservation here
reservation_keys = %w(OwnerId RequesterId)
instance_keys = %w(Tags InstanceId InstanceType PublicDnsName LaunchTime PrivateIpAddress KeyName) 
instances_without_tags = []

# Just use CLI here to avoid AWS dependencies
reservations = JSON.parse(
  `aws ec2 describe-instances`
)["Reservations"]

# A reservation is a single call to spin up instances. You could potentially
# have more than one instance in a reservation, but often only one is
# spun up at a time, meaning there is a single instance per reservation.
reservations.each do |reservation|
  reservation["Instances"].each do |instance|
    # Filter instances without the desired tags
    tag_keys = instance["Tags"].map { |t| t["Key"] }
    unless (tag_keys & desired_tags).length == desired_tags.length
      instances_without_tags << 
        reservation.select { |k| reservation_keys.include?(k) }.
          merge(instance.select { |k| instance_keys.include?(k) })
    end
  end
end

puts JSON.pretty_generate(instances_without_tags)
0
Ramfjord