Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

azuread_user: support employee hire date #1437

Draft
wants to merge 2 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
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
1 change: 1 addition & 0 deletions docs/data-sources/user.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ The following attributes are exported:
* `department` - The name for the department in which the user works.
* `display_name` - The display name of the user.
* `division` - The name of the division in which the user works.
* `employee_hire_date` - The hire date of the user, formatted as an RFC3339 date string (e.g. `2018-01-01T01:02:03Z`).
* `employee_id` - The employee identifier assigned to the user by the organisation.
* `employee_type` - Captures enterprise worker type. For example, Employee, Contractor, Consultant, or Vendor.
* `external_user_state` - For an external user invited to the tenant, this property represents the invited user's invitation status. Possible values are `PendingAcceptance` or `Accepted`.
Expand Down
1 change: 1 addition & 0 deletions docs/resources/user.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ The following arguments are supported:
* `disable_strong_password` - (Optional) Whether the user is allowed weaker passwords than the default policy to be specified. Defaults to `false`.
* `display_name` - (Required) The name to display in the address book for the user.
* `division` - (Optional) The name of the division in which the user works.
* `employee_hire_date` - The hire date of the user, formatted as an RFC3339 date string (e.g. `2018-01-01T01:02:03Z`).
* `employee_id` - (Optional) The employee identifier assigned to the user by the organisation.
* `employee_type` - (Optional) Captures enterprise worker type. For example, Employee, Contractor, Consultant, or Vendor.
* `fax_number` - (Optional) The fax number of the user.
Expand Down
7 changes: 7 additions & 0 deletions internal/services/users/user_data_source.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,12 @@ func userDataSource() *pluginsdk.Resource {
Computed: true,
},

"employee_hire_date": {
Description: "The hire date of the user, formatted as an RFC3339 date string (e.g. `2018-01-01T01:02:03Z`).",
Type: pluginsdk.TypeString,
Computed: true,
},

"employee_type": {
Description: "Captures enterprise worker type. For example, Employee, Contractor, Consultant, or Vendor.",
Type: pluginsdk.TypeString,
Expand Down Expand Up @@ -452,6 +458,7 @@ func userDataSourceRead(ctx context.Context, d *pluginsdk.ResourceData, meta int
"creationType",
"department",
"displayName",
"employee_hire_date",
"employeeId",
"employeeOrgData",
"employeeType",
Expand Down
1 change: 1 addition & 0 deletions internal/services/users/user_data_source_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ func (UserDataSource) testCheckFunc(data acceptance.TestData) acceptance.TestChe
check.That(data.ResourceName).Key("country").HasValue(fmt.Sprintf("acctestUser-%d-Country", data.RandomInteger)),
check.That(data.ResourceName).Key("department").HasValue(fmt.Sprintf("acctestUser-%d-Dept", data.RandomInteger)),
check.That(data.ResourceName).Key("display_name").HasValue(fmt.Sprintf("acctestUser-%d-DisplayName", data.RandomInteger)),
check.That(data.ResourceName).Key("employee_hire_date").HasValue("2018-01-01T01:02:03Z"),
check.That(data.ResourceName).Key("given_name").HasValue(fmt.Sprintf("acctestUser-%d-GivenName", data.RandomInteger)),
check.That(data.ResourceName).Key("job_title").HasValue(fmt.Sprintf("acctestUser-%d-Job", data.RandomInteger)),
// check.That(data.ResourceName).Key("mail").Exists(), // TODO only set for O365 domains
Expand Down
24 changes: 24 additions & 0 deletions internal/services/users/user_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,13 @@ func userResource() *pluginsdk.Resource {
Optional: true,
},

"employee_hire_date": {
Description: "The hire date of the user, formatted as an RFC3339 date string (e.g. `2018-01-01T01:02:03Z`).",
Type: pluginsdk.TypeString,
Optional: true,
ValidateFunc: validation.IsRFC3339Time,
},

"employee_id": {
Description: "The employee identifier assigned to the user by the organisation",
Type: pluginsdk.TypeString,
Expand Down Expand Up @@ -475,6 +482,14 @@ func userResourceCreate(ctx context.Context, d *pluginsdk.ResourceData, meta int
properties.OnPremisesImmutableId = nullable.NoZero(v.(string))
}

if v, ok := d.GetOk("employee_hire_date"); ok {
employeeHireDate, err := time.Parse(time.RFC3339, v.(string))
if err != nil {
tf.ErrorDiagF(err, "Unable to parse the provided employee_hire_date %q: %+v", v, err)
}
properties.EmployeeHireDate = &employeeHireDate
}

options := user.CreateUserOperationOptions{
RetryFunc: func(resp *http.Response, o *odata.OData) (bool, error) {
if response.WasBadRequest(resp) && o != nil && o.Error != nil {
Expand Down Expand Up @@ -611,6 +626,14 @@ func userResourceUpdate(ctx context.Context, d *pluginsdk.ResourceData, meta int
properties.ShowInAddressList = nullable.NoZero(d.Get("show_in_address_list").(bool))
}

if d.HasChange("employee_hire_date") {
employeeHireDate, err := time.Parse(time.RFC3339, d.Get("employee_hire_date").(string))
if err != nil {
tf.ErrorDiagF(err, "Unable to parse the provided employee_hire_date %q: %+v", d.Get("employee_hire_date"), err)
}
properties.EmployeeHireDate = &employeeHireDate
}

if _, err = client.UpdateUser(ctx, *id, properties, user.DefaultUpdateUserOperationOptions()); err != nil {
// Flag the state as 'partial' to avoid setting `password` from the current config. Since the config is the
// only source for this property, if the update fails due to a bad password, the current password will be forgotten
Expand Down Expand Up @@ -738,6 +761,7 @@ func userResourceRead(ctx context.Context, d *pluginsdk.ResourceData, meta inter
tf.Set(d, "consent_provided_for_minor", uExtra.ConsentProvidedForMinor.GetOrZero())
tf.Set(d, "country", uExtra.Country.GetOrZero())
tf.Set(d, "department", uExtra.Department.GetOrZero())
tf.Set(d, "employee_hire_date", user.EmployeeHireDate.Format(time.RFC3339))
tf.Set(d, "employee_id", uExtra.EmployeeId.GetOrZero())
tf.Set(d, "employee_type", uExtra.EmployeeType.GetOrZero())
tf.Set(d, "external_user_state", uExtra.ExternalUserState.GetOrZero())
Expand Down
1 change: 1 addition & 0 deletions internal/services/users/user_resource_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,7 @@ resource "azuread_user" "test" {
department = "acctestUser-%[1]d-Dept"
display_name = "acctestUser-%[1]d-DisplayName"
division = "acctestUser-%[1]d-Division"
employee_hire_date = "2018-01-01T01:02:03Z"
employee_id = "%[3]s%[3]s"
employee_type = "Contractor"
fax_number = "(555) 555-5555"
Expand Down