From b122523d22d7b1dfa3c3d0c59e2e90214d624473 Mon Sep 17 00:00:00 2001 From: Dan Petersen Date: Sun, 8 Dec 2019 23:57:45 +0100 Subject: [PATCH] Latest work --- CHANGELOG.md | 2 + README.md | 31 +++ data_source_virtual_environment_groups.go | 2 +- data_source_virtual_environment_roles.go | 2 +- data_source_virtual_environment_user.go | 151 ++++++++++++++ data_source_virtual_environment_user_test.go | 44 +++++ data_source_virtual_environment_users.go | 185 ++++++++++++++++++ data_source_virtual_environment_users_test.go | 45 +++++ .../data_source_virtual_environment_user.tf | 39 ++++ .../data_source_virtual_environment_users.tf | 39 ++++ provider.go | 2 + proxmox/common_types.go | 29 +++ proxmox/virtual_environment_users.go | 125 ++++++++++++ 13 files changed, 694 insertions(+), 2 deletions(-) create mode 100644 data_source_virtual_environment_user.go create mode 100644 data_source_virtual_environment_user_test.go create mode 100644 data_source_virtual_environment_users.go create mode 100644 data_source_virtual_environment_users_test.go create mode 100644 example/data_source_virtual_environment_user.tf create mode 100644 example/data_source_virtual_environment_users.tf create mode 100644 proxmox/virtual_environment_users.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 1db529d6..316336aa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ FEATURES: * **New Data Source:** `proxmox_virtual_environment_groups` * **New Data Source:** `proxmox_virtual_environment_role` * **New Data Source:** `proxmox_virtual_environment_roles` +* **New Data Source:** `proxmox_virtual_environment_user` +* **New Data Source:** `proxmox_virtual_environment_users` * **New Data Source:** `proxmox_virtual_environment_version` * **New Resource:** `proxmox_virtual_environment_group` * **New Resource:** `proxmox_virtual_environment_role` diff --git a/README.md b/README.md index cf2c56e2..625e2181 100644 --- a/README.md +++ b/README.md @@ -73,6 +73,37 @@ This data source doesn't accept arguments. * `role_ids` - The role ids. * `special` - Whether the role is special (built-in). +##### User (proxmox_virtual_environment_user) + +###### Arguments +* `user_id` - (Required) The user id. + +###### Attributes +* `comment` - The user comment +* `email` - The user's email address +* `enabled` - Whether the user account is enabled +* `expiration_date` - The user account's expiration date +* `first_name` - The user's first name +* `groups` - The user's groups +* `keys` - The user's keys +* `last_name` - The user's last name + +##### Users (proxmox_virtual_environment_user) + +###### Arguments +This data source doesn't accept arguments. + +###### Attributes +* `comments` - The user comments +* `emails` - The users' email addresses +* `enabled` - Whether a user account is enabled +* `expiration_dates` - The user accounts' expiration dates +* `first_names` - The users' first names +* `groups` - The users' groups +* `keys` - The users' keys +* `last_names` - The users' last names +* `user_ids` - The user ids. + ##### Version (proxmox_virtual_environment_version) ###### Arguments diff --git a/data_source_virtual_environment_groups.go b/data_source_virtual_environment_groups.go index 33ad150e..2a86189b 100644 --- a/data_source_virtual_environment_groups.go +++ b/data_source_virtual_environment_groups.go @@ -60,7 +60,7 @@ func dataSourceVirtualEnvironmentGroupsRead(d *schema.ResourceData, m interface{ groupIDs[i] = v.ID } - d.SetId("access_groups") + d.SetId("groups") d.Set(mkDataSourceVirtualEnvironmentGroupsComments, comments) d.Set(mkDataSourceVirtualEnvironmentGroupsGroupIDs, groupIDs) diff --git a/data_source_virtual_environment_roles.go b/data_source_virtual_environment_roles.go index adbb0c97..5e280c52 100644 --- a/data_source_virtual_environment_roles.go +++ b/data_source_virtual_environment_roles.go @@ -83,7 +83,7 @@ func dataSourceVirtualEnvironmentRolesRead(d *schema.ResourceData, m interface{} } } - d.SetId("access_roles") + d.SetId("roles") d.Set(mkDataSourceVirtualEnvironmentRolesPrivileges, privileges) d.Set(mkDataSourceVirtualEnvironmentRolesRoleIDs, roleIDs) diff --git a/data_source_virtual_environment_user.go b/data_source_virtual_environment_user.go new file mode 100644 index 00000000..916c34ab --- /dev/null +++ b/data_source_virtual_environment_user.go @@ -0,0 +1,151 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +package main + +import ( + "time" + + "github.com/hashicorp/terraform/helper/schema" +) + +const ( + mkDataSourceVirtualEnvironmentUserComment = "comment" + mkDataSourceVirtualEnvironmentUserEmail = "email" + mkDataSourceVirtualEnvironmentUserEnabled = "enabled" + mkDataSourceVirtualEnvironmentUserExpirationDate = "expiration_date" + mkDataSourceVirtualEnvironmentUserFirstName = "first_name" + mkDataSourceVirtualEnvironmentUserGroups = "groups" + mkDataSourceVirtualEnvironmentUserKeys = "keys" + mkDataSourceVirtualEnvironmentUserLastName = "last_name" + mkDataSourceVirtualEnvironmentUserUserID = "user_id" +) + +func dataSourceVirtualEnvironmentUser() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + mkDataSourceVirtualEnvironmentUserComment: &schema.Schema{ + Type: schema.TypeString, + Description: "The user comment", + Computed: true, + }, + mkDataSourceVirtualEnvironmentUserEmail: &schema.Schema{ + Type: schema.TypeString, + Description: "The user's email address", + Computed: true, + }, + mkDataSourceVirtualEnvironmentUserEnabled: &schema.Schema{ + Type: schema.TypeBool, + Description: "Whether the user account is enabled", + Computed: true, + }, + mkDataSourceVirtualEnvironmentUserExpirationDate: &schema.Schema{ + Type: schema.TypeString, + Description: "The user account's expiration date", + Computed: true, + }, + mkDataSourceVirtualEnvironmentUserFirstName: &schema.Schema{ + Type: schema.TypeString, + Description: "The user's first name", + Computed: true, + }, + mkDataSourceVirtualEnvironmentUserGroups: &schema.Schema{ + Type: schema.TypeList, + Description: "The user's groups", + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + mkDataSourceVirtualEnvironmentUserKeys: &schema.Schema{ + Type: schema.TypeString, + Description: "The user's keys", + Computed: true, + }, + mkDataSourceVirtualEnvironmentUserLastName: &schema.Schema{ + Type: schema.TypeString, + Description: "The user's last name", + Computed: true, + }, + mkDataSourceVirtualEnvironmentUserUserID: &schema.Schema{ + Type: schema.TypeString, + Description: "The user id", + Required: true, + }, + }, + Read: dataSourceVirtualEnvironmentUserRead, + } +} + +func dataSourceVirtualEnvironmentUserRead(d *schema.ResourceData, m interface{}) error { + config := m.(providerConfiguration) + veClient, err := config.GetVEClient() + + if err != nil { + return err + } + + userID := d.Get(mkDataSourceVirtualEnvironmentUserUserID).(string) + v, err := veClient.GetUser(userID) + + if err != nil { + return err + } + + d.SetId(userID) + + if v.Comment != nil { + d.Set(mkDataSourceVirtualEnvironmentUserComment, v.Comment) + } else { + d.Set(mkDataSourceVirtualEnvironmentUserComment, "") + } + + if v.Email != nil { + d.Set(mkDataSourceVirtualEnvironmentUserEmail, v.Email) + } else { + d.Set(mkDataSourceVirtualEnvironmentUserEmail, "") + } + + if v.Enabled != nil { + d.Set(mkDataSourceVirtualEnvironmentUserEnabled, v.Enabled) + } else { + d.Set(mkDataSourceVirtualEnvironmentUserEnabled, true) + } + + if v.ExpirationDate != nil { + t := time.Time(*v.ExpirationDate) + + if t.Unix() > 0 { + d.Set(mkDataSourceVirtualEnvironmentUserExpirationDate, t.UTC().Format(time.RFC3339)) + } else { + d.Set(mkDataSourceVirtualEnvironmentUserExpirationDate, time.Unix(2147483647, 0).UTC().Format(time.RFC3339)) + } + } else { + d.Set(mkDataSourceVirtualEnvironmentUserExpirationDate, time.Unix(2147483647, 0).UTC().Format(time.RFC3339)) + } + + if v.FirstName != nil { + d.Set(mkDataSourceVirtualEnvironmentUserFirstName, v.FirstName) + } else { + d.Set(mkDataSourceVirtualEnvironmentUserFirstName, "") + } + + if v.Groups != nil { + d.Set(mkDataSourceVirtualEnvironmentUserGroups, v.Groups) + } else { + d.Set(mkDataSourceVirtualEnvironmentUserGroups, "") + } + + if v.Keys != nil { + d.Set(mkDataSourceVirtualEnvironmentUserGroups, v.Keys) + } else { + d.Set(mkDataSourceVirtualEnvironmentUserGroups, "") + } + + if v.LastName != nil { + d.Set(mkDataSourceVirtualEnvironmentUserLastName, v.LastName) + } else { + d.Set(mkDataSourceVirtualEnvironmentUserLastName, "") + } + + return nil +} diff --git a/data_source_virtual_environment_user_test.go b/data_source_virtual_environment_user_test.go new file mode 100644 index 00000000..3eb5e0bb --- /dev/null +++ b/data_source_virtual_environment_user_test.go @@ -0,0 +1,44 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +package main + +import ( + "testing" +) + +// TestDataSourceVirtualEnvironmentUserInstantiation tests whether the DataSourceVirtualEnvironmentUser instance can be instantiated. +func TestDataSourceVirtualEnvironmentUserInstantiation(t *testing.T) { + s := dataSourceVirtualEnvironmentUser() + + if s == nil { + t.Fatalf("Cannot instantiate dataSourceVirtualEnvironmentUser") + } +} + +// TestDataSourceVirtualEnvironmentUserSchema tests the dataSourceVirtualEnvironmentUser schema. +func TestDataSourceVirtualEnvironmentUserSchema(t *testing.T) { + s := dataSourceVirtualEnvironmentUser() + + attributeKeys := []string{ + mkDataSourceVirtualEnvironmentUserComment, + mkDataSourceVirtualEnvironmentUserEmail, + mkDataSourceVirtualEnvironmentUserEnabled, + mkDataSourceVirtualEnvironmentUserExpirationDate, + mkDataSourceVirtualEnvironmentUserFirstName, + mkDataSourceVirtualEnvironmentUserGroups, + mkDataSourceVirtualEnvironmentUserKeys, + mkDataSourceVirtualEnvironmentUserLastName, + } + + for _, v := range attributeKeys { + if s.Schema[v] == nil { + t.Fatalf("Error in dataSourceVirtualEnvironmentUser.Schema: Missing attribute \"%s\"", v) + } + + if s.Schema[v].Computed != true { + t.Fatalf("Error in dataSourceVirtualEnvironmentUser.Schema: Attribute \"%s\" is not computed", v) + } + } +} diff --git a/data_source_virtual_environment_users.go b/data_source_virtual_environment_users.go new file mode 100644 index 00000000..e156576a --- /dev/null +++ b/data_source_virtual_environment_users.go @@ -0,0 +1,185 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +package main + +import ( + "time" + + "github.com/hashicorp/terraform/helper/schema" +) + +const ( + mkDataSourceVirtualEnvironmentUsersComments = "comments" + mkDataSourceVirtualEnvironmentUsersEmails = "emails" + mkDataSourceVirtualEnvironmentUsersEnabled = "enabled" + mkDataSourceVirtualEnvironmentUsersExpirationDates = "expiration_dates" + mkDataSourceVirtualEnvironmentUsersFirstNames = "first_names" + mkDataSourceVirtualEnvironmentUsersGroups = "groups" + mkDataSourceVirtualEnvironmentUsersKeys = "keys" + mkDataSourceVirtualEnvironmentUsersLastNames = "last_names" + mkDataSourceVirtualEnvironmentUsersUserIDs = "user_ids" +) + +func dataSourceVirtualEnvironmentUsers() *schema.Resource { + return &schema.Resource{ + Schema: map[string]*schema.Schema{ + mkDataSourceVirtualEnvironmentUsersComments: &schema.Schema{ + Type: schema.TypeList, + Description: "The user comments", + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + mkDataSourceVirtualEnvironmentUsersEmails: &schema.Schema{ + Type: schema.TypeList, + Description: "The users' email addresses", + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + mkDataSourceVirtualEnvironmentUsersEnabled: &schema.Schema{ + Type: schema.TypeList, + Description: "Whether a user account is enabled", + Computed: true, + Elem: &schema.Schema{Type: schema.TypeBool}, + }, + mkDataSourceVirtualEnvironmentUsersExpirationDates: &schema.Schema{ + Type: schema.TypeList, + Description: "The user accounts' expiration dates", + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + mkDataSourceVirtualEnvironmentUsersFirstNames: &schema.Schema{ + Type: schema.TypeList, + Description: "The users' first names", + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + mkDataSourceVirtualEnvironmentUsersGroups: &schema.Schema{ + Type: schema.TypeList, + Description: "The users' groups", + Computed: true, + Elem: &schema.Schema{ + Type: schema.TypeList, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + mkDataSourceVirtualEnvironmentUsersKeys: &schema.Schema{ + Type: schema.TypeList, + Description: "The users' keys", + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + mkDataSourceVirtualEnvironmentUsersLastNames: &schema.Schema{ + Type: schema.TypeList, + Description: "The users' last names", + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + mkDataSourceVirtualEnvironmentUsersUserIDs: &schema.Schema{ + Type: schema.TypeList, + Description: "The user ids", + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + Read: dataSourceVirtualEnvironmentUsersRead, + } +} + +func dataSourceVirtualEnvironmentUsersRead(d *schema.ResourceData, m interface{}) error { + config := m.(providerConfiguration) + veClient, err := config.GetVEClient() + + if err != nil { + return err + } + + list, err := veClient.ListUsers() + + if err != nil { + return err + } + + comments := make([]interface{}, len(list)) + emails := make([]interface{}, len(list)) + enabled := make([]interface{}, len(list)) + expirationDates := make([]interface{}, len(list)) + firstNames := make([]interface{}, len(list)) + groups := make([]interface{}, len(list)) + keys := make([]interface{}, len(list)) + lastNames := make([]interface{}, len(list)) + userIDs := make([]interface{}, len(list)) + + for i, v := range list { + if v.Comment != nil { + comments[i] = v.Comment + } else { + comments[i] = "" + } + + if v.Email != nil { + emails[i] = v.Email + } else { + emails[i] = "" + } + + if v.Enabled != nil { + enabled[i] = v.Enabled + } else { + enabled[i] = true + } + + if v.ExpirationDate != nil { + t := time.Time(*v.ExpirationDate) + + if t.Unix() > 0 { + expirationDates[i] = t.UTC().Format(time.RFC3339) + } else { + expirationDates[i] = time.Unix(2147483647, 0).UTC().Format(time.RFC3339) + } + } else { + expirationDates[i] = time.Unix(2147483647, 0).UTC().Format(time.RFC3339) + } + + if v.FirstName != nil { + firstNames[i] = v.FirstName + } else { + firstNames[i] = "" + } + + if v.Groups != nil { + groups[i] = v.Groups + } else { + groups[i] = make([]string, 0) + } + + if v.Keys != nil { + keys[i] = v.Keys + } else { + keys[i] = "" + } + + if v.LastName != nil { + lastNames[i] = v.LastName + } else { + lastNames[i] = "" + } + + userIDs[i] = v.ID + } + + d.SetId("users") + + d.Set(mkDataSourceVirtualEnvironmentUsersComments, comments) + d.Set(mkDataSourceVirtualEnvironmentUsersEmails, emails) + d.Set(mkDataSourceVirtualEnvironmentUsersEnabled, enabled) + d.Set(mkDataSourceVirtualEnvironmentUsersExpirationDates, expirationDates) + d.Set(mkDataSourceVirtualEnvironmentUsersFirstNames, firstNames) + d.Set(mkDataSourceVirtualEnvironmentUsersGroups, groups) + d.Set(mkDataSourceVirtualEnvironmentUsersKeys, keys) + d.Set(mkDataSourceVirtualEnvironmentUsersLastNames, lastNames) + d.Set(mkDataSourceVirtualEnvironmentUsersUserIDs, userIDs) + + return nil +} diff --git a/data_source_virtual_environment_users_test.go b/data_source_virtual_environment_users_test.go new file mode 100644 index 00000000..01581026 --- /dev/null +++ b/data_source_virtual_environment_users_test.go @@ -0,0 +1,45 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +package main + +import ( + "testing" +) + +// TestDataSourceVirtualEnvironmentUsersInstantiation tests whether the DataSourceVirtualEnvironmentUsers instance can be instantiated. +func TestDataSourceVirtualEnvironmentUsersInstantiation(t *testing.T) { + s := dataSourceVirtualEnvironmentUsers() + + if s == nil { + t.Fatalf("Cannot instantiate dataSourceVirtualEnvironmentUsers") + } +} + +// TestDataSourceVirtualEnvironmentUsersSchema tests the dataSourceVirtualEnvironmentUsers schema. +func TestDataSourceVirtualEnvironmentUsersSchema(t *testing.T) { + s := dataSourceVirtualEnvironmentUsers() + + attributeKeys := []string{ + mkDataSourceVirtualEnvironmentUsersComments, + mkDataSourceVirtualEnvironmentUsersEmails, + mkDataSourceVirtualEnvironmentUsersEnabled, + mkDataSourceVirtualEnvironmentUsersExpirationDates, + mkDataSourceVirtualEnvironmentUsersFirstNames, + mkDataSourceVirtualEnvironmentUsersGroups, + mkDataSourceVirtualEnvironmentUsersKeys, + mkDataSourceVirtualEnvironmentUsersLastNames, + mkDataSourceVirtualEnvironmentUsersUserIDs, + } + + for _, v := range attributeKeys { + if s.Schema[v] == nil { + t.Fatalf("Error in dataSourceVirtualEnvironmentUsers.Schema: Missing attribute \"%s\"", v) + } + + if s.Schema[v].Computed != true { + t.Fatalf("Error in dataSourceVirtualEnvironmentUsers.Schema: Attribute \"%s\" is not computed", v) + } + } +} diff --git a/example/data_source_virtual_environment_user.tf b/example/data_source_virtual_environment_user.tf new file mode 100644 index 00000000..9df34935 --- /dev/null +++ b/example/data_source_virtual_environment_user.tf @@ -0,0 +1,39 @@ +data "proxmox_virtual_environment_user" "example" { + user_id = "root@pam" +} + +output "data_proxmox_virtual_environment_user_example_comment" { + value = "${data.proxmox_virtual_environment_user.example.comment}" +} + +output "data_proxmox_virtual_environment_user_example_email" { + value = "${data.proxmox_virtual_environment_user.example.email}" +} + +output "data_proxmox_virtual_environment_user_example_enabled" { + value = "${data.proxmox_virtual_environment_user.example.enabled}" +} + +output "data_proxmox_virtual_environment_user_example_expiration_date" { + value = "${data.proxmox_virtual_environment_user.example.expiration_date}" +} + +output "data_proxmox_virtual_environment_user_example_first_name" { + value = "${data.proxmox_virtual_environment_user.example.first_name}" +} + +output "data_proxmox_virtual_environment_user_example_groups" { + value = "${data.proxmox_virtual_environment_user.example.groups}" +} + +output "data_proxmox_virtual_environment_user_example_keys" { + value = "${data.proxmox_virtual_environment_user.example.keys}" +} + +output "data_proxmox_virtual_environment_user_example_last_name" { + value = "${data.proxmox_virtual_environment_user.example.last_name}" +} + +output "data_proxmox_virtual_environment_user_example_user_id" { + value = "${data.proxmox_virtual_environment_user.example.id}" +} diff --git a/example/data_source_virtual_environment_users.tf b/example/data_source_virtual_environment_users.tf new file mode 100644 index 00000000..7adf7e77 --- /dev/null +++ b/example/data_source_virtual_environment_users.tf @@ -0,0 +1,39 @@ +data "proxmox_virtual_environment_users" "example" { + depends_on = ["proxmox_virtual_environment_role.example"] +} + +output "data_proxmox_virtual_environment_users_example_comments" { + value = "${data.proxmox_virtual_environment_users.example.comments}" +} + +output "data_proxmox_virtual_environment_users_example_emails" { + value = "${data.proxmox_virtual_environment_users.example.emails}" +} + +output "data_proxmox_virtual_environment_users_example_enabled" { + value = "${data.proxmox_virtual_environment_users.example.enabled}" +} + +output "data_proxmox_virtual_environment_users_example_expiration_dates" { + value = "${data.proxmox_virtual_environment_users.example.expiration_dates}" +} + +output "data_proxmox_virtual_environment_users_example_first_names" { + value = "${data.proxmox_virtual_environment_users.example.first_names}" +} + +output "data_proxmox_virtual_environment_users_example_groups" { + value = "${data.proxmox_virtual_environment_users.example.groups}" +} + +output "data_proxmox_virtual_environment_users_example_keys" { + value = "${data.proxmox_virtual_environment_users.example.keys}" +} + +output "data_proxmox_virtual_environment_users_example_last_names" { + value = "${data.proxmox_virtual_environment_users.example.last_names}" +} + +output "data_proxmox_virtual_environment_users_example_user_ids" { + value = "${data.proxmox_virtual_environment_users.example.user_ids}" +} diff --git a/provider.go b/provider.go index 001b3078..70489b22 100644 --- a/provider.go +++ b/provider.go @@ -32,6 +32,8 @@ func Provider() *schema.Provider { "proxmox_virtual_environment_groups": dataSourceVirtualEnvironmentGroups(), "proxmox_virtual_environment_role": dataSourceVirtualEnvironmentRole(), "proxmox_virtual_environment_roles": dataSourceVirtualEnvironmentRoles(), + "proxmox_virtual_environment_user": dataSourceVirtualEnvironmentUser(), + "proxmox_virtual_environment_users": dataSourceVirtualEnvironmentUsers(), "proxmox_virtual_environment_version": dataSourceVirtualEnvironmentVersion(), }, ResourcesMap: map[string]*schema.Resource{ diff --git a/proxmox/common_types.go b/proxmox/common_types.go index c809acb9..58c155b0 100644 --- a/proxmox/common_types.go +++ b/proxmox/common_types.go @@ -7,7 +7,9 @@ package proxmox import ( "bytes" "encoding/json" + "strconv" "strings" + "time" ) // CustomBool allows a JSON boolean value to also be an integer. @@ -16,6 +18,9 @@ type CustomBool bool // CustomPrivileges allows a JSON object of privileges to also be a string array. type CustomPrivileges []string +// CustomTimestamp allows a JSON boolean value to also be a unix timestamp. +type CustomTimestamp time.Time + // MarshalJSON converts a boolean to a JSON value. func (r CustomBool) MarshalJSON() ([]byte, error) { buffer := new(bytes.Buffer) @@ -79,3 +84,27 @@ func (r *CustomPrivileges) UnmarshalJSON(b []byte) error { return nil } + +// MarshalJSON converts a boolean to a JSON value. +func (r CustomTimestamp) MarshalJSON() ([]byte, error) { + var timestamp time.Time + + timestamp = time.Time(r) + buffer := bytes.NewBufferString(strconv.FormatInt(timestamp.Unix(), 10)) + + return buffer.Bytes(), nil +} + +// UnmarshalJSON converts a JSON value to a boolean. +func (r *CustomTimestamp) UnmarshalJSON(b []byte) error { + s := string(b) + i, err := strconv.ParseInt(s, 10, 64) + + if err != nil { + return err + } + + *r = CustomTimestamp(time.Unix(i, 0)) + + return nil +} diff --git a/proxmox/virtual_environment_users.go b/proxmox/virtual_environment_users.go new file mode 100644 index 00000000..bea1dbe0 --- /dev/null +++ b/proxmox/virtual_environment_users.go @@ -0,0 +1,125 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +package proxmox + +import ( + "errors" + "fmt" + "net/url" + "sort" +) + +// VirtualEnvironmentUserCreateRequestBody contains the data for an user create request. +type VirtualEnvironmentUserCreateRequestBody struct { + Comment *string `json:"comment,omitempty"` + Email *string `json:"email,omitempty"` + Enabled *CustomBool `json:"enable,omitempty"` + ExpirationDate *CustomTimestamp `json:"expire,omitempty"` + FirstName *string `json:"firstname,omitempty"` + Groups *[]string `json:"groups,omitempty"` + ID string `json:"userid"` + Keys *string `json:"keys,omitempty"` + LastName *string `json:"lastname,omitempty"` + Password string `json:"password"` +} + +// VirtualEnvironmentUserGetResponseBody contains the body from an user get response. +type VirtualEnvironmentUserGetResponseBody struct { + Data *VirtualEnvironmentUserGetResponseData `json:"data,omitempty"` +} + +// VirtualEnvironmentUserGetResponseData contains the data from an user get response. +type VirtualEnvironmentUserGetResponseData struct { + Comment *string `json:"comment,omitempty"` + Email *string `json:"email,omitempty"` + Enabled *CustomBool `json:"enable,omitempty"` + ExpirationDate *CustomTimestamp `json:"expire,omitempty"` + FirstName *string `json:"firstname,omitempty"` + Groups *[]string `json:"groups,omitempty"` + Keys *string `json:"keys,omitempty"` + LastName *string `json:"lastname,omitempty"` +} + +// VirtualEnvironmentUserListResponseBody contains the body from an user list response. +type VirtualEnvironmentUserListResponseBody struct { + Data []*VirtualEnvironmentUserListResponseData `json:"data,omitempty"` +} + +// VirtualEnvironmentUserListResponseData contains the data from an user list response. +type VirtualEnvironmentUserListResponseData struct { + Comment *string `json:"comment,omitempty"` + Email *string `json:"email,omitempty"` + Enabled *CustomBool `json:"enable,omitempty"` + ExpirationDate *CustomTimestamp `json:"expire,omitempty"` + FirstName *string `json:"firstname,omitempty"` + Groups *[]string `json:"groups,omitempty"` + ID string `json:"userid"` + Keys *string `json:"keys,omitempty"` + LastName *string `json:"lastname,omitempty"` +} + +// VirtualEnvironmentUserUpdateRequestBody contains the data for an user update request. +type VirtualEnvironmentUserUpdateRequestBody struct { + Append *CustomBool `json:"append,omitempty"` + Comment *string `json:"comment,omitempty"` + Email *string `json:"email,omitempty"` + Enabled *CustomBool `json:"enable,omitempty"` + ExpirationDate *CustomTimestamp `json:"expire,omitempty"` + FirstName *string `json:"firstname,omitempty"` + Groups *[]string `json:"groups,omitempty"` + Keys *string `json:"keys,omitempty"` + LastName *string `json:"lastname,omitempty"` +} + +// CreateUser creates an user. +func (c *VirtualEnvironmentClient) CreateUser(d *VirtualEnvironmentUserCreateRequestBody) error { + return c.DoRequest(hmPOST, "access/users", d, nil) +} + +// DeleteUser deletes an user. +func (c *VirtualEnvironmentClient) DeleteUser(id string) error { + return c.DoRequest(hmDELETE, fmt.Sprintf("access/users/%s", id), nil, nil) +} + +// GetUser retrieves an user. +func (c *VirtualEnvironmentClient) GetUser(id string) (*VirtualEnvironmentUserGetResponseData, error) { + resBody := &VirtualEnvironmentUserGetResponseBody{} + err := c.DoRequest(hmGET, fmt.Sprintf("access/users/%s", url.PathEscape(id)), nil, resBody) + + if err != nil { + return nil, err + } + + if resBody.Data == nil { + return nil, errors.New("The server did not include a data object in the response") + } + + return resBody.Data, nil +} + +// ListUsers retrieves a list of users. +func (c *VirtualEnvironmentClient) ListUsers() ([]*VirtualEnvironmentUserListResponseData, error) { + resBody := &VirtualEnvironmentUserListResponseBody{} + err := c.DoRequest(hmGET, "access/users", nil, resBody) + + if err != nil { + return nil, err + } + + if resBody.Data == nil { + return nil, errors.New("The server did not include a data object in the response") + } + + sort.Slice(resBody.Data, func(i, j int) bool { + return resBody.Data[i].ID < resBody.Data[j].ID + }) + + return resBody.Data, nil +} + +// UpdateUser updates an user. +func (c *VirtualEnvironmentClient) UpdateUser(id string, d *VirtualEnvironmentUserUpdateRequestBody) error { + return c.DoRequest(hmPUT, fmt.Sprintf("access/users/%s", id), d, nil) +}