Skip to content

Commit

Permalink
Merge pull request #415 from deploymenttheory/update-app-catalog-app-…
Browse files Browse the repository at this point in the history
…installer-titles

removed managed software updates from provider
  • Loading branch information
ShocOne authored Sep 17, 2024
2 parents 4402fc5 + 0928ccc commit d70a590
Show file tree
Hide file tree
Showing 8 changed files with 238 additions and 112 deletions.
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ go 1.22.4
require (
github.com/deploymenttheory/go-api-http-client v0.2.12
github.com/deploymenttheory/go-api-http-client-integrations v0.0.11
github.com/deploymenttheory/go-api-sdk-jamfpro v1.11.2
github.com/deploymenttheory/go-api-sdk-jamfpro v1.11.3

)

Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,8 @@ github.com/deploymenttheory/go-api-http-client v0.2.12 h1:ZPnxbF9/S3EBTx8aFzRcof
github.com/deploymenttheory/go-api-http-client v0.2.12/go.mod h1:LKDnBcieS6CyikZjTKPpziVdxnTwzBHE6Hx1cuWRcuU=
github.com/deploymenttheory/go-api-http-client-integrations v0.0.11 h1:1jRrAeD6iGXw7DDccoYTre0XS9bVbCAk3lmFCO43Z28=
github.com/deploymenttheory/go-api-http-client-integrations v0.0.11/go.mod h1:FQPNu+QaAyq9XWSjItJo82ABvkiGwdOlt73Qm6vp3MU=
github.com/deploymenttheory/go-api-sdk-jamfpro v1.11.2 h1:ByesWMSSPXffJEpoqK9cKLlsIj0fvfnC+7sfPv6fd5o=
github.com/deploymenttheory/go-api-sdk-jamfpro v1.11.2/go.mod h1:O/OX63ngU0NrEpPw6cZdMQL3eODLjJrEG4BlN/BoOUI=
github.com/deploymenttheory/go-api-sdk-jamfpro v1.11.3 h1:jlSSYT8b1le1oUh6JBaEg4Ft7JNq1eW4G0xFxPp7tAM=
github.com/deploymenttheory/go-api-sdk-jamfpro v1.11.3/go.mod h1:O/OX63ngU0NrEpPw6cZdMQL3eODLjJrEG4BlN/BoOUI=
github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc=
github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
Expand Down
25 changes: 12 additions & 13 deletions internal/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ import (
"github.com/deploymenttheory/terraform-provider-jamfpro/internal/resources/filesharedistributionpoints"
"github.com/deploymenttheory/terraform-provider-jamfpro/internal/resources/macosconfigurationprofilesplist"
"github.com/deploymenttheory/terraform-provider-jamfpro/internal/resources/macosconfigurationprofilesplistgenerator"
"github.com/deploymenttheory/terraform-provider-jamfpro/internal/resources/managedsoftwareupdates"
"github.com/deploymenttheory/terraform-provider-jamfpro/internal/resources/mobiledeviceconfigurationprofilesplist"
"github.com/deploymenttheory/terraform-provider-jamfpro/internal/resources/networksegments"
"github.com/deploymenttheory/terraform-provider-jamfpro/internal/resources/packages"
Expand Down Expand Up @@ -395,18 +394,18 @@ func Provider() *schema.Provider {
"jamfpro_network_segment": networksegments.ResourceJamfProNetworkSegments(),
"jamfpro_macos_configuration_profile_plist": macosconfigurationprofilesplist.ResourceJamfProMacOSConfigurationProfilesPlist(),
"jamfpro_macos_configuration_profile_plist_generator": macosconfigurationprofilesplistgenerator.ResourceJamfProMacOSConfigurationProfilesPlistGenerator(),
"jamfpro_managed_software_update": managedsoftwareupdates.ResourceJamfProManagedSoftwareUpdate(),
"jamfpro_mobile_device_configuration_profile_plist": mobiledeviceconfigurationprofilesplist.ResourceJamfProMobileDeviceConfigurationProfilesPlist(),
"jamfpro_package": packages.ResourceJamfProPackages(),
"jamfpro_policy": policies.ResourceJamfProPolicies(),
"jamfpro_printer": printers.ResourceJamfProPrinters(),
"jamfpro_script": scripts.ResourceJamfProScripts(),
"jamfpro_site": sites.ResourceJamfProSites(),
"jamfpro_smart_computer_group": smartcomputergroups.ResourceJamfProSmartComputerGroups(),
"jamfpro_static_computer_group": staticcomputergroups.ResourceJamfProStaticComputerGroups(),
"jamfpro_restricted_software": restrictedsoftware.ResourceJamfProRestrictedSoftwares(),
"jamfpro_user_group": usergroups.ResourceJamfProUserGroups(),
"jamfpro_webhook": webhooks.ResourceJamfProWebhooks(),
//"jamfpro_managed_software_update": managedsoftwareupdates.ResourceJamfProManagedSoftwareUpdate(),
"jamfpro_mobile_device_configuration_profile_plist": mobiledeviceconfigurationprofilesplist.ResourceJamfProMobileDeviceConfigurationProfilesPlist(),
"jamfpro_package": packages.ResourceJamfProPackages(),
"jamfpro_policy": policies.ResourceJamfProPolicies(),
"jamfpro_printer": printers.ResourceJamfProPrinters(),
"jamfpro_script": scripts.ResourceJamfProScripts(),
"jamfpro_site": sites.ResourceJamfProSites(),
"jamfpro_smart_computer_group": smartcomputergroups.ResourceJamfProSmartComputerGroups(),
"jamfpro_static_computer_group": staticcomputergroups.ResourceJamfProStaticComputerGroups(),
"jamfpro_restricted_software": restrictedsoftware.ResourceJamfProRestrictedSoftwares(),
"jamfpro_user_group": usergroups.ResourceJamfProUserGroups(),
"jamfpro_webhook": webhooks.ResourceJamfProWebhooks(),
},
}

Expand Down
69 changes: 47 additions & 22 deletions internal/resources/managedsoftwareupdates/constructor.go
Original file line number Diff line number Diff line change
@@ -1,55 +1,80 @@
package managedsoftwareupdates

import (
"encoding/json"
"fmt"
"log"

"github.com/deploymenttheory/go-api-sdk-jamfpro/sdk/jamfpro"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

// construct constructs a ResourceManagedSoftwareUpdatePlan object from the provided schema data.
// construct builds a ResourceManagedSoftwareUpdatePlan object from the provided schema data.
func construct(d *schema.ResourceData) (*jamfpro.ResourceManagedSoftwareUpdatePlan, error) {
resource := &jamfpro.ResourceManagedSoftwareUpdatePlan{
Config: jamfpro.ResourcManagedSoftwareUpdatePlanConfig{
UpdateAction: d.Get("config.0.update_action").(string),
VersionType: d.Get("config.0.version_type").(string),
SpecificVersion: d.Get("config.0.specific_version").(string),
MaxDeferrals: d.Get("config.0.max_deferrals").(int),
ForceInstallLocalDateTime: d.Get("config.0.force_install_local_date_time").(string),
},
Config: jamfpro.ResourcManagedSoftwareUpdatePlanConfig{},
}

// Handle group
if v, ok := d.GetOk("group"); ok {
groups := v.([]interface{})
if len(groups) > 0 {
group := groups[0].(map[string]interface{})
groupList := v.([]interface{})
if len(groupList) > 0 {
group := groupList[0].(map[string]interface{})
resource.Group = jamfpro.ResourcManagedSoftwareUpdatePlanObject{
GroupId: group["group_id"].(string),
ObjectType: group["object_type"].(string),
}
}
}

// Optional: Add build_version if it's set
if v, ok := d.GetOk("config.0.build_version"); ok {
// Handle device
if v, ok := d.GetOk("device"); ok {
deviceList := v.([]interface{})
if len(deviceList) > 0 {
device := deviceList[0].(map[string]interface{})
resource.Devices = []jamfpro.ResourcManagedSoftwareUpdatePlanObject{
{
DeviceId: device["device_id"].(string),
ObjectType: device["object_type"].(string),
},
}
}
}

// Now handle the fields that were previously inside the config block
resource.Config.UpdateAction = d.Get("update_action").(string)
resource.Config.VersionType = d.Get("version_type").(string)

if v, ok := d.GetOk("specific_version"); ok {
resource.Config.SpecificVersion = v.(string)
} else {
resource.Config.SpecificVersion = "NO_SPECIFIC_VERSION"
}

if v, ok := d.GetOk("build_version"); ok {
resource.Config.BuildVersion = v.(string)
} else {
resource.Config.BuildVersion = ""
}

// Validate that specific_version is set when required
if resource.Config.VersionType == "SPECIFIC_VERSION" || resource.Config.VersionType == "CUSTOM_VERSION" {
if resource.Config.SpecificVersion == "" {
return nil, fmt.Errorf("specific_version is required when version_type is SPECIFIC_VERSION or CUSTOM_VERSION")
}
if v, ok := d.GetOk("max_deferrals"); ok {
resource.Config.MaxDeferrals = v.(int)
} else {
resource.Config.MaxDeferrals = 0
}

// Validate that max_deferrals is set when required
if resource.Config.UpdateAction == "DOWNLOAD_INSTALL_ALLOW_DEFERRAL" && resource.Config.MaxDeferrals == 0 {
return nil, fmt.Errorf("max_deferrals is required when update_action is DOWNLOAD_INSTALL_ALLOW_DEFERRAL")
if v, ok := d.GetOk("force_install_local_date_time"); ok {
resource.Config.ForceInstallLocalDateTime = v.(string)
} else {
resource.Config.ForceInstallLocalDateTime = ""
}

log.Printf("[DEBUG] Constructed Jamf Pro Managed Software Update Plan: %+v\n", resource)
// Debug logging for config specifically
configJSON, err := json.MarshalIndent(resource.Config, "", " ")
if err != nil {
return nil, fmt.Errorf("failed to marshal Jamf Pro managed software update config to JSON: %v", err)
}
log.Printf("[DEBUG] Constructed Jamf Pro managed software update config JSON:\n%s\n", string(configJSON))

return resource, nil
}
32 changes: 25 additions & 7 deletions internal/resources/managedsoftwareupdates/crud.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,9 @@ func create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.
client := meta.(*jamfpro.Client)
var diags diag.Diagnostics

// Lock the mutex to ensure only one create operation can run this function at a time
mu.Lock()
defer mu.Unlock()

// Check and accept the Jamf Managed Software Update terms and conditions
err := checkAndEnableManagedSoftwareUpdateFeatureToggle(ctx, client)
if err != nil {
return diag.FromErr(fmt.Errorf("failed to ensure Jamf Pro Managed Software Update toggle is enabled: %v", err))
Expand All @@ -43,29 +41,49 @@ func create(ctx context.Context, d *schema.ResourceData, meta interface{}) diag.
var creationResponse *jamfpro.ResponseManagedSoftwareUpdatePlanCreate
err = retry.RetryContext(ctx, d.Timeout(schema.TimeoutCreate), func() *retry.RetryError {
var apiErr error
creationResponse, apiErr = client.CreateManagedSoftwareUpdatePlanByGroupID(resource)
if resource.Group.GroupId != "" {
creationResponse, apiErr = client.CreateManagedSoftwareUpdatePlanByGroupID(resource)
} else {
creationResponse, apiErr = client.CreateManagedSoftwareUpdatePlanByDeviceID(resource)
}
if apiErr != nil {
return retry.RetryableError(apiErr)
}
return nil
})

if err != nil {
return diag.FromErr(fmt.Errorf("failed to create Jamf Pro Managed Software Update '%s' after retries: %v", resource.Group.GroupId, err))
return diag.FromErr(fmt.Errorf("failed to create Jamf Pro Managed Software Update after retries: %v", err))
}

d.SetId(creationResponse.Plans[0].PlanID)
if len(creationResponse.Plans) > 0 {
planUUID := creationResponse.Plans[0].PlanID
d.SetId(planUUID)
if err := d.Set("plan_uuid", planUUID); err != nil {
return diag.FromErr(fmt.Errorf("error setting planID as plan_uuid: %v", err))
}

// Set group and object_type
if resource.Group.GroupId != "" {
if err := d.Set("group_id", resource.Group.GroupId); err != nil {
return diag.FromErr(fmt.Errorf("error setting group_id: %v", err))
}
if err := d.Set("object_type", resource.Group.ObjectType); err != nil {
return diag.FromErr(fmt.Errorf("error setting object_type: %v", err))
}
}
}

return append(diags, readNoCleanup(ctx, d, meta)...)
}

// read reads and states a jamfpro managed software update plan
func read(ctx context.Context, d *schema.ResourceData, meta interface{}, cleanup bool) diag.Diagnostics {
client := meta.(*jamfpro.Client)
resourceUUID := d.Id()
var diags diag.Diagnostics
resourceUUID := d.Id()

var response *jamfpro.ResponseManagedSoftwareUpdatePlan

err := retry.RetryContext(ctx, d.Timeout(schema.TimeoutRead), func() *retry.RetryError {
var apiErr error
response, apiErr = client.GetManagedSoftwareUpdatePlanByUUID(resourceUUID)
Expand Down
64 changes: 64 additions & 0 deletions internal/resources/managedsoftwareupdates/data_validator.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package managedsoftwareupdates

import (
"context"
"fmt"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

// mainCustomDiffFunc orchestrates all custom diff validations.
func mainCustomDiffFunc(ctx context.Context, diff *schema.ResourceDiff, i interface{}) error {
if err := validateGroupOrDevice(ctx, diff, i); err != nil {
return err
}

if err := validateConfigFields(ctx, diff, i); err != nil {
return err
}

return nil
}

// validateGroupOrDevice ensures that either 'group' or 'device' is specified, but not both.
func validateGroupOrDevice(_ context.Context, diff *schema.ResourceDiff, _ interface{}) error {
resourceName := diff.Get("name").(string)
_, hasGroup := diff.GetOk("group")
_, hasDevice := diff.GetOk("device")

if hasGroup && hasDevice {
return fmt.Errorf("in 'jamfpro_managed_software_update.%s': only one of 'group' or 'device' can be specified, not both", resourceName)
}

if !hasGroup && !hasDevice {
return fmt.Errorf("in 'jamfpro_managed_software_update.%s': either 'group' or 'device' must be specified", resourceName)
}

return nil
}

// validateConfigFields performs validation on the 'config' block fields.
func validateConfigFields(_ context.Context, diff *schema.ResourceDiff, _ interface{}) error {
resourceName := diff.Get("name").(string)
config := diff.Get("config").([]interface{})

if len(config) == 0 {
return fmt.Errorf("in 'jamfpro_managed_software_update.%s': 'config' block is required", resourceName)
}

configMap := config[0].(map[string]interface{})
updateAction := configMap["update_action"].(string)
versionType := configMap["version_type"].(string)
specificVersion := configMap["specific_version"].(string)
maxDeferrals := configMap["max_deferrals"].(int)

if updateAction == "DOWNLOAD_INSTALL_ALLOW_DEFERRAL" && maxDeferrals == 0 {
return fmt.Errorf("in 'jamfpro_managed_software_update.%s': 'max_deferrals' must be set when 'update_action' is 'DOWNLOAD_INSTALL_ALLOW_DEFERRAL'", resourceName)
}

if (versionType == "SPECIFIC_VERSION" || versionType == "CUSTOM_VERSION") && specificVersion == "" {
return fmt.Errorf("in 'jamfpro_managed_software_update.%s': 'specific_version' must be set when 'version_type' is 'SPECIFIC_VERSION' or 'CUSTOM_VERSION'", resourceName)
}

return nil
}
Loading

0 comments on commit d70a590

Please sign in to comment.