juju / terraform-provider-juju

A Terraform provider for Juju
Apache License 2.0
21 stars 43 forks source link

Add juju_access_offer schema #627

Open amandahla opened 2 weeks ago

amandahla commented 2 weeks ago

Type of change

Adding new schema

Description

In the current version, the operator can create an offer via the Juju Terraform Provider but cannot grant or revoke permissions, meaning this must be done manually.

The juju_access_offer resource aims to provide the same functionality as the existing `juju_jaas_access_offer` resource, where the operator can set users and access levels for an offer.

Details

"access": schema.StringAttribute{
    Description: "Level of access to grant. Changing this value will replace the Terraform resource. Valid access levels are described at https://juju.is/docs/juju/manage-offers#control-access-to-an-offer",
    Required:    true,
    PlanModifiers: []planmodifier.String{
        stringplanmodifier.RequiresReplace(),
    },
        Validators: []validator.Set{ setvalidator.ValueStringsAre(validator.OneOf("read", "consume", "admin"),),},
},
"users": schema.SetAttribute{
    Description: "List of users to grant access.",
    Optional:    true,
    ElementType: types.StringType,
    Validators: []validator.Set{
        setvalidator.ValueStringsAre(ValidatorMatchString(names.IsValidUser, "user must be a valid Juju username")),
    },
},
// ID required for imports
"id": schema.StringAttribute{
    Computed: true,
    PlanModifiers: []planmodifier.String{
        stringplanmodifier.UseStateForUnknown(),
    },
},
"offer_url": schema.StringAttribute{
    Description: "The url of the offer for access management. If this is changed the resource will be deleted and a new resource will be created.",
    Required:    true,
    Validators: []validator.String{
        ValidatorMatchString(func(s string) bool {
            _, err := crossmodel.ParseOfferURL(s)
            return err == nil
        }, "offer_url must be a valid offer string."),
    },
    PlanModifiers: []planmodifier.String{
        stringplanmodifier.RequiresReplace(),
    },
}

Example terraform plan

resource "juju_access_offer" "development" {
  offer_url        = juju_offer.myoffer.url
  access           = "consume"
  users            = ["foo", "bar"]
}

Notes & References

To grant bob consume access to an offer:

juju grant bob consume admin/default.hosted-mysql

To revoke bob’s consume access (he will be left with read access):

juju revoke bob consume admin/default.hosted-mysql

To revoke all of bob’s access:

juju revoke bob read admin/default.hosted-mysql
hmlanigan commented 2 weeks ago

@amandahla,

Overall this look good, thank you for the detail.

I'm unsure of stringplanmodifier.RequiresReplace() for changing the access level. Why do the extra work? It's done that way for JaaS due to limitation of their API as far as I know.

I just noticed that the juju_access_model resource does the same thing which has me scratching my head. The rest of the code has some logic errors in this area too.

I'd prefer to have improved behavior rather than repeating mistakes made in juju_access_model.

amandahla commented 2 weeks ago

In that case, the resource would need to check during the update whether a grant or revoke should be run, right? For example, if the access level is initially 'admin' and then changes to 'read', the provider should call 'revoke' instead of 'grant'.

amandahla commented 18 hours ago

Hi, although the issue was not closed, I started working on a draft PR that is now ready for review. While working on it, I noticed why Access was set to RequiresReplace: it changes the ID, and without it, the update fails. I’ve marked the PR as ready for review, but if there are any updates on this issue, I can revert it back to a draft.