Skip to content

Commit

Permalink
Merge pull request #22 from pluralsh/add-rbac-resources
Browse files Browse the repository at this point in the history
Add resources for managing rbac
  • Loading branch information
michaeljguarino authored Jan 4, 2024
2 parents 80c2e3f + a25f14d commit b11f150
Show file tree
Hide file tree
Showing 19 changed files with 2,503 additions and 56 deletions.
268 changes: 265 additions & 3 deletions go.mod

Large diffs are not rendered by default.

1,281 changes: 1,279 additions & 2 deletions go.sum

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion internal/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ type Client struct {
*gqlclient.Client
}

func (c *Client) CreateServiceDeployment(ctx context.Context, id, handle *string, attrs gqlclient.ServiceDeploymentAttributes) (*gqlclient.ServiceDeploymentFragment, error) {
func (c *Client) CreateServiceDeployment(ctx context.Context, id, handle *string, attrs gqlclient.ServiceDeploymentAttributes) (*gqlclient.ServiceDeploymentExtended, error) {
if len(lo.FromPtr(id)) == 0 && len(lo.FromPtr(handle)) == 0 {
return nil, fmt.Errorf("could not create service deployment: id or handle not provided")
}
Expand Down
101 changes: 101 additions & 0 deletions internal/datasource/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package datasource

import (
"context"
"fmt"
"os"

"terraform-provider-plural/internal/client"
"terraform-provider-plural/internal/common"

"github.com/mitchellh/go-homedir"

"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"

"gopkg.in/yaml.v2"
)

type config struct {
Email types.String `tfsdk:"email" yaml:"email"`
Token types.String `tfsdk:"token" yaml:"email"`
}

func NewConfigDataSource() datasource.DataSource {
return &configDataSource{}
}

type configDataSource struct {
client *client.Client
}

func (d *configDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_config"
}

func (d *configDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
MarkdownDescription: "A representation of a config to authenticate to app.plural.sh",
Attributes: map[string]schema.Attribute{
"email": schema.StringAttribute{
Optional: true,
Computed: true,
MarkdownDescription: "The email used to authenticate to plural.",
},
"token": schema.StringAttribute{
MarkdownDescription: "Access token used to authenticate to plural.",
Computed: true,
},
},
}
}

func (d *configDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
if req.ProviderData == nil {
return
}

data, ok := req.ProviderData.(*common.ProviderData)
if !ok {
resp.Diagnostics.AddError(
"Unexpected Config Resource Configure Type",
fmt.Sprintf("Expected *common.ProviderData, got: %T. Please report this issue to the provider developers.", req.ProviderData),
)
return
}

d.client = data.Client
}

func (d *configDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var data config
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}

p, err := homedir.Expand("~/.plural/config.yml")
if err != nil {
resp.Diagnostics.AddWarning("Client Error", fmt.Sprintf("Could not read local plural config: %s", err))
return
}

res, err := os.ReadFile(p)
if err != nil {
resp.Diagnostics.AddWarning("Client Error", fmt.Sprintf("Could not read local plural config: %s", err))
return
}

var conf struct {
Spec config
}

if err := yaml.Unmarshal(res, &conf); err != nil {
resp.Diagnostics.AddWarning("Client Error", fmt.Sprintf("Could not parse local plural config: %s", err))
return
}

data = conf.Spec
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}
95 changes: 95 additions & 0 deletions internal/datasource/group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package datasource

import (
"context"
"fmt"

"terraform-provider-plural/internal/client"
"terraform-provider-plural/internal/common"

"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
console "github.com/pluralsh/console-client-go"
)

func NewGroupDataSource() datasource.DataSource {
return &groupDataSource{}
}

type groupDataSource struct {
client *client.Client
}

func (d *groupDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_group"
}

func (d *groupDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
MarkdownDescription: "A representation of a group to organize authorization in your plural console.",
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Optional: true,
Computed: true,
MarkdownDescription: "Internal identifier of this group.",
Validators: []validator.String{stringvalidator.ExactlyOneOf(path.MatchRoot("id"))},
},
"name": schema.StringAttribute{
MarkdownDescription: "Name of the group.",
Computed: true,
},
},
}
}

func (d *groupDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
if req.ProviderData == nil {
return
}

data, ok := req.ProviderData.(*common.ProviderData)
if !ok {
resp.Diagnostics.AddError(
"Unexpected User Resource Configure Type",
fmt.Sprintf("Expected *common.ProviderData, got: %T. Please report this issue to the provider developers.", req.ProviderData),
)
return
}

d.client = data.Client
}

func (d *groupDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var data group
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}

if data.Name.IsNull() {
resp.Diagnostics.AddError(
"Missing group name",
"The provider could not read group data. Name must be specified.",
)
}

var group *console.GroupFragment
if !data.Name.IsNull() {
if c, err := d.client.GetGroup(ctx, data.Name.ValueString()); err != nil {
resp.Diagnostics.AddWarning("Client Error", fmt.Sprintf("Unable to read group by name, got error: %s", err))
} else {
group = c.Group
}
}

if group == nil {
resp.Diagnostics.AddError("Client Error", "Unable to read group, see warnings for more information")
return
}

data.From(group, ctx, resp.Diagnostics)
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}
19 changes: 19 additions & 0 deletions internal/datasource/group_model.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package datasource

import (
"context"

"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/types"
console "github.com/pluralsh/console-client-go"
)

type group struct {
Id types.String `tfsdk:"id"`
Name types.String `tfsdk:"name"`
}

func (c *group) From(cl *console.GroupFragment, ctx context.Context, d diag.Diagnostics) {
c.Id = types.StringValue(cl.ID)
c.Name = types.StringValue(cl.Name)
}
101 changes: 101 additions & 0 deletions internal/datasource/user.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package datasource

import (
"context"
"fmt"

"terraform-provider-plural/internal/client"
"terraform-provider-plural/internal/common"

"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
console "github.com/pluralsh/console-client-go"
)

func NewUserDataSource() datasource.DataSource {
return &userDataSource{}
}

type userDataSource struct {
client *client.Client
}

func (d *userDataSource) Metadata(_ context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_user"
}

func (d *userDataSource) Schema(_ context.Context, _ datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
MarkdownDescription: "A representation of a user to authenticate to your plural console.",
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Optional: true,
Computed: true,
MarkdownDescription: "Internal identifier of this user.",
Validators: []validator.String{stringvalidator.ExactlyOneOf(path.MatchRoot("email"))},
},
"name": schema.StringAttribute{
MarkdownDescription: "Name of the user.",
Computed: true,
},
"email": schema.StringAttribute{
MarkdownDescription: "Email address of this user.",
Computed: true,
Validators: []validator.String{stringvalidator.ExactlyOneOf(path.MatchRoot("id"))},
},
},
}
}

func (d *userDataSource) Configure(_ context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
if req.ProviderData == nil {
return
}

data, ok := req.ProviderData.(*common.ProviderData)
if !ok {
resp.Diagnostics.AddError(
"Unexpected User Resource Configure Type",
fmt.Sprintf("Expected *common.ProviderData, got: %T. Please report this issue to the provider developers.", req.ProviderData),
)
return
}

d.client = data.Client
}

func (d *userDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
var data user
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}

if data.Email.IsNull() {
resp.Diagnostics.AddError(
"Missing user email",
"The provider could not read user data. Email must be specified.",
)
}

// First try to fetch cluster by ID if it was provided.
var user *console.UserFragment
if !data.Email.IsNull() {
if c, err := d.client.GetUser(ctx, data.Email.ValueString()); err != nil {
resp.Diagnostics.AddWarning("Client Error", fmt.Sprintf("Unable to read user by email, got error: %s", err))
} else {
user = c.User
}
}

if user == nil {
resp.Diagnostics.AddError("Client Error", "Unable to read user, see warnings for more information")
return
}

data.From(user, ctx, resp.Diagnostics)
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}
21 changes: 21 additions & 0 deletions internal/datasource/user_model.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package datasource

import (
"context"

"github.com/hashicorp/terraform-plugin-framework/diag"
"github.com/hashicorp/terraform-plugin-framework/types"
console "github.com/pluralsh/console-client-go"
)

type user struct {
Id types.String `tfsdk:"id"`
Name types.String `tfsdk:"name"`
Email types.String `tfsdk:"email"`
}

func (c *user) From(cl *console.UserFragment, ctx context.Context, d diag.Diagnostics) {
c.Id = types.StringValue(cl.ID)
c.Name = types.StringValue(cl.Name)
c.Email = types.StringValue(cl.Email)
}
9 changes: 8 additions & 1 deletion internal/resource/git_repository.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
"github.com/hashicorp/terraform-plugin-framework/path"
"github.com/hashicorp/terraform-plugin-framework/resource"
"github.com/hashicorp/terraform-plugin-framework/resource/schema"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/booldefault"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/planmodifier"
"github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
"github.com/hashicorp/terraform-plugin-framework/schema/validator"
Expand Down Expand Up @@ -61,7 +62,6 @@ func (r *GitRepositoryResource) Schema(_ context.Context, _ resource.SchemaReque
stringvalidator.ConflictsWith(
path.MatchRoot("username"), path.MatchRoot("password"),
),
stringvalidator.AlsoRequires(path.MatchRoot("passphrase")),
},
},
"passphrase": schema.StringAttribute{
Expand Down Expand Up @@ -99,6 +99,13 @@ func (r *GitRepositoryResource) Schema(_ context.Context, _ resource.SchemaReque
stringvalidator.AlsoRequires(path.MatchRoot("username")),
},
},
"decrypt": schema.BoolAttribute{
Description: "If set to \"true\" then runs plural crypto unlock on the repo after clone.",
MarkdownDescription: "If set to `true` then runs `plural crypto unlock` on the repo after clone.",
Optional: true,
Computed: true,
Default: booldefault.StaticBool(false),
},
"url_format": schema.StringAttribute{
Optional: true,
Description: "Similar to https_Path, a manually supplied url format for custom git. Should be something like {url}/tree/{ref}/{folder}.",
Expand Down
2 changes: 2 additions & 0 deletions internal/resource/git_repository_model.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type gitRepository struct {
Password types.String `tfsdk:"password"`
UrlFormat types.String `tfsdk:"url_format"`
HttpsPath types.String `tfsdk:"https_path"`
Decrypt types.Bool `tfsdk:"decrypt"`
}

func (g *gitRepository) From(response *gqlclient.GitRepositoryFragment) {
Expand All @@ -30,5 +31,6 @@ func (g *gitRepository) Attributes() gqlclient.GitAttributes {
Password: g.Password.ValueStringPointer(),
HTTPSPath: g.HttpsPath.ValueStringPointer(),
URLFormat: g.UrlFormat.ValueStringPointer(),
Decrypt: g.Decrypt.ValueBoolPointer(),
}
}
Loading

0 comments on commit b11f150

Please sign in to comment.