internal/provider/resource_gitlab_integration_telegram.go (243 lines of code) (raw):
package provider
import (
"context"
"fmt"
"github.com/hashicorp/terraform-plugin-framework-validators/stringvalidator"
"github.com/hashicorp/terraform-plugin-framework/diag"
"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"
"github.com/hashicorp/terraform-plugin-framework/tfsdk"
"github.com/hashicorp/terraform-plugin-framework/types"
"github.com/hashicorp/terraform-plugin-log/tflog"
gitlab "gitlab.com/gitlab-org/api/client-go"
"gitlab.com/gitlab-org/terraform-provider-gitlab/internal/provider/api"
"gitlab.com/gitlab-org/terraform-provider-gitlab/internal/provider/utils"
)
var (
_ resource.Resource = &gitlabIntegrationTelegramResource{}
_ resource.ResourceWithConfigure = &gitlabIntegrationTelegramResource{}
_ resource.ResourceWithImportState = &gitlabIntegrationTelegramResource{}
)
func init() {
registerResource(NewGitlabIntegrationTelegramResource)
}
func NewGitlabIntegrationTelegramResource() resource.Resource {
return &gitlabIntegrationTelegramResource{}
}
type gitlabIntegrationTelegramResourceModel struct {
Id types.String `tfsdk:"id"`
Project types.String `tfsdk:"project"`
Token types.String `tfsdk:"token"`
Room types.String `tfsdk:"room"`
NotifyOnlyBrokenPipelines types.Bool `tfsdk:"notify_only_broken_pipelines"`
BranchesToBeNotified types.String `tfsdk:"branches_to_be_notified"`
PushEvents types.Bool `tfsdk:"push_events"`
IssuesEvents types.Bool `tfsdk:"issues_events"`
ConfidentialIssuesEvents types.Bool `tfsdk:"confidential_issues_events"`
MergeRequestsEvents types.Bool `tfsdk:"merge_requests_events"`
TagPushEvents types.Bool `tfsdk:"tag_push_events"`
NoteEvents types.Bool `tfsdk:"note_events"`
ConfidentialNoteEvents types.Bool `tfsdk:"confidential_note_events"`
PipelineEvents types.Bool `tfsdk:"pipeline_events"`
WikiPageEvents types.Bool `tfsdk:"wiki_page_events"`
}
func (r *gitlabIntegrationTelegramResourceModel) TelegramServiceToStateModel(service *gitlab.TelegramService, projectId string) {
r.Id = types.StringValue(projectId)
r.Project = types.StringValue(projectId)
r.Room = types.StringValue(service.Properties.Room)
r.NotifyOnlyBrokenPipelines = types.BoolValue(service.Properties.NotifyOnlyBrokenPipelines)
r.BranchesToBeNotified = types.StringValue(service.Properties.BranchesToBeNotified)
r.PushEvents = types.BoolValue(service.PushEvents)
r.IssuesEvents = types.BoolValue(service.IssuesEvents)
r.ConfidentialIssuesEvents = types.BoolValue(service.ConfidentialIssuesEvents)
r.MergeRequestsEvents = types.BoolValue(service.MergeRequestsEvents)
r.TagPushEvents = types.BoolValue(service.TagPushEvents)
r.NoteEvents = types.BoolValue(service.NoteEvents)
r.ConfidentialNoteEvents = types.BoolValue(service.ConfidentialNoteEvents)
r.PipelineEvents = types.BoolValue(service.PipelineEvents)
r.WikiPageEvents = types.BoolValue(service.WikiPageEvents)
}
type gitlabIntegrationTelegramResource struct {
client *gitlab.Client
}
func (r *gitlabIntegrationTelegramResource) Metadata(_ context.Context, req resource.MetadataRequest, resp *resource.MetadataResponse) {
resp.TypeName = req.ProviderTypeName + "_integration_telegram"
}
func (r *gitlabIntegrationTelegramResource) Schema(_ context.Context, _ resource.SchemaRequest, resp *resource.SchemaResponse) {
resp.Schema = schema.Schema{
MarkdownDescription: `The ` + "`gitlab_integration_telegram`" + ` resource allows to manage the lifecycle of a project integration with Telegram.
**Upstream API**: [GitLab REST API docs](https://docs.gitlab.com/api/project_integrations/#telegram)`,
Attributes: map[string]schema.Attribute{
"id": schema.StringAttribute{
Computed: true,
MarkdownDescription: "The ID of this Terraform resource. In the format of `<project>`.",
PlanModifiers: []planmodifier.String{stringplanmodifier.UseStateForUnknown()},
},
"project": schema.StringAttribute{
MarkdownDescription: "The ID or full path of the project to integrate with Telegram.",
Required: true,
PlanModifiers: []planmodifier.String{stringplanmodifier.RequiresReplace()},
Validators: []validator.String{stringvalidator.LengthAtLeast(1)},
},
"token": schema.StringAttribute{
MarkdownDescription: "The Telegram bot token.",
Required: true,
Sensitive: true,
Validators: []validator.String{stringvalidator.LengthAtLeast(1)},
},
"room": schema.StringAttribute{
MarkdownDescription: "Unique identifier for the target chat or the username of the target channel (in the format `@channelusername`)",
Required: true,
Validators: []validator.String{stringvalidator.LengthAtLeast(1)},
},
"notify_only_broken_pipelines": schema.BoolAttribute{
MarkdownDescription: "Send notifications for broken pipelines.",
Optional: true,
Computed: true,
Default: booldefault.StaticBool(true),
},
"branches_to_be_notified": schema.StringAttribute{
MarkdownDescription: fmt.Sprintf("Branches to send notifications for. Valid options are %s.", utils.RenderValueListForDocs(api.ValidBranchesToBeNotified)),
Optional: true,
Computed: true,
Validators: []validator.String{stringvalidator.OneOf(api.ValidBranchesToBeNotified...)},
},
"push_events": schema.BoolAttribute{
MarkdownDescription: "Enable notifications for push events.",
Required: true,
},
"issues_events": schema.BoolAttribute{
MarkdownDescription: "Enable notifications for issues events.",
Required: true,
},
"confidential_issues_events": schema.BoolAttribute{
MarkdownDescription: "Enable notifications for confidential issues events.",
Required: true,
},
"merge_requests_events": schema.BoolAttribute{
MarkdownDescription: "Enable notifications for merge requests events.",
Required: true,
},
"tag_push_events": schema.BoolAttribute{
MarkdownDescription: "Enable notifications for tag push events.",
Required: true,
},
"note_events": schema.BoolAttribute{
MarkdownDescription: "Enable notifications for note events.",
Required: true,
},
"confidential_note_events": schema.BoolAttribute{
MarkdownDescription: "Enable notifications for confidential note events.",
Required: true,
},
"pipeline_events": schema.BoolAttribute{
MarkdownDescription: "Enable notifications for pipeline events.",
Required: true,
},
"wiki_page_events": schema.BoolAttribute{
MarkdownDescription: "Enable notifications for wiki page events.",
Required: true,
},
},
}
}
func (r *gitlabIntegrationTelegramResource) Configure(_ context.Context, req resource.ConfigureRequest, _ *resource.ConfigureResponse) {
if req.ProviderData == nil {
return
}
resourceData := req.ProviderData.(*GitLabResourceData)
r.client = resourceData.Client
}
func (r *gitlabIntegrationTelegramResource) Create(ctx context.Context, req resource.CreateRequest, resp *resource.CreateResponse) {
err := r.update(ctx, &req.Plan, &resp.State, &resp.Diagnostics)
if err != nil {
resp.Diagnostics.AddError("Failed to create telegram integration", err.Error())
}
}
func (r *gitlabIntegrationTelegramResource) Read(ctx context.Context, req resource.ReadRequest, resp *resource.ReadResponse) {
var data gitlabIntegrationTelegramResourceModel
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
projectId := data.Id.ValueString()
service, _, err := r.client.Services.GetTelegramService(projectId, gitlab.WithContext(ctx))
if err != nil {
if api.Is404(err) {
tflog.Debug(ctx, "telegram integration doesn't exist, removing from state", map[string]any{
"project": data.Project,
})
resp.State.RemoveResource(ctx)
return
}
resp.Diagnostics.AddError("GitLab API error occurred", fmt.Sprintf("Error reading telegram integration for project %s", err.Error()))
return
}
data.TelegramServiceToStateModel(service, projectId)
resp.Diagnostics.Append(resp.State.Set(ctx, &data)...)
}
func (r *gitlabIntegrationTelegramResource) Update(ctx context.Context, req resource.UpdateRequest, resp *resource.UpdateResponse) {
err := r.update(ctx, &req.Plan, &resp.State, &resp.Diagnostics)
if err != nil {
resp.Diagnostics.AddError("Failed to update telegram integration", err.Error())
}
}
func (r *gitlabIntegrationTelegramResource) update(ctx context.Context, plan *tfsdk.Plan, state *tfsdk.State, diags *diag.Diagnostics) error {
var data gitlabIntegrationTelegramResourceModel
diags.Append(plan.Get(ctx, &data)...)
if diags.HasError() {
return nil
}
projectId := data.Project.ValueString()
options := &gitlab.SetTelegramServiceOptions{
Token: data.Token.ValueStringPointer(),
Room: data.Room.ValueStringPointer(),
NotifyOnlyBrokenPipelines: data.NotifyOnlyBrokenPipelines.ValueBoolPointer(),
BranchesToBeNotified: data.BranchesToBeNotified.ValueStringPointer(),
PushEvents: data.PushEvents.ValueBoolPointer(),
IssuesEvents: data.IssuesEvents.ValueBoolPointer(),
ConfidentialIssuesEvents: data.ConfidentialIssuesEvents.ValueBoolPointer(),
MergeRequestsEvents: data.MergeRequestsEvents.ValueBoolPointer(),
TagPushEvents: data.TagPushEvents.ValueBoolPointer(),
NoteEvents: data.NoteEvents.ValueBoolPointer(),
ConfidentialNoteEvents: data.ConfidentialNoteEvents.ValueBoolPointer(),
PipelineEvents: data.PipelineEvents.ValueBoolPointer(),
WikiPageEvents: data.WikiPageEvents.ValueBoolPointer(),
}
if _, _, err := r.client.Services.SetTelegramService(projectId, options, gitlab.WithContext(ctx)); err != nil {
return err
}
service, _, err := r.client.Services.GetTelegramService(projectId, gitlab.WithContext(ctx))
if err != nil {
return err
}
data.TelegramServiceToStateModel(service, projectId)
diags.Append(state.Set(ctx, &data)...)
return nil
}
func (r *gitlabIntegrationTelegramResource) Delete(ctx context.Context, req resource.DeleteRequest, resp *resource.DeleteResponse) {
var data gitlabIntegrationTelegramResourceModel
resp.Diagnostics.Append(req.State.Get(ctx, &data)...)
if resp.Diagnostics.HasError() {
return
}
projectId := data.Id.ValueString()
if _, err := r.client.Services.DeleteTelegramService(projectId, gitlab.WithContext(ctx)); err != nil {
if api.Is404(err) {
tflog.Debug(ctx, "telegram integration doesn't exist, removing from state", map[string]any{
"project": data.Project,
})
return
}
resp.Diagnostics.AddError("GitLab API error occurred", fmt.Sprintf("Error deleting telegram integration for project %s", err.Error()))
return
}
}
func (r *gitlabIntegrationTelegramResource) ImportState(ctx context.Context, req resource.ImportStateRequest, resp *resource.ImportStateResponse) {
resource.ImportStatePassthroughID(ctx, path.Root("id"), req, resp)
}