summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulien Dessaux2023-06-18 17:01:35 +0200
committerJulien Dessaux2023-06-18 17:01:35 +0200
commit64ac1f44e0c27bba6b4bedc2ec564994daf3e029 (patch)
tree0abbdd7cc5465045a2658e1ef08ee9deaa0a445f
parentImplemented projects datasource (diff)
downloadterraform-provider-eventline-64ac1f44e0c27bba6b4bedc2ec564994daf3e029.tar.gz
terraform-provider-eventline-64ac1f44e0c27bba6b4bedc2ec564994daf3e029.tar.bz2
terraform-provider-eventline-64ac1f44e0c27bba6b4bedc2ec564994daf3e029.zip
Implemented project resource
-rw-r--r--internal/provider/project_resource.go145
-rw-r--r--internal/provider/projects_data_source.go29
-rw-r--r--internal/provider/provider.go4
3 files changed, 162 insertions, 16 deletions
diff --git a/internal/provider/project_resource.go b/internal/provider/project_resource.go
new file mode 100644
index 0000000..9e9d9e2
--- /dev/null
+++ b/internal/provider/project_resource.go
@@ -0,0 +1,145 @@
+package provider
+
+import (
+ "context"
+ "errors"
+ "fmt"
+
+ "git.adyxax.org/adyxax/terraform-eventline/internal/evcli"
+ "github.com/exograd/eventline/pkg/eventline"
+ "github.com/exograd/go-daemon/ksuid"
+ "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/planmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/resource/schema/stringplanmodifier"
+ "github.com/hashicorp/terraform-plugin-framework/types"
+)
+
+type ProjectResource struct {
+ client *evcli.Client
+}
+
+var _ resource.Resource = &ProjectResource{} // Ensure provider defined types fully satisfy framework interfaces
+var _ resource.ResourceWithImportState = &ProjectResource{} // Ensure provider defined types fully satisfy framework interfaces
+func NewProjectResource() resource.Resource {
+ return &ProjectResource{}
+}
+
+type ProjectResourceModel struct {
+ Id types.String `tfsdk:"id"`
+ Name types.String `tfsdk:"name"`
+}
+
+func (r *ProjectResource) Metadata(ctx context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
+ resp.TypeName = req.ProviderTypeName + "_project"
+}
+
+func (r *ProjectResource) Schema(ctx context.Context, req resource.SchemaRequest, resp *resource.SchemaResponse) {
+ resp.Schema = schema.Schema{
+ Attributes: map[string]schema.Attribute{
+ "id": schema.StringAttribute{
+ Computed: true,
+ MarkdownDescription: "Project Id",
+ PlanModifiers: []planmodifier.String{
+ stringplanmodifier.UseStateForUnknown(),
+ },
+ },
+ "name": schema.StringAttribute{
+ MarkdownDescription: "Project name",
+ Required: true,
+ },
+ },
+ MarkdownDescription: "Eventline project resource",
+ }
+}
+
+func (r *ProjectResource) Configure(ctx context.Context, req resource.ConfigureRequest, resp *resource.ConfigureResponse) {
+ r.client, _ = req.ProviderData.(*evcli.Client)
+}
+
+func (r *ProjectResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
+ var data *ProjectResourceModel
+ resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+ project := eventline.Project{Name: data.Name.ValueString()}
+ if err := r.client.CreateProject(&project); err != nil {
+ resp.Diagnostics.AddError("CreateProject", fmt.Sprintf("Unable to create project, got error: %s\nTry importing the resource instead?", err))
+ return
+ }
+ data.Id = types.StringValue(project.Id.String())
+ resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
+}
+
+func (r *ProjectResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
+ var data *ProjectResourceModel
+ resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+ var id ksuid.KSUID
+ if err := id.Parse(data.Id.ValueString()); err != nil {
+ resp.Diagnostics.AddError("KsuidParse", fmt.Sprintf("Unable to parse project id, got error: %s", err))
+ return
+ }
+ project, err := r.client.FetchProjectById(id)
+ if err != nil {
+ var e *evcli.APIError
+ if errors.As(err, &e) && e.Code == "unknown_project" {
+ resp.State.RemoveResource(ctx) // The project does not exist
+ return
+ }
+ resp.Diagnostics.AddError("FetchProjectById", fmt.Sprintf("Unable to fetch project by id, got error: %s", err))
+ return
+ }
+ data.Id = types.StringValue(project.Id.String())
+ data.Name = types.StringValue(project.Name)
+ resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
+}
+
+func (r *ProjectResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
+ var data *ProjectResourceModel
+ resp.Diagnostics.Append(req.Plan.Get(ctx, &data)...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+ var id ksuid.KSUID
+ if err := id.Parse(data.Id.ValueString()); err != nil {
+ resp.Diagnostics.AddError("KsuidParse", fmt.Sprintf("Unable to parse project id, got error: %s", err))
+ return
+ }
+ project := eventline.Project{Id: id, Name: data.Name.ValueString()}
+ if err := r.client.UpdateProject(&project); err != nil {
+ resp.Diagnostics.AddError("UpdateProject", fmt.Sprintf("Unable to update project, got error: %s", err))
+ return
+ }
+ data.Id = types.StringValue(project.Id.String())
+ resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
+}
+
+func (r *ProjectResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
+ var data *ProjectResourceModel
+ resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
+ if resp.Diagnostics.HasError() {
+ return
+ }
+ var id ksuid.KSUID
+ if err := id.Parse(data.Id.ValueString()); err != nil {
+ resp.Diagnostics.AddError("KsuidParse", fmt.Sprintf("Unable to parse project id, got error: %s", err))
+ return
+ }
+ if err := r.client.DeleteProject(id); err != nil {
+ var e *evcli.APIError
+ if errors.As(err, &e) && e.Code == "unknown_project" {
+ return // the project does not exist, that is what we want
+ }
+ resp.Diagnostics.AddError("DeleteProject", fmt.Sprintf("Unable to delete project by id, got error: %s", err))
+ return
+ }
+}
+
+func (r *ProjectResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
+ resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
+}
diff --git a/internal/provider/projects_data_source.go b/internal/provider/projects_data_source.go
index b13fd87..e0b5b8b 100644
--- a/internal/provider/projects_data_source.go
+++ b/internal/provider/projects_data_source.go
@@ -9,33 +9,31 @@ import (
"github.com/hashicorp/terraform-plugin-framework/datasource"
"github.com/hashicorp/terraform-plugin-framework/datasource/schema"
"github.com/hashicorp/terraform-plugin-framework/types"
- "github.com/hashicorp/terraform-plugin-framework/types/basetypes"
)
-type projectsDataSource struct {
+type ProjectsDataSource struct {
client *evcli.Client
}
-var _ datasource.DataSource = &projectsDataSource{} // Ensure provider defined types fully satisfy framework interfaces.
+var _ datasource.DataSource = &ProjectsDataSource{} // Ensure provider defined types fully satisfy framework interfaces
func NewProjectsDataSource() datasource.DataSource {
- return &projectsDataSource{}
+ return &ProjectsDataSource{}
}
-type ProjectsModel struct {
- Elements []ProjectModel `tfsdk:"elements"`
+type ProjectsDataSourceModel struct {
+ Elements []ProjectDataSourceModel `tfsdk:"elements"`
}
-type ProjectModel struct {
+type ProjectDataSourceModel struct {
Id types.String `tfsdk:"id"`
Name types.String `tfsdk:"name"`
}
-func (d *projectsDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
+func (d *ProjectsDataSource) Metadata(ctx context.Context, req datasource.MetadataRequest, resp *datasource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_projects"
}
-func (d *projectsDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
+func (d *ProjectsDataSource) Schema(ctx context.Context, req datasource.SchemaRequest, resp *datasource.SchemaResponse) {
resp.Schema = schema.Schema{
- MarkdownDescription: "Eventline projects data source",
Attributes: map[string]schema.Attribute{
"elements": schema.ListAttribute{
Computed: true,
@@ -48,15 +46,16 @@ func (d *projectsDataSource) Schema(ctx context.Context, req datasource.SchemaRe
MarkdownDescription: "Projects list",
},
},
+ MarkdownDescription: "Eventline projects data source",
}
}
-func (d *projectsDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
+func (d *ProjectsDataSource) Configure(ctx context.Context, req datasource.ConfigureRequest, resp *datasource.ConfigureResponse) {
d.client, _ = req.ProviderData.(*evcli.Client)
}
-func (d *projectsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
- var data ProjectsModel
+func (d *ProjectsDataSource) Read(ctx context.Context, req datasource.ReadRequest, resp *datasource.ReadResponse) {
+ var data ProjectsDataSourceModel
resp.Diagnostics.Append(req.Config.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
@@ -66,9 +65,9 @@ func (d *projectsDataSource) Read(ctx context.Context, req datasource.ReadReques
resp.Diagnostics.AddError("FetchProjects", fmt.Sprintf("Unable to fetch projects, got error: %s", err))
return
}
- projectList := make([]ProjectModel, len(projects))
+ projectList := make([]ProjectDataSourceModel, len(projects))
for i, project := range projects {
- projectList[i] = ProjectModel{Id: basetypes.NewStringValue(project.Id.String()), Name: basetypes.NewStringValue(project.Name)}
+ projectList[i] = ProjectDataSourceModel{Id: types.StringValue(project.Id.String()), Name: types.StringValue(project.Name)}
}
data.Elements = projectList
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
diff --git a/internal/provider/provider.go b/internal/provider/provider.go
index c29a915..3ae769e 100644
--- a/internal/provider/provider.go
+++ b/internal/provider/provider.go
@@ -70,7 +70,9 @@ func (p *Provider) Configure(ctx context.Context, req provider.ConfigureRequest,
}
func (p *Provider) Resources(ctx context.Context) []func() resource.Resource {
- return []func() resource.Resource{}
+ return []func() resource.Resource{
+ NewProjectResource,
+ }
}
func (p *Provider) DataSources(ctx context.Context) []func() datasource.DataSource {