3
votes

Comment ajouter des règles de cycle de vie à un compartiment S3 à l'aide de terraform?

J'utilise Terraform pour créer un compartiment dans S3 et je souhaite y ajouter des "dossiers" et des règles de cycle de vie.

Je peux créer le compartiment (en utilisant une ressource "aws_s3_bucket").

Je peux créer le bucket et définir mes règles de cycle de vie au sein de la même ressource "aws_s3_bucket", ie. au moment de la création.

Je peux ajouter des "dossiers" au bucket (je sais que ce ne sont pas vraiment des dossiers, mais ils sont présentés aux systèmes clients comme s'ils étaient ... :-)), en utilisant une ressource "aws_s3_bucket_object", ie. après la création du bucket.

Tout va bien ...

Mais je veux pouvoir ajouter des règles de cycle de vie APRÈS avoir créé le bucket, mais j'obtiens une erreur m'indiquant le bucket existe déjà. (En fait, je veux pouvoir ajouter ultérieurement des dossiers et des règles de cycle de vie correspondantes au fur et à mesure des besoins.)

Maintenant, je peux ajouter des règles de cycle de vie à un compartiment existant dans l'interface graphique AWS, donc je sais que c'est un chose raisonnable à faire.

Mais y a-t-il un moyen de le faire avec Terraform?

Suis-je en train de manquer quelque chose?

2 error(s) occurred:

* module.s3.aws_s3_bucket.bucket_quarterly: 1 error(s) occurred:

* aws_s3_bucket.bucket_quarterly: Error creating S3 bucket: BucketAlreadyOwnedByYou: Your previous request to create the named bucket succeeded and you already own it.
    status code: 409, request id: EFE9C62B25341478, host id: hcsCNracNrpTJZ4QdU0AV2wNm/FqhYSEY4KieQ+zSHNsj6AUR69XvPF+0BiW4ZOpfgIoqwFoXkI=
* module.s3.aws_s3_bucket.bucket_permanent: 1 error(s) occurred:

* aws_s3_bucket.bucket_permanent: Error creating S3 bucket: BucketAlreadyOwnedByYou: Your previous request to create the named bucket succeeded and you already own it.
    status code: 409, request id: 7DE1B1A36138A614, host id: 8jB6l7d6Hc6CZFgQSLQRMJg4wtvnrSL6Yp5R4RScq+GtuMW+6rkN39bcTUwQhzxeI7jRStgLXSc=

Terraform does not automatically rollback in the face of errors.
Instead, your Terraform state file has been partially updated with
any resources that successfully completed. Please address the error
above and apply again to incrementally change your infrastructure.

Je m'attends à avoir un bucket avec 2 règles de cycle de vie, mais j'obtiens l'erreur suivante:

Erreur: Erreur lors de l'application du plan:

resource "aws_s3_bucket" "bucket" {
    bucket      = "${replace(var.tags["Name"],"/_/","-")}"
    region      = "${var.aws_region}"

    #tags                = "${merge(var.tags, map("Name", "${var.tags["Name"]}"))}"
    tags                = "${merge(var.tags, map("Name", "${replace(var.tags["Name"],"/_/","-")}"))}"
}


resource "aws_s3_bucket" "bucket_quarterly" {
    bucket      = "${aws_s3_bucket.bucket.id}"
    #region      = "${var.aws_region}"

    lifecycle_rule {
        id      = "quarterly_retention"
        prefix  = "quarterly/"
        enabled = true

        expiration {
            days = 92
        }
    }

}


resource "aws_s3_bucket" "bucket_permanent" {
    bucket      = "${aws_s3_bucket.bucket.id}"
    #region      = "${var.aws_region}"

    lifecycle_rule {
        id      = "permanent_retention"
        enabled = true
        prefix  = "permanent/"

        transition {
            days            = 1
            storage_class   = "GLACIER"
        }
    }

}


resource "aws_s3_bucket_object" "quarterly" {
    bucket  = "${aws_s3_bucket.bucket.id}"
    #bucket  = "${var.bucket_id}"
    acl     = "private"
    key     = "quarterly"
    source  = "/dev/null"
}


resource "aws_s3_bucket_object" "permanent" {
    bucket  = "${aws_s3_bucket.bucket.id}"
    #bucket  = "${var.bucket_id}"
    acl     = "private"
    key     = "permanent"
    source  = "/dev/null"
}


1 commentaires

Cela ressemble à un bug récurrent ( voir github ici et ici ).


3 Réponses :


0
votes

Pour autant que je sache, vous ne pouvez pas élaborer une politique de cycle de vie séparément.

Quelqu'un a soulevé un PR pour qu'une ressource soit créée pour vous permettre de le faire, mais il semble qu'elle soit toujours ouverte: https://github.com/terraform-providers/terraform-provider-aws/issues/6188


En ce qui concerne votre erreur, je pense que la raison pour laquelle vous obtenez l'erreur est que:

  • ressource "aws_s3_bucket" "bucket"

Crée un bucket avec un nom particulier.

  • ressource "aws_s3_bucket" "bucket_quarterly"

Références bucket = "$ {aws_s3_bucket.bucket.id}" et essaie donc de créer un bucket avec le même nom que la ressource précédente (ce qui ne peut pas être fait car les noms sont uniques).

  • ressource "aws_s3_bucket" "bucket_permanent"

De même, cette ressource fait référence à bucket = "$ {aws_s3_bucket.bucket.id}" et essaie donc de créer un bucket avec le même nom que la première ressource (ce qui ne peut pas être fait car les noms sont unique).


Vous avez mentionné J'espère avoir un bucket avec 2 règles de cycle de vie mais dans votre code ci-dessus, vous créez 3 buckets s3 séparés (un sans cycle de vie et 2 avec un cycle de vie) et deux objets ( dossiers) qui sont placés dans le compartiment s3 sans politique de cycle de vie.


0 commentaires

7
votes

Voyons d'abord ce qui se passe et comment nous pouvons résoudre ce problème. Chaque fois que vous définissez une ressource "aws_s3_bucket" , terraform tentera de créer un bucket avec les paramètres spécifiés. Si vous souhaitez attacher une politique de cycle de vie à un bucket, faites-le là où vous définissez le bucket, par exemple :

// example of what the variable would look like:
variable "lifecycle_rules" {
  type = "list"
  default = []
}

// example of what the assignment would look like:
lifecycle_rules = [{
  id = "cleanup"
  prefix = ""
  enabled = true
  expiration = [{
    days = 1
  }]
}, {...}, {...} etc...]

// example what the usage would look like
resource "aws_s3_bucket" "quarterly" {
    bucket  = "quarterly_bucket_name"
    #bucket  = "${var.bucket_id}"
    acl     = "private"
    source  = "/dev/null"
    lifecycle_rule = [ "${var.lifecycle_rules}" ]
}

Un bucket peut contenir plusieurs blocs lifecycle_rule . Si vous souhaitez définir les règles de cycle de vie en tant que blocs externes, vous pouvez le faire de cette manière:

resource "aws_s3_bucket" "quarterly" {
    bucket  = "quarterly_bucket_name"
    #bucket  = "${var.bucket_id}"
    acl     = "private"
    lifecycle_rule {
        id      = "quarterly_retention"
        prefix  = "folder/"
        enabled = true

        expiration {
            days = 92
        }
    }
}

resource "aws_s3_bucket" "permanent" {
    bucket  = "perm_bucket_name"
    acl     = "private"
    lifecycle_rule {
        id      = "permanent_retention"
        enabled = true
        prefix  = "permanent/"

        transition {
            days            = 1
            storage_class   = "GLACIER"
        }
    }
}

Remarque: l'implémentation ci-dessus d'une politique de cycle de vie externe n'est pas vraiment la meilleure façon de le faire, mais la seule. Vous incitez à peu près terraform à accepter la liste des cartes, qui se trouve être du même type que lifecycle_rule, donc cela fonctionne. Idéalement, Terraform devrait avoir son propre bloc de ressources pour les règles de cycle de vie, mais ce n'est pas le cas.

Modifier: pourquoi avoir des blocs de ressources séparés alors que nous avons maintenant des blocs dynamiques! Woohoo


4 commentaires

> Les blocs de type "lifecycle_rule" ne sont pas attendus ici. Il ne semble pas y avoir de lifecycle_rule pour aws_s3_bucket_object


Merci d'avoir fait remarquer cela. J'ai mis à jour les noms des ressources pour qu'ils soient corrects maintenant.


@Moe, que voulez-vous dire par blocs dynamiques ?


google "blocs dynamiques terraform" et le premier résultat l'explique en détail: github.com/hashicorp/terraform-guides/tree/master/...



0
votes

Merci pour l'info (j'aime l'idée de la liste pour séparer les règles de la ressource).

Le problème était que je n'appréciais pas que vous puissiez définir des règles de cycle de vie dans la ressource ET les modifier par la suite, alors j'essayais de comprendre comment les définir séparément ...

Tout ce qui est nécessaire est de les spécifier dans la ressource et de faire appliquer terraform, puis vous pouvez le modifier et ajouter / modifier / supprimer des éléments lifecycle_rules et simplement appliquer à nouveau terraform pour appliquer les modifications.


0 commentaires