diff --git a/internal/juju/offers.go b/internal/juju/offers.go index 675fe5ef..274b94ea 100644 --- a/internal/juju/offers.go +++ b/internal/juju/offers.go @@ -75,7 +75,7 @@ type RemoveRemoteOfferInput struct { OfferURL string } -type GrantOfferInput struct { +type GrantRevokeOfferInput struct { User string Access string OfferURL string @@ -400,7 +400,7 @@ func (c offersClient) RemoveRemoteOffer(input *RemoveRemoteOfferInput) []error { } // This function adds access to an offer -func (c offersClient) GrantOffer(input GrantOfferInput) error { +func (c offersClient) GrantOffer(input *GrantRevokeOfferInput) error { conn, err := c.GetConnection(nil) if err != nil { return err @@ -420,3 +420,25 @@ func (c offersClient) GrantOffer(input GrantOfferInput) error { return nil } + +// This function revokes access to an offer. +func (c offersClient) RevokeOffer(input *GrantRevokeOfferInput) error { + conn, err := c.GetConnection(nil) + if err != nil { + return err + } + defer func() { _ = conn.Close() }() + + client := applicationoffers.NewClient(conn) + _, err = client.ApplicationOffer(input.OfferURL) + if err != nil { + return err + } + + err = client.RevokeOffer(input.User, input.Access, input.OfferURL) + if err != nil { + return err + } + + return nil +} diff --git a/internal/provider/resource_access_offer.go b/internal/provider/resource_access_offer.go index 535a3c4c..e93c8b55 100644 --- a/internal/provider/resource_access_offer.go +++ b/internal/provider/resource_access_offer.go @@ -139,7 +139,7 @@ func (a *accessOfferResource) Create(ctx context.Context, req resource.CreateReq accessStr := plan.Access.ValueString() // Call Offers.GrantOffer for _, user := range users { - err := a.client.Offers.GrantOffer(juju.GrantOfferInput{ + err := a.client.Offers.GrantOffer(&juju.GrantRevokeOfferInput{ User: user, Access: accessStr, OfferURL: offerURLStr, @@ -212,7 +212,39 @@ func (a *accessOfferResource) Update(ctx context.Context, req resource.UpdateReq } func (a *accessOfferResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) { - // Delete + // Check first if the client is configured + if a.client == nil { + addClientNotConfiguredError(&resp.Diagnostics, "access offer", "read") + return + } + var plan accessOfferResourceOffer + + // Get the Terraform state from the request into the plan + resp.Diagnostics.Append(req.State.Get(ctx, &plan)...) + if resp.Diagnostics.HasError() { + return + } + + // Get the users + var users []string + resp.Diagnostics.Append(plan.Users.ElementsAs(ctx, &users, false)...) + if resp.Diagnostics.HasError() { + return + } + + // Revoking against "read" guarantees that the entire access will be removed + // instead of only decreasing the access level. + for _, user := range users { + err := a.client.Offers.RevokeOffer(&juju.GrantRevokeOfferInput{ + User: user, + Access: "read", + OfferURL: plan.OfferURL.ValueString(), + }) + if err != nil { + resp.Diagnostics.AddError("Client Error", fmt.Sprintf("Unable to destroy access offer resource, got error: %s", err)) + return + } + } } func (a *accessOfferResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {