Skip to content

Commit

Permalink
Feat/1.7.0 (#486)
Browse files Browse the repository at this point in the history
Co-authored-by: Pradeepsingh Bhati <[email protected]>
Co-authored-by: Abhishek <[email protected]>
Co-authored-by: Matthew Machivenyika <[email protected]>
  • Loading branch information
4 people authored Aug 12, 2022
1 parent d57a46e commit d97329a
Show file tree
Hide file tree
Showing 33 changed files with 1,001 additions and 120 deletions.
44 changes: 44 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,47 @@
## 1.7.0 (August 12, 2022)

[Full Changelog](https://github.com/nutanix/terraform-provider-nutanix/compare/v1.6.1...v1.7.0)

**New Feature:**
- Added a resource for user groups. [\#477] (https://github.com/nutanix/terraform-provider-nutanix/pull/477)

New Resource :
- nutanix_user_groups

**Merged pull request:**

- Feature user groups [\#477] (https://github.com/nutanix/terraform-provider-nutanix/pull/477) ([abhimutant](https://github.com/abhimutant))
- Fix checksum issue in image resource [\#481] (https://github.com/nutanix/terraform-provider-nutanix/pull/481) ([bhatipradeep](https://github.com/bhatipradeep))
- Fix image resource issues [\#480] (https://github.com/nutanix/terraform-provider-nutanix/pull/480) ([bhatipradeep](https://github.com/bhatipradeep))
- Add field to set time zone for cluster created using foundation [\#484] (https://github.com/nutanix/terraform-provider-nutanix/pull/484) ([bhatipradeep](https://github.com/bhatipradeep))
- fixed the issue and added testcase for sysprep custom key values guest customisation [\#478] (https://github.com/nutanix/terraform-provider-nutanix/pull/478) ([abhimutant](https://github.com/abhimutant))
- Changes in karbon cluster documentation for storage config [\#479] (https://github.com/nutanix/terraform-provider-nutanix/pull/479) ([abhimutant](https://github.com/abhimutant))
- Enable tests for protection rules based datasources and resources [\#366] (https://github.com/nutanix/terraform-provider-nutanix/pull/366) ([bhatipradeep](https://github.com/bhatipradeep))
- Add uuid to address_groups data source [\#472] (https://github.com/nutanix/terraform-provider-nutanix/pull/472) ([mcguppy](https://github.com/mcguppy))


**Fixed bugs:**

- Terraform provider crashes when using guest_customization_sysprep_custom_key_values [\#441] (https://github.com/nutanix/terraform-provider-nutanix/issues/441)
- Nutanix terraform- Karbon clusters, the storage_class_config is not been displayed. [\#417] (https://github.com/nutanix/terraform-provider-nutanix/issues/417)
- Checksum is not considered while uploading image from local using nutanix_image resource. [\#469] (https://github.com/nutanix/terraform-provider-nutanix/issues/469)
- Not able to update image_type of PC image [\#454] (https://github.com/nutanix/terraform-provider-nutanix/issues/454)
- Image gets deleted from PC if nutanix_image update errors out [\#453] (https://github.com/nutanix/terraform-provider-nutanix/issues/453)

**Closed issues:**

- Support for User Groups [\#475] (https://github.com/nutanix/terraform-provider-nutanix/issues/475)
- Resizing disk identified in plan, but not actually done during apply [\#463] (https://github.com/nutanix/terraform-provider-nutanix/issues/463)
- uuid of address_groups are not available [\#461] (https://github.com/nutanix/terraform-provider-nutanix/issues/461)
- ntx provider have ENTITY_READ_ERROR when try to recreate a VM deleted manually [\#451] (https://github.com/nutanix/terraform-provider-nutanix/issues/451)
- Allow project definiation by name and not just ID [\#406] (https://github.com/nutanix/terraform-provider-nutanix/issues/406)
- Upload images to Foundation VM from a remote server using nutanix_foundation_image resource [\#455] (https://github.com/nutanix/terraform-provider-nutanix/issues/455)
- Change catagories from list to dictionary for more straightforward use [\#407] (https://github.com/nutanix/terraform-provider-nutanix/issues/407)
- VM creation fails when boot_type = LEGACY [\#304] (https://github.com/nutanix/terraform-provider-nutanix/issues/304)
- Add attributes to set timezone during cluster creation using image_nodes [\#449] (https://github.com/nutanix/terraform-provider-nutanix/issues/449)
- Enable multi-pc tests [\#448] (https://github.com/nutanix/terraform-provider-nutanix/issues/448)


## 1.6.1 (July 7, 2022)

[Full Changelog](https://github.com/nutanix/terraform-provider-nutanix/compare/v1.5.0...v1.6.1)
Expand Down
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Terraform provider plugin to integrate with Nutanix Enterprise Cloud

NOTE: The latest version of the Nutanix provider is [v1.6.1](https://github.com/nutanix/terraform-provider-nutanix/releases/tag/v1.6.1)
NOTE: The latest version of the Nutanix provider is [v1.7.0](https://github.com/nutanix/terraform-provider-nutanix/releases/tag/v1.7.0)

Modules based on Terraform Nutanix Provider can be found here : [Modules](https://github.com/nutanix/terraform-provider-nutanix/tree/master/modules)
## Build, Quality Status
Expand Down Expand Up @@ -42,10 +42,14 @@ The Terraform Nutanix provider is designed to work with Nutanix Prism Central an
> For the 1.6.1 release of the provider it will have N-2 compatibility with the Prism Central APIs. This release was tested against Prism Central versions pc2022.4 pc2022.1.0.2 and pc2021.9.0.4.
> For the 1.7.0 release of the provider it will have N-2 compatibility with the Prism Central APIs. This release was tested against Prism Central versions pc2022.6, pc2022.4 and pc2022.1.0.2.
### note
With v1.6.1 release of flow networking feature in provider, IAMv2 setups would be mandate.
Also, there is known issue for access_control_policies resource where update would be failing. We are continuously tracking the issue internally.

with v1.7.0 release of user groups feature in provider, pc version should be minimum 2022.1 to support organisational and saml user group.

## Foundation
> For the 1.5.0-beta release of the provider it will have N-1 compatibility with the Foundation. This release was tested against Foundation versions v5.2 and v5.1.1
Expand Down Expand Up @@ -152,6 +156,7 @@ From foundation getting released in 1.5.0-beta, provider configuration will acco
* nutanix_pbr
* nutanix_static_routes
* nutanix_floating_ip
* nutanix_user_groups

## Data Sources

Expand Down
1 change: 1 addition & 0 deletions client/foundation/foundation_structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ type Clusters struct {
CvmDNSServers string `json:"cvm_dns_servers,omitempty"`
ClusterInitNow *bool `json:"cluster_init_now"`
HypervisorNtpServers string `json:"hypervisor_ntp_servers,omitempty"`
Timezone string `json:"timezone,omitempty"`
}

// EOS metadata struct used in node imaging when importing cluster config got from install.nutanix.com
Expand Down
48 changes: 46 additions & 2 deletions client/v3/v3_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ type Service interface {
GetImage(uuid string) (*ImageIntentResponse, error)
ListImage(getEntitiesRequest *DSMetadata) (*ImageListIntentResponse, error)
UpdateImage(uuid string, body *ImageIntentInput) (*ImageIntentResponse, error)
UploadImage(uuid, filepath string) error
UploadImage(uuid string, filepath string, checksum *Checksum) error
CreateOrUpdateCategoryKey(body *CategoryKey) (*CategoryKeyStatus, error)
ListCategories(getEntitiesRequest *CategoryListMetadata) (*CategoryKeyListResponse, error)
DeleteCategoryKey(name string) error
Expand Down Expand Up @@ -89,9 +89,12 @@ type Service interface {
DeleteUser(uuid string) (*DeleteResponse, error)
ListUser(getEntitiesRequest *DSMetadata) (*UserListResponse, error)
ListAllUser(filter string) (*UserListResponse, error)
CreateUserGroup(ctx context.Context, body *UserGroupIntentInput) (*UserGroupIntentResponse, error)
GetUserGroup(userUUID string) (*UserGroupIntentResponse, error)
ListUserGroup(getEntitiesRequest *DSMetadata) (*UserGroupListResponse, error)
ListAllUserGroup(filter string) (*UserGroupListResponse, error)
UpdateUserGroup(ctx context.Context, uuid string, body *UserGroupIntentInput) (*UserGroupIntentResponse, error)
DeleteUserGroup(ctx context.Context, uuid string) (*DeleteResponse, error)
GetPermission(permissionUUID string) (*PermissionIntentResponse, error)
ListPermission(getEntitiesRequest *DSMetadata) (*PermissionListResponse, error)
ListAllPermission(filter string) (*PermissionListResponse, error)
Expand Down Expand Up @@ -375,7 +378,7 @@ func (op Operations) CreateImage(body *ImageIntentInput) (*ImageIntentResponse,
*
* @param uuid @param filepath
*/
func (op Operations) UploadImage(uuid, filepath string) error {
func (op Operations) UploadImage(uuid, filepath string, checksum *Checksum) error {
ctx := context.Background()

path := fmt.Sprintf("/images/%s/file", uuid)
Expand All @@ -392,6 +395,11 @@ func (op Operations) UploadImage(uuid, filepath string) error {
return fmt.Errorf("error: Creating request %s", err)
}

if checksum != nil && *checksum != (Checksum{}) {
req.Header.Add("X-Nutanix-Checksum-Type", *checksum.ChecksumAlgorithm)
req.Header.Add("X-Nutanix-Checksum-Bytes", *checksum.ChecksumValue)
}

err = op.client.Do(ctx, req, nil)

return err
Expand Down Expand Up @@ -1857,6 +1865,17 @@ func (op Operations) GetUserGroup(userGroupUUID string) (*UserGroupIntentRespons
return User, op.client.Do(ctx, req, User)
}

func (op Operations) CreateUserGroup(ctx context.Context, body *UserGroupIntentInput) (*UserGroupIntentResponse, error) {
req, err := op.client.NewRequest(ctx, http.MethodPost, "/user_groups", body)
userGroupResponse := new(UserGroupIntentResponse)

if err != nil {
return nil, err
}

return userGroupResponse, op.client.Do(ctx, req, userGroupResponse)
}

/*ListUserGroup gets a list of UserGroups.
*
* @param metadata allows create filters to get specific data - *DSMetadata.
Expand All @@ -1876,6 +1895,31 @@ func (op Operations) ListUserGroup(getEntitiesRequest *DSMetadata) (*UserGroupLi
return UserGroupList, op.client.Do(ctx, req, UserGroupList)
}

func (op Operations) UpdateUserGroup(ctx context.Context, uuid string, body *UserGroupIntentInput) (*UserGroupIntentResponse, error) {
path := fmt.Sprintf("/user_groups/%s", uuid)
req, err := op.client.NewRequest(ctx, http.MethodPut, path, body)
userGroupResponse := new(UserGroupIntentResponse)

if err != nil {
return nil, err
}

return userGroupResponse, op.client.Do(ctx, req, userGroupResponse)
}

func (op Operations) DeleteUserGroup(ctx context.Context, uuid string) (*DeleteResponse, error) {
path := fmt.Sprintf("/user_groups/%s", uuid)

req, err := op.client.NewRequest(ctx, http.MethodDelete, path, nil)
deleteResponse := new(DeleteResponse)

if err != nil {
return nil, err
}

return deleteResponse, op.client.Do(ctx, req, deleteResponse)
}

// ListAllUserGroup ...
func (op Operations) ListAllUserGroup(filter string) (*UserGroupListResponse, error) {
entities := make([]*UserGroupIntentResponse, 0)
Expand Down
4 changes: 2 additions & 2 deletions client/v3/v3_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -987,7 +987,7 @@ func TestOperations_UploadImageError(t *testing.T) {
op := Operations{
client: tt.fields.client,
}
if err := op.UploadImage(tt.args.UUID, tt.args.filepath); (err != nil) != tt.wantErr {
if err := op.UploadImage(tt.args.UUID, tt.args.filepath, nil); (err != nil) != tt.wantErr {
t.Errorf("Operations.UploadImage() error = %v, wantErr %v", err, tt.wantErr)
}
})
Expand Down Expand Up @@ -1037,7 +1037,7 @@ func TestOperations_UploadImage(t *testing.T) {
op := Operations{
client: tt.fields.client,
}
if err := op.UploadImage(tt.args.UUID, tt.args.filepath); err != nil {
if err := op.UploadImage(tt.args.UUID, tt.args.filepath, nil); err != nil {
t.Errorf("Operations.UploadImage() error = %v", err)
}
})
Expand Down
21 changes: 17 additions & 4 deletions client/v3/v3_structs.go
Original file line number Diff line number Diff line change
Expand Up @@ -1681,7 +1681,6 @@ type Metadata struct {
//CategoriesMapping map[string][]string `json:"categories_mapping,omitempty" mapstructure:"categories_mapping,omitempty"`
//EntityVersion *string `json:"entity_version,omitempty" mapstructure:"entity_version,omitempty"`
//UseCategoriesMapping *bool `json:"use_categories_mapping,omitempty" mapstructure:"use_categories_mapping,omitempty"`

}

// NetworkSecurityRuleIntentInput An intentful representation of a network_security_rule
Expand Down Expand Up @@ -2255,20 +2254,33 @@ type UserGroupSpec struct {
Resources *UserGroupResources `json:"resources,omitempty"` // User Group Resource Definition
}

type SamlUserGroup struct {
IdpUUID *string `json:"idpUuid,omitempty"`
Name *string `json:"name,omitempty"`
}

// User Group Resource Definition
type UserGroupResources struct {
AccessControlPolicyReferenceList []*Reference `json:"access_control_policy_reference_list,omitempty"` // List of ACP references.
DirectoryServiceUserGroup *DirectoryServiceUserGroup `json:"directory_service_user_group,omitempty"` // A Directory Service user group.
DisplayName *string `json:"display_name,omitempty"` // The display name for the user group.
ProjectsReferenceList []*Reference `json:"projects_reference_list,omitempty"` // A list of projects the user group is part of.
UserGroupType *string `json:"user_group_type,omitempty"`
DirectoryServiceOU *DirectoryServiceUserGroup `json:"directory_service_ou,omitempty"`
SamlUserGroup *SamlUserGroup `json:"saml_user_group,omitempty"`
}

// User group status definition.
type UserGroupStatus struct {
MessageList []MessageResource `json:"message_list,omitempty"`
Resources *UserGroupResources `json:"resources,omitempty"` // User Group Resource Definition.
State *string `json:"state,omitempty"` // The state of the entity.
MessageList []MessageResource `json:"message_list,omitempty"`
Resources *UserGroupResources `json:"resources,omitempty"` // User Group Resource Definition.
State *string `json:"state,omitempty"` // The state of the entity.
ExecutionContext *ExecutionContext `json:"execution_context,omitempty"`
}

type UserGroupIntentInput struct {
Metadata *Metadata `json:"metadata,omitempty"`
Spec *UserGroupSpec `json:"spec,omitempty"`
}

// A Directory Service user group.
Expand Down Expand Up @@ -2601,6 +2613,7 @@ type AddressGroupResponse struct {
}

type AddressGroupListEntry struct {
UUID *string `json:"uuid,omitempty"`
AddressGroup *AddressGroupInput `json:"address_group,omitempty"`
AssociatedPoliciesList []*ReferenceValues `json:"associated_policies_list,omitempty"`
}
Expand Down
41 changes: 41 additions & 0 deletions examples/user_groups/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
terraform{
required_providers {
nutanix = {
source = "nutanix/nutanix"
version = "1.7.0"
}
}
}

#definig nutanix configuration
provider "nutanix"{
username = var.nutanix_username
password = var.nutanix_password
endpoint = var.nutanix_endpoint
port = 9440
insecure = true
}

# Add a User group to the system.

# Add Directory Service user group.
resource "nutanix_user_groups" "t1" {
directory_service_user_group{
distinguished_name = "<distinguished name of the user group>"
}
}

# Add Directory Service organizational unit.
resource "nutanix_user_groups" "t1" {
directory_service_ou{
distinguished_name = "<distinguished name of the organizational group>"
}
}

# Add SAML Service user group.
resource "nutanix_user_groups" "t1" {
saml_user_group{
name = "<group name>"
idp_uuid = "<idp uuid of user group>"
}
}
5 changes: 5 additions & 0 deletions examples/user_groups/terraform.tfvars
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#define values to the variables to be used in terraform file
nutanix_username = "admin"
nutanix_password = "password"
nutanix_endpoint = "10.xx.xx.xx"
nutanix_port = 9440
13 changes: 13 additions & 0 deletions examples/user_groups/variables.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#define the type of variables to be used in terraform file
variable "nutanix_username" {
type = string
}
variable "nutanix_password" {
type = string
}
variable "nutanix_endpoint" {
type = string
}
variable "nutanix_port" {
type = string
}
15 changes: 10 additions & 5 deletions nutanix/data_source_nutanix_address_groups.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,31 +58,35 @@ func dataSourceNutanixAddressGroups() *schema.Resource {
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"uuid": {
Type: schema.TypeString,
Computed: true,
},
"address_group": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"name": {
Type: schema.TypeString,
Required: true,
Computed: true,
},
"description": {
Type: schema.TypeString,
Optional: true,
Computed: true,
},
"ip_address_block_list": {
Type: schema.TypeList,
Required: true,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"ip": {
Type: schema.TypeString,
Required: true,
Computed: true,
},
"prefix_length": {
Type: schema.TypeInt,
Required: true,
Computed: true,
},
},
},
Expand Down Expand Up @@ -158,6 +162,7 @@ func flattenAddressGroup(entries []*v3.AddressGroupListEntry) interface{} {
},
},
"associated_policies_list": flattenReferenceList(entry.AssociatedPoliciesList),
"uuid": entry.UUID,
}
}
return entities
Expand Down
10 changes: 10 additions & 0 deletions nutanix/data_source_nutanix_image.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,16 @@ func dataSourceNutanixImageRead(ctx context.Context, d *schema.ResourceData, met
return diag.FromErr(err)
}

checksum := make(map[string]string)
if resp.Status.Resources.Checksum != nil {
checksum["checksum_algorithm"] = utils.StringValue(resp.Status.Resources.Checksum.ChecksumAlgorithm)
checksum["checksum_value"] = utils.StringValue(resp.Status.Resources.Checksum.ChecksumValue)
}

if err := d.Set("checksum", checksum); err != nil {
return diag.FromErr(err)
}

d.SetId(utils.StringValue(resp.Metadata.UUID))

return nil
Expand Down
Loading

0 comments on commit d97329a

Please sign in to comment.