Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## Enhancements
* Adds BETA support for listing `TFPolicyEvaluationOutcome`, which is EXPERIMENTAL, SUBJECT TO CHANGE, and may not be available to all users by @subhro-acharjee-1 [#1313](https://github.com/hashicorp/go-tfe/pull/1313)
* Adds support for `NotificationConfigurationSubscribableChoice` type `Project` to support Project Level Notifications by @jillirami [#1350](https://github.com/hashicorp/go-tfe/pull/1350)


# v1.107.0

Expand Down
47 changes: 47 additions & 0 deletions helper_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -962,6 +962,53 @@ func createTeamNotificationConfiguration(t *testing.T, client *Client, team *Tea
}
}

func createProjectNotificationConfiguration(t *testing.T, client *Client, project *Project, options *NotificationConfigurationCreateOptions) (*NotificationConfiguration, func()) {
var pCleanup func()

if project == nil {
project, pCleanup = createProject(t, client, nil)
}

runTaskURL := os.Getenv("TFC_RUN_TASK_URL")
if runTaskURL == "" {
t.Error("You must set TFC_RUN_TASK_URL for run task related tests.")
}

if options == nil {
options = &NotificationConfigurationCreateOptions{
DestinationType: NotificationDestination(NotificationDestinationTypeGeneric),
Enabled: Bool(false),
Name: String(randomString(t)),
Token: String(randomString(t)),
URL: String(runTaskURL),
Triggers: []NotificationTriggerType{NotificationTriggerCreated},
SubscribableChoice: &NotificationConfigurationSubscribableChoice{Project: project},
}
}

ctx := context.Background()
nc, err := client.NotificationConfigurations.Create(
ctx,
project.ID,
*options,
)
if err != nil {
t.Fatal(err)
}

return nc, func() {
if err := client.NotificationConfigurations.Delete(ctx, nc.ID); err != nil {
t.Errorf("Error destroying project notification configuration! WARNING: Dangling\n"+
"resources may exist! The full error is shown below.\n\n"+
"NotificationConfiguration: %s\nError: %s", nc.ID, err)
}

if pCleanup != nil {
pCleanup()
}
}
}

func createPolicySetParameter(t *testing.T, client *Client, ps *PolicySet) (*PolicySetParameter, func()) {
var psCleanup func()

Expand Down
84 changes: 56 additions & 28 deletions notification_configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ type NotificationConfigurationList struct {
// within a polymorphic relation. If a value is available, exactly one field
// will be non-nil.
type NotificationConfigurationSubscribableChoice struct {
Project *Project
Team *Team
Workspace *Workspace
}
Expand Down Expand Up @@ -165,7 +166,7 @@ type NotificationConfigurationCreateOptions struct {
// Optional: The list of users belonging to the organization that will receive notification emails.
EmailUsers []*User `jsonapi:"relation,users,omitempty"`

// Required: The workspace or team that the notification configuration is associated with.
// Required: The workspace, team, or project that the notification configuration is associated with.
SubscribableChoice *NotificationConfigurationSubscribableChoice `jsonapi:"polyrelation,subscribable,omitempty"`
}

Expand Down Expand Up @@ -203,7 +204,6 @@ type NotificationConfigurationUpdateOptions struct {

// List all the notification configurations associated with a workspace.
func (s *notificationConfigurations) List(ctx context.Context, subscribableID string, options *NotificationConfigurationListOptions) (*NotificationConfigurationList, error) {
var u string
if options == nil {
options = &NotificationConfigurationListOptions{
SubscribableChoice: &NotificationConfigurationSubscribableChoice{
Expand All @@ -216,16 +216,9 @@ func (s *notificationConfigurations) List(ctx context.Context, subscribableID st
}
}

if options.SubscribableChoice.Team != nil {
if !validStringID(&subscribableID) {
return nil, ErrInvalidTeamID
}
u = fmt.Sprintf("teams/%s/notification-configurations", url.PathEscape(subscribableID))
} else {
if !validStringID(&subscribableID) {
return nil, ErrInvalidWorkspaceID
}
u = fmt.Sprintf("workspaces/%s/notification-configurations", url.PathEscape(subscribableID))
u, err := notificationSubscribableURL(subscribableID, options.SubscribableChoice)
if err != nil {
return nil, err
}

req, err := s.client.NewRequest("GET", u, options)
Expand All @@ -248,26 +241,29 @@ func (s *notificationConfigurations) List(ctx context.Context, subscribableID st

// Create a notification configuration with the given options.
func (s *notificationConfigurations) Create(ctx context.Context, subscribableID string, options NotificationConfigurationCreateOptions) (*NotificationConfiguration, error) {
var u string
var subscribableChoice *NotificationConfigurationSubscribableChoice
if options.SubscribableChoice == nil || options.SubscribableChoice.Team == nil {
u = fmt.Sprintf("workspaces/%s/notification-configurations", url.PathEscape(subscribableID))
options.SubscribableChoice = &NotificationConfigurationSubscribableChoice{Workspace: &Workspace{ID: subscribableID}}
} else {
u = fmt.Sprintf("teams/%s/notification-configurations", url.PathEscape(subscribableID))
if options.SubscribableChoice != nil && options.SubscribableChoice.Team != nil {
options.SubscribableChoice = &NotificationConfigurationSubscribableChoice{Team: &Team{ID: subscribableID}}
} else if options.SubscribableChoice != nil && options.SubscribableChoice.Project != nil {
options.SubscribableChoice = &NotificationConfigurationSubscribableChoice{Project: &Project{ID: subscribableID}}
} else {
options.SubscribableChoice = &NotificationConfigurationSubscribableChoice{Workspace: &Workspace{ID: subscribableID}}
}

if err := options.valid(); err != nil {
return nil, err
}

u, err := notificationSubscribableURL(subscribableID, options.SubscribableChoice)
if err != nil {
return nil, err
}

req, err := s.client.NewRequest("POST", u, &options)
if err != nil {
return nil, err
}

nc := &NotificationConfiguration{SubscribableChoice: subscribableChoice}
nc := &NotificationConfiguration{}
err = req.Do(ctx, nc)

if err != nil {
Expand Down Expand Up @@ -368,14 +364,8 @@ func (s *notificationConfigurations) Verify(ctx context.Context, notificationCon
}

func (o NotificationConfigurationCreateOptions) valid() error {
if o.SubscribableChoice == nil || o.SubscribableChoice.Workspace != nil {
if !validStringID(&o.SubscribableChoice.Workspace.ID) {
return ErrInvalidWorkspaceID
}
} else {
if !validStringID(&o.SubscribableChoice.Team.ID) {
return ErrInvalidTeamID
}
if err := validateSubscribableChoice(o.SubscribableChoice); err != nil {
return err
}

if o.DestinationType == nil {
Expand Down Expand Up @@ -424,6 +414,44 @@ func backfillDeprecatedSubscribable(notification *NotificationConfiguration) {
}
}

func notificationSubscribableURL(subscribableID string, choice *NotificationConfigurationSubscribableChoice) (string, error) {
if choice != nil && choice.Team != nil {
if !validStringID(&subscribableID) {
return "", ErrInvalidTeamID
}
return fmt.Sprintf("teams/%s/notification-configurations", url.PathEscape(subscribableID)), nil
}
if choice != nil && choice.Project != nil {
if !validStringID(&subscribableID) {
return "", ErrInvalidProjectID
}
return fmt.Sprintf("projects/%s/notification-configurations", url.PathEscape(subscribableID)), nil
}
if choice == nil || !validStringID(&subscribableID) {
return "", ErrInvalidWorkspaceID
}
return fmt.Sprintf("workspaces/%s/notification-configurations", url.PathEscape(subscribableID)), nil
}

func validateSubscribableChoice(choice *NotificationConfigurationSubscribableChoice) error {
if choice != nil && choice.Team != nil {
if !validStringID(&choice.Team.ID) {
return ErrInvalidTeamID
}
return nil
}
if choice != nil && choice.Project != nil {
if !validStringID(&choice.Project.ID) {
return ErrInvalidProjectID
}
return nil
}
if choice == nil || !validStringID(&choice.Workspace.ID) {
return ErrInvalidWorkspaceID
}
return nil
}

func validNotificationTriggerType(triggers []NotificationTriggerType) bool {
for _, t := range triggers {
switch t {
Expand Down
Loading
Loading