diff --git a/README.md b/README.md index dad7eee63..55b3df27e 100644 --- a/README.md +++ b/README.md @@ -710,11 +710,47 @@ This documentation provides details on the API endpoints available for managing - [x] ✅ **DELETE** `/JSSResource/ebooks/name/{name}` `DeleteEbookByName` deletes an ebook by its name. +### Jamf Pro Classic API - VPP Mac Applications + +This documentation outlines the API endpoints available for managing VPP Mac applications within Jamf Pro using the Classic API, which supports XML data structures. + +## Endpoints + +- [x] ✅ **GET** `/JSSResource/macapplications` + `GetMacApplications` retrieves a serialized list of all VPP Mac applications. + +- [x] ✅ **GET** `/JSSResource/macapplications/id/{id}` + `GetMacApplicationByID` fetches a single Mac application by its ID. + +- [x] ✅ **GET** `/JSSResource/macapplications/name/{name}` + `GetMacApplicationByName` retrieves a Mac application by its name. + +- [x] ✅ **GET** `/JSSResource/macapplications/name/{name}/subset/{subset}` + `GetMacApplicationByNameAndDataSubset` retrieves a specific subset (General, Scope, SelfService, VPPCodes, and VPP) of a Mac application by its name. + +- [x] ✅ **GET** `/JSSResource/macapplications/id/{id}/subset/{subset}` + `GetMacApplicationByIDAndDataSubset` retrieves a specific subset (General, Scope, SelfService, VPPCodes, and VPP) of a Mac application by its ID. + +- [x] ✅ **POST** `/JSSResource/macapplications/id/0` + `CreateMacApplication` creates a new Mac application with the provided details. The ID `0` in the endpoint indicates creation. + +- [x] ✅ **PUT** `/JSSResource/macapplications/id/{id}` + `UpdateMacApplicationByID` updates an existing Mac application by its ID. + +- [x] ✅ **PUT** `/JSSResource/macapplications/name/{name}` + `UpdateMacApplicationByName` updates an existing Mac application by its name. + +- [x] ✅ **DELETE** `/JSSResource/macapplications/id/{id}` + `DeleteMacApplicationByID` deletes a Mac application by its ID. + +- [x] ✅ **DELETE** `/JSSResource/macapplications/name/{name}` + `DeleteMacApplicationByName` deletes a Mac application by its name. + ## Progress Summary -- Total Endpoints: 244 -- Covered: 225 +- Total Endpoints: 254 +- Covered: 235 - Not Covered: 19 - Partially Covered: 0 diff --git a/examples/mac_applications/CreateMacApplication/CreateMacApplication.go b/examples/mac_applications/CreateMacApplication/CreateMacApplication.go new file mode 100644 index 000000000..9fb714bba --- /dev/null +++ b/examples/mac_applications/CreateMacApplication/CreateMacApplication.go @@ -0,0 +1,85 @@ +package main + +import ( + "encoding/xml" + "fmt" + "log" + + "github.com/deploymenttheory/go-api-sdk-jamfpro/sdk/http_client" // Import http_client for logging + "github.com/deploymenttheory/go-api-sdk-jamfpro/sdk/jamfpro" +) + +func main() { + // Define the path to the JSON configuration file + configFilePath := "/Users/dafyddwatkins/GitHub/deploymenttheory/go-api-sdk-jamfpro/clientauth.json" + + // Load the client OAuth credentials from the configuration file + authConfig, err := jamfpro.LoadClientAuthConfig(configFilePath) + if err != nil { + log.Fatalf("Failed to load client OAuth configuration: %v", err) + } + + // Instantiate the default logger and set the desired log level + logger := http_client.NewDefaultLogger() + logLevel := http_client.LogLevelDebug // LogLevelNone // LogLevelWarning // LogLevelInfo // LogLevelDebug + + // Configuration for the jamfpro + config := jamfpro.Config{ + InstanceName: authConfig.InstanceName, + LogLevel: logLevel, + Logger: logger, + ClientID: authConfig.ClientID, + ClientSecret: authConfig.ClientSecret, + } + + // Create a new jamfpro client instance + client, err := jamfpro.NewClient(config) + if err != nil { + log.Fatalf("Failed to create Jamf Pro client: %v", err) + } + + // Define a new Mac Application + newMacApp := jamfpro.ResponseMacApplications{ + General: jamfpro.MacAppDataSubsetGeneral{ + Name: "TextWrangler.app", + Version: "5.5.2", + IsFree: true, + BundleID: "com.barebones.textwrangler", + URL: "https://itunes.apple.com/us/app/textwrangler/id404010395?mt=12&uo=4", + Category: jamfpro.MacAppCategory{ID: -1, Name: "Unknown"}, + Site: jamfpro.MacAppSite{ID: -1, Name: "None"}, + }, + Scope: jamfpro.MacAppDataSubsetScope{ + AllComputers: false, + AllJSSUsers: false, + }, + SelfService: jamfpro.MacAppDataSubsetSelfService{ + InstallButtonText: "Install", + SelfServiceDescription: "Installs the TextWrangler application", + ForceUsersToViewDescription: true, + SelfServiceIcon: jamfpro.MacAppSelfServiceIcon{}, + FeatureOnMainPage: true, + SelfServiceCategories: []jamfpro.MacAppSelfServiceCategory{}, + Notification: "string", + NotificationSubject: "TextWrangler is Available to Install", + NotificationMessage: "You can install TextWrangler by clicking this link or going to Self Service", + VPP: jamfpro.MacAppVPP{ + AssignVPPDeviceBasedLicenses: false, + VPPAdminAccountID: -1, + }, + }, + } + + // Call CreateMacApplication + createdMacApp, err := client.CreateMacApplication(newMacApp) + if err != nil { + log.Fatalf("Error creating Mac Application: %v", err) + } + + // Pretty print the created Mac Application in XML + macAppXML, err := xml.MarshalIndent(createdMacApp, "", " ") // Indent with 4 spaces + if err != nil { + log.Fatalf("Error marshaling Mac Application data: %v", err) + } + fmt.Println("Created Mac Application:\n", string(macAppXML)) +} diff --git a/examples/mac_applications/DeleteMacApplicationByID/DeleteMacApplicationByID.go b/examples/mac_applications/DeleteMacApplicationByID/DeleteMacApplicationByID.go new file mode 100644 index 000000000..5917cdd52 --- /dev/null +++ b/examples/mac_applications/DeleteMacApplicationByID/DeleteMacApplicationByID.go @@ -0,0 +1,50 @@ +package main + +import ( + "fmt" + "log" + + "github.com/deploymenttheory/go-api-sdk-jamfpro/sdk/http_client" // Import http_client for logging + "github.com/deploymenttheory/go-api-sdk-jamfpro/sdk/jamfpro" +) + +func main() { + // Define the path to the JSON configuration file + configFilePath := "/Users/dafyddwatkins/GitHub/deploymenttheory/go-api-sdk-jamfpro/clientauth.json" + + // Load the client OAuth credentials from the configuration file + authConfig, err := jamfpro.LoadClientAuthConfig(configFilePath) + if err != nil { + log.Fatalf("Failed to load client OAuth configuration: %v", err) + } + + // Instantiate the default logger and set the desired log level + logger := http_client.NewDefaultLogger() + logLevel := http_client.LogLevelDebug // LogLevelNone // LogLevelWarning // LogLevelInfo // LogLevelDebug + + // Configuration for the jamfpro + config := jamfpro.Config{ + InstanceName: authConfig.InstanceName, + LogLevel: logLevel, + Logger: logger, + ClientID: authConfig.ClientID, + ClientSecret: authConfig.ClientSecret, + } + + // Create a new jamfpro client instance + client, err := jamfpro.NewClient(config) + if err != nil { + log.Fatalf("Failed to create Jamf Pro client: %v", err) + } + + // Define the ID of the VPP mac application you want to delete + profileID := 1 + + // Call the DeleteMacOSConfigurationProfileByID function + err = client.DeleteMacApplicationByID(profileID) + if err != nil { + log.Fatalf("Failed to delete VPP mac application with ID %d: %v", profileID, err) + } + + fmt.Printf("VPP mac application with ID %d deleted successfully\n", profileID) +} diff --git a/examples/mac_applications/DeleteMacApplicationByName/DeleteMacApplicationByName.go b/examples/mac_applications/DeleteMacApplicationByName/DeleteMacApplicationByName.go new file mode 100644 index 000000000..cae601521 --- /dev/null +++ b/examples/mac_applications/DeleteMacApplicationByName/DeleteMacApplicationByName.go @@ -0,0 +1,50 @@ +package main + +import ( + "fmt" + "log" + + "github.com/deploymenttheory/go-api-sdk-jamfpro/sdk/http_client" // Import http_client for logging + "github.com/deploymenttheory/go-api-sdk-jamfpro/sdk/jamfpro" +) + +func main() { + // Define the path to the JSON configuration file + configFilePath := "/Users/dafyddwatkins/GitHub/deploymenttheory/go-api-sdk-jamfpro/clientauth.json" + + // Load the client OAuth credentials from the configuration file + authConfig, err := jamfpro.LoadClientAuthConfig(configFilePath) + if err != nil { + log.Fatalf("Failed to load client OAuth configuration: %v", err) + } + + // Instantiate the default logger and set the desired log level + logger := http_client.NewDefaultLogger() + logLevel := http_client.LogLevelDebug // LogLevelNone // LogLevelWarning // LogLevelInfo // LogLevelDebug + + // Configuration for the jamfpro + config := jamfpro.Config{ + InstanceName: authConfig.InstanceName, + LogLevel: logLevel, + Logger: logger, + ClientID: authConfig.ClientID, + ClientSecret: authConfig.ClientSecret, + } + + // Create a new jamfpro client instance + client, err := jamfpro.NewClient(config) + if err != nil { + log.Fatalf("Failed to create Jamf Pro client: %v", err) + } + + // Define the name of the macOS Configuration Profile you want to delete + VPPMacApplicationName := "TextWrangler.app" + + // Call the DeleteMacApplicationByName function + err = client.DeleteMacApplicationByName(VPPMacApplicationName) + if err != nil { + log.Fatalf("Failed to delete VPP Mac Application with name '%s': %v", VPPMacApplicationName, err) + } + + fmt.Printf("VPP Mac Application with name '%s' deleted successfully\n", VPPMacApplicationName) +} diff --git a/examples/mac_applications/GetMacApplicationByID/GetMacApplicationByID.go b/examples/mac_applications/GetMacApplicationByID/GetMacApplicationByID.go new file mode 100644 index 000000000..3e8e5d2be --- /dev/null +++ b/examples/mac_applications/GetMacApplicationByID/GetMacApplicationByID.go @@ -0,0 +1,53 @@ +package main + +import ( + "encoding/xml" + "fmt" + "log" + + "github.com/deploymenttheory/go-api-sdk-jamfpro/sdk/http_client" // Import http_client for logging + "github.com/deploymenttheory/go-api-sdk-jamfpro/sdk/jamfpro" +) + +func main() { + // Define the path to the JSON configuration file + configFilePath := "/Users/dafyddwatkins/GitHub/deploymenttheory/go-api-sdk-jamfpro/clientauth.json" + + // Load the client OAuth credentials from the configuration file + authConfig, err := jamfpro.LoadClientAuthConfig(configFilePath) + if err != nil { + log.Fatalf("Failed to load client OAuth configuration: %v", err) + } + + // Instantiate the default logger and set the desired log level + logger := http_client.NewDefaultLogger() + logLevel := http_client.LogLevelDebug // LogLevelNone // LogLevelWarning // LogLevelInfo // LogLevelDebug + + // Configuration for the jamfpro + config := jamfpro.Config{ + InstanceName: authConfig.InstanceName, + LogLevel: logLevel, + Logger: logger, + ClientID: authConfig.ClientID, + ClientSecret: authConfig.ClientSecret, + } + + // Create a new jamfpro client instance + client, err := jamfpro.NewClient(config) + if err != nil { + log.Fatalf("Failed to create Jamf Pro client: %v", err) + } + + id := 1 // Replace with your Mac application ID + macApp, err := client.GetMacApplicationByID(id) + if err != nil { + log.Fatalf("Error fetching Mac Application by ID: %v", err) + } + + // Pretty print the profile in XML + profileXML, err := xml.MarshalIndent(macApp, "", " ") // Indent with 4 spaces + if err != nil { + log.Fatalf("Error marshaling VPP mac Application data: %v", err) + } + fmt.Println("Fetched VPP mac Application:\n", string(profileXML)) +} diff --git a/examples/mac_applications/GetMacApplicationByIDAndDataSubset/GetMacApplicationByIDAndDataSubset.go b/examples/mac_applications/GetMacApplicationByIDAndDataSubset/GetMacApplicationByIDAndDataSubset.go new file mode 100644 index 000000000..1930ab001 --- /dev/null +++ b/examples/mac_applications/GetMacApplicationByIDAndDataSubset/GetMacApplicationByIDAndDataSubset.go @@ -0,0 +1,57 @@ +package main + +import ( + "encoding/xml" + "fmt" + "log" + + "github.com/deploymenttheory/go-api-sdk-jamfpro/sdk/http_client" // Import http_client for logging + "github.com/deploymenttheory/go-api-sdk-jamfpro/sdk/jamfpro" +) + +func main() { + // Define the path to the JSON configuration file + configFilePath := "/Users/dafyddwatkins/GitHub/deploymenttheory/go-api-sdk-jamfpro/clientauth.json" + + // Load the client OAuth credentials from the configuration file + authConfig, err := jamfpro.LoadClientAuthConfig(configFilePath) + if err != nil { + log.Fatalf("Failed to load client OAuth configuration: %v", err) + } + + // Instantiate the default logger and set the desired log level + logger := http_client.NewDefaultLogger() + logLevel := http_client.LogLevelDebug // LogLevelNone // LogLevelWarning // LogLevelInfo // LogLevelDebug + + // Configuration for the jamfpro + config := jamfpro.Config{ + InstanceName: authConfig.InstanceName, + LogLevel: logLevel, + Logger: logger, + ClientID: authConfig.ClientID, + ClientSecret: authConfig.ClientSecret, + } + + // Create a new jamfpro client instance + client, err := jamfpro.NewClient(config) + if err != nil { + log.Fatalf("Failed to create Jamf Pro client: %v", err) + } + + // Define the application name and the subset you want to retrieve + appID := 1 // Replace with the actual application name + subset := "General" // Subset values can be General, Scope, SelfService, VPPCodes and VPP. + + // Call GetMacApplicationByNameAndDataSubset + macApp, err := client.GetMacApplicationByIDAndDataSubset(appID, subset) + if err != nil { + log.Fatalf("Error fetching Mac Application by Name and Subset: %v", err) + } + + // Pretty print the response in XML + macAppXML, err := xml.MarshalIndent(macApp, "", " ") // Indent with 4 spaces + if err != nil { + log.Fatalf("Error marshaling Mac Application data: %v", err) + } + fmt.Println("Fetched Mac Application Data:\n", string(macAppXML)) +} diff --git a/examples/mac_applications/GetMacApplicationByName/GetMacApplicationByName.go b/examples/mac_applications/GetMacApplicationByName/GetMacApplicationByName.go new file mode 100644 index 000000000..76068859c --- /dev/null +++ b/examples/mac_applications/GetMacApplicationByName/GetMacApplicationByName.go @@ -0,0 +1,53 @@ +package main + +import ( + "encoding/xml" + "fmt" + "log" + + "github.com/deploymenttheory/go-api-sdk-jamfpro/sdk/http_client" // Import http_client for logging + "github.com/deploymenttheory/go-api-sdk-jamfpro/sdk/jamfpro" +) + +func main() { + // Define the path to the JSON configuration file + configFilePath := "/Users/dafyddwatkins/GitHub/deploymenttheory/go-api-sdk-jamfpro/clientauth.json" + + // Load the client OAuth credentials from the configuration file + authConfig, err := jamfpro.LoadClientAuthConfig(configFilePath) + if err != nil { + log.Fatalf("Failed to load client OAuth configuration: %v", err) + } + + // Instantiate the default logger and set the desired log level + logger := http_client.NewDefaultLogger() + logLevel := http_client.LogLevelDebug // LogLevelNone // LogLevelWarning // LogLevelInfo // LogLevelDebug + + // Configuration for the jamfpro + config := jamfpro.Config{ + InstanceName: authConfig.InstanceName, + LogLevel: logLevel, + Logger: logger, + ClientID: authConfig.ClientID, + ClientSecret: authConfig.ClientSecret, + } + + // Create a new jamfpro client instance + client, err := jamfpro.NewClient(config) + if err != nil { + log.Fatalf("Failed to create Jamf Pro client: %v", err) + } + + name := "TextWrangler.app" // Replace with your Mac application name + macApp, err := client.GetMacApplicationByName(name) + if err != nil { + log.Fatalf("Error fetching Mac Application by Name: %v", err) + } + + // Pretty print the profile in XML + profileXML, err := xml.MarshalIndent(macApp, "", " ") // Indent with 4 spaces + if err != nil { + log.Fatalf("Error marshaling VPP mac Application data: %v", err) + } + fmt.Println("Fetched VPP mac Application:\n", string(profileXML)) +} diff --git a/examples/mac_applications/GetMacApplicationByNameAndDataSubset/GetMacApplicationByNameAndDataSubset.go b/examples/mac_applications/GetMacApplicationByNameAndDataSubset/GetMacApplicationByNameAndDataSubset.go new file mode 100644 index 000000000..a8800dd38 --- /dev/null +++ b/examples/mac_applications/GetMacApplicationByNameAndDataSubset/GetMacApplicationByNameAndDataSubset.go @@ -0,0 +1,57 @@ +package main + +import ( + "encoding/xml" + "fmt" + "log" + + "github.com/deploymenttheory/go-api-sdk-jamfpro/sdk/http_client" // Import http_client for logging + "github.com/deploymenttheory/go-api-sdk-jamfpro/sdk/jamfpro" +) + +func main() { + // Define the path to the JSON configuration file + configFilePath := "/Users/dafyddwatkins/GitHub/deploymenttheory/go-api-sdk-jamfpro/clientauth.json" + + // Load the client OAuth credentials from the configuration file + authConfig, err := jamfpro.LoadClientAuthConfig(configFilePath) + if err != nil { + log.Fatalf("Failed to load client OAuth configuration: %v", err) + } + + // Instantiate the default logger and set the desired log level + logger := http_client.NewDefaultLogger() + logLevel := http_client.LogLevelDebug // LogLevelNone // LogLevelWarning // LogLevelInfo // LogLevelDebug + + // Configuration for the jamfpro + config := jamfpro.Config{ + InstanceName: authConfig.InstanceName, + LogLevel: logLevel, + Logger: logger, + ClientID: authConfig.ClientID, + ClientSecret: authConfig.ClientSecret, + } + + // Create a new jamfpro client instance + client, err := jamfpro.NewClient(config) + if err != nil { + log.Fatalf("Failed to create Jamf Pro client: %v", err) + } + + // Define the application name and the subset you want to retrieve + appName := "TextWrangler.app" // Replace with the actual application name + subset := "General" // Subset values can be General, Scope, SelfService, VPPCodes and VPP. + + // Call GetMacApplicationByNameAndDataSubset + macApp, err := client.GetMacApplicationByNameAndDataSubset(appName, subset) + if err != nil { + log.Fatalf("Error fetching Mac Application by Name and Subset: %v", err) + } + + // Pretty print the response in XML + macAppXML, err := xml.MarshalIndent(macApp, "", " ") // Indent with 4 spaces + if err != nil { + log.Fatalf("Error marshaling Mac Application data: %v", err) + } + fmt.Println("Fetched Mac Application Data:\n", string(macAppXML)) +} diff --git a/examples/mac_applications/GetMacApplications/GetMacApplications.go b/examples/mac_applications/GetMacApplications/GetMacApplications.go new file mode 100644 index 000000000..bb47d4d69 --- /dev/null +++ b/examples/mac_applications/GetMacApplications/GetMacApplications.go @@ -0,0 +1,48 @@ +package main + +import ( + "fmt" + "log" + + "github.com/deploymenttheory/go-api-sdk-jamfpro/sdk/http_client" // Import http_client for logging + "github.com/deploymenttheory/go-api-sdk-jamfpro/sdk/jamfpro" +) + +func main() { + // Define the path to the JSON configuration file + configFilePath := "/Users/dafyddwatkins/GitHub/deploymenttheory/go-api-sdk-jamfpro/clientauth.json" + + // Load the client OAuth credentials from the configuration file + authConfig, err := jamfpro.LoadClientAuthConfig(configFilePath) + if err != nil { + log.Fatalf("Failed to load client OAuth configuration: %v", err) + } + + // Instantiate the default logger and set the desired log level + logger := http_client.NewDefaultLogger() + logLevel := http_client.LogLevelDebug // LogLevelNone // LogLevelWarning // LogLevelInfo // LogLevelDebug + + // Configuration for the jamfpro + config := jamfpro.Config{ + InstanceName: authConfig.InstanceName, + LogLevel: logLevel, + Logger: logger, + ClientID: authConfig.ClientID, + ClientSecret: authConfig.ClientSecret, + } + + // Create a new jamfpro client instance + client, err := jamfpro.NewClient(config) + if err != nil { + log.Fatalf("Failed to create Jamf Pro client: %v", err) + } + + macApps, err := client.GetMacApplications() + if err != nil { + log.Fatalf("Error fetching Mac Applications: %v", err) + } + + for _, app := range macApps.MacApplications { + fmt.Printf("ID: %d, Name: %s\n", app.ID, app.Name) + } +} diff --git a/examples/mac_applications/UpdateMacApplicationByID/UpdateMacApplicationByID.go b/examples/mac_applications/UpdateMacApplicationByID/UpdateMacApplicationByID.go new file mode 100644 index 000000000..9847b1f04 --- /dev/null +++ b/examples/mac_applications/UpdateMacApplicationByID/UpdateMacApplicationByID.go @@ -0,0 +1,87 @@ +package main + +import ( + "encoding/xml" + "fmt" + "log" + + "github.com/deploymenttheory/go-api-sdk-jamfpro/sdk/http_client" // Import http_client for logging + "github.com/deploymenttheory/go-api-sdk-jamfpro/sdk/jamfpro" +) + +func main() { + // Define the path to the JSON configuration file + configFilePath := "/Users/dafyddwatkins/GitHub/deploymenttheory/go-api-sdk-jamfpro/clientauth.json" + + // Load the client OAuth credentials from the configuration file + authConfig, err := jamfpro.LoadClientAuthConfig(configFilePath) + if err != nil { + log.Fatalf("Failed to load client OAuth configuration: %v", err) + } + + // Instantiate the default logger and set the desired log level + logger := http_client.NewDefaultLogger() + logLevel := http_client.LogLevelDebug // LogLevelNone // LogLevelWarning // LogLevelInfo // LogLevelDebug + + // Configuration for the jamfpro + config := jamfpro.Config{ + InstanceName: authConfig.InstanceName, + LogLevel: logLevel, + Logger: logger, + ClientID: authConfig.ClientID, + ClientSecret: authConfig.ClientSecret, + } + + // Create a new jamfpro client instance + client, err := jamfpro.NewClient(config) + if err != nil { + log.Fatalf("Failed to create Jamf Pro client: %v", err) + } + + // Define the Mac Application to be updated + updateMacApp := jamfpro.ResponseMacApplications{ + General: jamfpro.MacAppDataSubsetGeneral{ + Name: "TextWrangler.app", + Version: "5.5.2", + IsFree: true, + BundleID: "com.barebones.textwrangler", + URL: "https://itunes.apple.com/us/app/textwrangler/id404010395?mt=12&uo=4", + Category: jamfpro.MacAppCategory{ID: -1, Name: "Unknown"}, + Site: jamfpro.MacAppSite{ID: -1, Name: "None"}, + }, + Scope: jamfpro.MacAppDataSubsetScope{ + AllComputers: false, + AllJSSUsers: false, + }, + SelfService: jamfpro.MacAppDataSubsetSelfService{ + InstallButtonText: "Install", + SelfServiceDescription: "Installs the TextWrangler application", + ForceUsersToViewDescription: true, + SelfServiceIcon: jamfpro.MacAppSelfServiceIcon{}, + FeatureOnMainPage: true, + SelfServiceCategories: []jamfpro.MacAppSelfServiceCategory{}, + Notification: "string", + NotificationSubject: "TextWrangler is Available to Install", + NotificationMessage: "You can install TextWrangler by clicking this link or going to Self Service", + VPP: jamfpro.MacAppVPP{ + AssignVPPDeviceBasedLicenses: false, + VPPAdminAccountID: -1, + }, + }, + } + + id := 1 // Replace with your Mac application ID + // Call UpdateMacApplicationByID + updatedMacApp, err := client.UpdateMacApplicationByID(id, updateMacApp) // Replace 123 with the actual ID + if err != nil { + log.Fatalf("Error updating Mac Application by ID: %v", err) + } + + // Print the updated Mac Application details + updatedMacAppXML, err := xml.MarshalIndent(updatedMacApp, "", " ") // Indent with 4 spaces + if err != nil { + log.Fatalf("Error marshaling updated Mac Application data: %v", err) + } + fmt.Println("Updated Mac Application:\n", string(updatedMacAppXML)) + +} diff --git a/examples/mac_applications/UpdateMacApplicationByName/UpdateMacApplicationByName.go b/examples/mac_applications/UpdateMacApplicationByName/UpdateMacApplicationByName.go new file mode 100644 index 000000000..10a1fed19 --- /dev/null +++ b/examples/mac_applications/UpdateMacApplicationByName/UpdateMacApplicationByName.go @@ -0,0 +1,87 @@ +package main + +import ( + "encoding/xml" + "fmt" + "log" + + "github.com/deploymenttheory/go-api-sdk-jamfpro/sdk/http_client" // Import http_client for logging + "github.com/deploymenttheory/go-api-sdk-jamfpro/sdk/jamfpro" +) + +func main() { + // Define the path to the JSON configuration file + configFilePath := "/Users/dafyddwatkins/GitHub/deploymenttheory/go-api-sdk-jamfpro/clientauth.json" + + // Load the client OAuth credentials from the configuration file + authConfig, err := jamfpro.LoadClientAuthConfig(configFilePath) + if err != nil { + log.Fatalf("Failed to load client OAuth configuration: %v", err) + } + + // Instantiate the default logger and set the desired log level + logger := http_client.NewDefaultLogger() + logLevel := http_client.LogLevelDebug // LogLevelNone // LogLevelWarning // LogLevelInfo // LogLevelDebug + + // Configuration for the jamfpro + config := jamfpro.Config{ + InstanceName: authConfig.InstanceName, + LogLevel: logLevel, + Logger: logger, + ClientID: authConfig.ClientID, + ClientSecret: authConfig.ClientSecret, + } + + // Create a new jamfpro client instance + client, err := jamfpro.NewClient(config) + if err != nil { + log.Fatalf("Failed to create Jamf Pro client: %v", err) + } + + // Define the Mac Application to be updated + updateMacApp := jamfpro.ResponseMacApplications{ + General: jamfpro.MacAppDataSubsetGeneral{ + Name: "BBEdit.app", + Version: "14", + IsFree: true, + BundleID: "com.barebones.bbedit", + URL: "https://apps.apple.com/gb/app/bbedit/id404009241?mt=12", + Category: jamfpro.MacAppCategory{ID: -1, Name: "Unknown"}, + Site: jamfpro.MacAppSite{ID: -1, Name: "None"}, + }, + Scope: jamfpro.MacAppDataSubsetScope{ + AllComputers: false, + AllJSSUsers: false, + }, + SelfService: jamfpro.MacAppDataSubsetSelfService{ + InstallButtonText: "Install", + SelfServiceDescription: "Installs the TextWrangler application", + ForceUsersToViewDescription: true, + SelfServiceIcon: jamfpro.MacAppSelfServiceIcon{}, + FeatureOnMainPage: true, + SelfServiceCategories: []jamfpro.MacAppSelfServiceCategory{}, + Notification: "string", + NotificationSubject: "TextWrangler is Available to Install", + NotificationMessage: "You can install TextWrangler by clicking this link or going to Self Service", + VPP: jamfpro.MacAppVPP{ + AssignVPPDeviceBasedLicenses: false, + VPPAdminAccountID: -1, + }, + }, + } + + macAppName := "TextWrangler.app" // Replace with your vpp Mac application name + // Call UpdateMacApplicationByName + updatedMacApp, err := client.UpdateMacApplicationByName(macAppName, updateMacApp) + if err != nil { + log.Fatalf("Error updating Mac Application by Name: %v", err) + } + + // Print the updated Mac Application details + updatedMacAppXML, err := xml.MarshalIndent(updatedMacApp, "", " ") // Indent with 4 spaces + if err != nil { + log.Fatalf("Error marshaling updated Mac Application data: %v", err) + } + fmt.Println("Updated Mac Application:\n", string(updatedMacAppXML)) + +} diff --git a/migration/jamfpro/appStoreMacApplication.go b/migration/jamfpro/appStoreMacApplication.go deleted file mode 100644 index a5a9b463a..000000000 --- a/migration/jamfpro/appStoreMacApplication.go +++ /dev/null @@ -1,255 +0,0 @@ -// appStoreMacApplication.go -// Jamf Pro Classic Api -// Classic API requires the structs to support both XML and JSON. - -package jamfpro - -import ( - "encoding/xml" - "fmt" -) - -const uriAPIAppStoreMacApplication = "/JSSResource/macapplications" - -// Top-level struct -type ResponseAppStoreMacApplication struct { - General General `xml:"general"` - Scope Scope `xml:"scope"` - SelfService SelfService `xml:"self_service"` -} - -// Tier 2 - General Section -type General struct { - ID int `xml:"id,omitempty"` - Name string `xml:"name"` - Version string `xml:"version"` - IsFree bool `xml:"is_free,omitempty"` - BundleID string `xml:"bundle_id"` - URL string `xml:"url"` - Category AppStoreMacApplicationDataSubsetIDName `xml:"category,omitempty"` - Site AppStoreMacApplicationDataSubsetIDName `xml:"site,omitempty"` -} - -// Tier 2 - Scope section -type Scope struct { - AllComputers bool `xml:"all_computers,omitempty"` - AllJSSUsers bool `xml:"all_jss_users,omitempty"` - Buildings []AppStoreMacApplicationDataSubsetBuilding `xml:"buildings,omitempty"` - Departments []AppStoreMacApplicationDataSubsetDepartment `xml:"departments,omitempty"` - Computers []AppStoreMacApplicationDataSubsetComputer `xml:"computers,omitempty"` - ComputerGroups []AppStoreMacApplicationDataSubsetComputerGroup `xml:"computer_groups,omitempty"` - JSSUsers []AppStoreMacApplicationDataSubsetJSSUser `xml:"jss_users,omitempty"` - JSSUserGroups []AppStoreMacApplicationDataSubsetJSSUserGroup `xml:"jss_user_groups,omitempty"` - Limitations struct { - Users []AppStoreMacApplicationDataSubsetJSSUser `xml:"users,omitempty"` - UserGroups []AppStoreMacApplicationDataSubsetJSSUserGroup `xml:"user_groups,omitempty"` - NetworkSegments []struct { - NetworkSegment AppStoreMacApplicationDataSubsetIDName `xml:"network_segment,omitempty"` - } `xml:"network_segments"` - } `xml:"limitations,omitempty"` - Exclusions struct { - Buildings []AppStoreMacApplicationDataSubsetBuilding `xml:"buildings,omitempty"` - Departments []AppStoreMacApplicationDataSubsetDepartment `xml:"departments,omitempty"` - Users []AppStoreMacApplicationDataSubsetJSSUser `xml:"users,omitempty"` - UserGroups []AppStoreMacApplicationDataSubsetJSSUserGroup `xml:"user_groups,omitempty"` - NetworkSegments []struct { - NetworkSegment struct { - ID int `xml:"id,omitempty"` - UID string `xml:"uid,omitempty"` - Name string `xml:"name"` - } `xml:"network_segment,omitempty"` - } `xml:"network_segments"` - Computers []AppStoreMacApplicationDataSubsetComputer `xml:"computers,omitempty"` - ComputerGroups []AppStoreMacApplicationDataSubsetComputerGroup `xml:"computer_groups,omitempty"` - JSSUsers []AppStoreMacApplicationDataSubsetJSSUser `xml:"jss_users,omitempty"` - JSSUserGroups []AppStoreMacApplicationDataSubsetJSSUserGroup `xml:"jss_user_groups,omitempty"` - } `xml:"exclusions,omitempty"` -} - -// Tier 2 - SelfService section -type SelfService struct { - InstallButtonText string `xml:"install_button_text,omitempty"` - SelfServiceDescription string `xml:"self_service_description,omitempty"` - ForceUsersToViewDescription bool `xml:"force_users_to_view_description,omitempty"` - SelfServiceIcon AppStoreMacApplicationDataSubsetSelfServiceIcon `xml:"self_service_icon,omitempty"` - FeatureOnMainPage bool `xml:"feature_on_main_page,omitempty"` - SelfServiceCategories []AppStoreMacApplicationDataSubsetSelfServiceCategory `xml:"self_service_categories,omitempty"` - Notification string `xml:"notification,omitempty"` - NotificationSubject string `xml:"notification_subject,omitempty"` - NotificationMessage string `xml:"notification_message,omitempty"` - VPP AppStoreMacApplicationDataSubsetVPP `xml:"vpp,omitempty"` -} - -// Tier 3 - Scope Section - -// Shared inner structs for reusability -type AppStoreMacApplicationDataSubsetIDName struct { - ID int `xml:"id,omitempty"` - Name string `xml:"name,omitempty"` -} - -type AppStoreMacApplicationDataSubsetBuilding struct { - Building AppStoreMacApplicationDataSubsetIDName `xml:"building,omitempty"` -} - -type AppStoreMacApplicationDataSubsetDepartment struct { - Department AppStoreMacApplicationDataSubsetIDName `xml:"department,omitempty"` -} - -type AppStoreMacApplicationDataSubsetComputer struct { - Computer struct { - ID int `xml:"id,omitempty"` - Name string `xml:"name"` - UDID string `xml:"udid,omitempty"` - } `xml:"computer"` -} - -type AppStoreMacApplicationDataSubsetComputerGroup struct { - ComputerGroup AppStoreMacApplicationDataSubsetIDName `xml:"computer_group,omitempty"` -} - -type AppStoreMacApplicationDataSubsetJSSUser struct { - User AppStoreMacApplicationDataSubsetIDName `xml:"user,omitempty"` -} - -type AppStoreMacApplicationDataSubsetJSSUserGroup struct { - UserGroup AppStoreMacApplicationDataSubsetIDName `xml:"user_group,omitempty"` -} - -// Tier 3 - Self Service section -type AppStoreMacApplicationDataSubsetSelfServiceIcon struct { - ID int `xml:"id,omitempty"` - URI string `xml:"uri,omitempty"` - Data string `xml:"data,omitempty"` -} - -type AppStoreMacApplicationDataSubsetSelfServiceCategory struct { - Category struct { - ID int `xml:"id,omitempty"` - Name string `xml:"name"` - DisplayIn bool `xml:"display_in,omitempty"` - FeatureIn bool `xml:"feature_in,omitempty"` - } `xml:"category"` -} - -// Tier 3 - VPP section -type AppStoreMacApplicationDataSubsetVPP struct { - AssignVPPDeviceBasedLicenses bool `xml:"assign_vpp_device_based_licenses,omitempty"` - VPPAdminAccountID int `xml:"vpp_admin_account_id,omitempty"` -} - -// List all app store mac apps - -type ResponseAppStoreMacApplicationList struct { - MacApplications []MacApplication `xml:"mac_application"` -} - -type MacApplication struct { - ID int `xml:"id"` - Name string `xml:"name"` -} - -// Create / Update - App store mac application - -type AppStoreMacApplication struct { - XMLName xml.Name `xml:"mac_application"` - General General `xml:"general"` - Scope Scope `xml:"scope"` - SelfService SelfService `xml:"self_service"` -} - -//--- appStoreMacApplication CRUD Functions ---// - -// GetAppStoreMacApplicationByID retrieves the App Store Mac Application by its ID -func (c *Client) GetAppStoreMacApplicationByID(id int) (*ResponseAppStoreMacApplication, error) { - url := fmt.Sprintf("%s/id/%d", uriAPIAppStoreMacApplication, id) - - var app ResponseAppStoreMacApplication - if err := c.DoRequest("GET", url, nil, nil, &app); err != nil { - // The raw response logging is already handled within DoRequestDebug, so we don't need to explicitly log it here. - return nil, fmt.Errorf("failed to execute request: %v", err) - } - - return &app, nil -} - -// GetAppStoreMacApplications retrieves a list of all App Store Mac Applications -func (c *Client) GetAppStoreMacApplications() ([]ResponseAppStoreMacApplicationList, error) { - url := uriAPIAppStoreMacApplication - - // Define a slice of the adjusted struct to hold the response - var appList []ResponseAppStoreMacApplicationList - - if err := c.DoRequest("GET", url, nil, nil, &appList); err != nil { - // Handle error - return nil, fmt.Errorf("failed to execute request: %v", err) - } - - return appList, nil -} - -// GetAppStoreMacApplicationByName retrieves the App Store Mac Application by its name -func (c *Client) GetAppStoreMacApplicationByName(appName string) (*ResponseAppStoreMacApplication, error) { - url := fmt.Sprintf("%s/name/%s", uriAPIAppStoreMacApplication, appName) - - var app ResponseAppStoreMacApplication - if err := c.DoRequest("GET", url, nil, nil, &app); err != nil { - return nil, fmt.Errorf("failed to execute request: %v", err) - } - - return &app, nil -} - -// CreateAppStoreMacApplication creates a new App Store Mac Application -func (c *Client) CreateAppStoreMacApplication(app *AppStoreMacApplication) (*ResponseAppStoreMacApplication, error) { - // URL for creating a new App Store Mac Application - url := uriAPIAppStoreMacApplication - - // Execute the request - var responseApp ResponseAppStoreMacApplication - if err := c.DoRequest("POST", url, app, nil, &responseApp); err != nil { - return nil, fmt.Errorf("failed to create App Store Mac Application: %v", err) - } - - return &responseApp, nil -} - -// UpdateAppStoreMacApplication updates an existing App Store Mac Application -func (c *Client) UpdateAppStoreMacApplication(id int, app *AppStoreMacApplication) (*ResponseAppStoreMacApplication, error) { - // URL for updating the App Store Mac Application with the specified ID - url := fmt.Sprintf("%s/id/%d", uriAPIAppStoreMacApplication, id) - - // Execute the request - var responseApp ResponseAppStoreMacApplication - if err := c.DoRequest("PUT", url, app, nil, &responseApp); err != nil { - return nil, fmt.Errorf("failed to update App Store Mac Application: %v", err) - } - - return &responseApp, nil -} - -// DeleteAppStoreMacApplicationByID deletes an App Store Mac Application by its ID -func (c *Client) DeleteAppStoreMacApplicationByID(id int) error { - // URL for deleting the App Store Mac Application with the specified ID - url := fmt.Sprintf("%s/id/%d", uriAPIAppStoreMacApplication, id) - - // Execute the request - if err := c.DoRequest("DELETE", url, nil, nil, nil); err != nil { - return fmt.Errorf("failed to delete App Store Mac Application: %v", err) - } - - return nil -} - -// DeleteAppStoreMacApplicationByName deletes an App Store Mac Application by its name -func (c *Client) DeleteAppStoreMacApplicationByName(appName string) error { - // URL for deleting the App Store Mac Application with the specified name - url := fmt.Sprintf("%s/name/%s", uriAPIAppStoreMacApplication, appName) - - // Execute the request - if err := c.DoRequest("DELETE", url, nil, nil, nil); err != nil { - return fmt.Errorf("failed to delete App Store Mac Application named '%s': %v", appName, err) - } - - return nil -} diff --git a/migration/jamfpro/helpers.go b/migration/jamfpro/helpers.go deleted file mode 100644 index bace31f62..000000000 --- a/migration/jamfpro/helpers.go +++ /dev/null @@ -1,31 +0,0 @@ -package jamfpro - -import ( - "net/http" - - "github.com/pkg/errors" -) - -func (c *Client) invalidateToken() error { - req, err := http.NewRequest("POST", c.url+"/api/v1/auth/invalidate-token", nil) - if err != nil { - return err - } - req.Header.Add("Authorization", "Bearer "+*c.token) - - resp, err := c.HttpClient.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - if resp.StatusCode == 204 { - c.token = nil - c.tokenExpiration = nil - return nil - } else if resp.StatusCode == 401 { - return errors.New("Token already invalid") - } - - return errors.New("An unknown error occurred invalidating the token") -} diff --git a/sdk/jamfpro/classicapi_mac_applications.go b/sdk/jamfpro/classicapi_mac_applications.go new file mode 100644 index 000000000..231c415d9 --- /dev/null +++ b/sdk/jamfpro/classicapi_mac_applications.go @@ -0,0 +1,376 @@ +// classicapi_mac_applications.go +// Jamf Pro Classic Api - VPP Mac Applications +// api reference: https://developer.jamf.com/jamf-pro/reference/macapplications +// Classic API requires the structs to support an XML data structure. + +package jamfpro + +import ( + "encoding/xml" + "fmt" +) + +const uriVPPMacApplications = "/JSSResource/macapplications" + +type ResponseMacApplicationsList struct { + MacApplications []MacApplication `xml:"mac_application"` +} + +type MacApplication struct { + ID int `xml:"id"` + Name string `xml:"name"` +} + +// ResponseMacApplications represents the detailed structure of a Mac Application response. +type ResponseMacApplications struct { + General MacAppDataSubsetGeneral `xml:"general"` + Scope MacAppDataSubsetScope `xml:"scope"` + SelfService MacAppDataSubsetSelfService `xml:"self_service"` +} + +type MacAppDataSubsetGeneral struct { + ID int `xml:"id"` + Name string `xml:"name"` + Version string `xml:"version"` + IsFree bool `xml:"is_free"` + BundleID string `xml:"bundle_id"` + URL string `xml:"url"` + Category MacAppCategory `xml:"category"` + Site MacAppSite `xml:"site"` +} + +type MacAppCategory struct { + ID int `xml:"id"` + Name string `xml:"name"` +} + +type MacAppSite struct { + ID int `xml:"id"` + Name string `xml:"name"` +} + +type MacAppDataSubsetScope struct { + AllComputers bool `xml:"all_computers"` + AllJSSUsers bool `xml:"all_jss_users"` + Buildings []MacAppScopeBuilding `xml:"buildings>building"` + Departments []MacAppScopeDepartment `xml:"departments>department"` + Computers []MacAppScopeComputer `xml:"computers>computer"` + ComputerGroups []MacAppScopeComputerGroup `xml:"computer_groups>computer_group"` + JSSUsers []MacAppScopeUser `xml:"jss_users>user"` + JSSUserGroups []MacAppScopeUserGroup `xml:"jss_user_groups>user_group"` + Limitations MacAppScopeLimitations `xml:"limitations"` + Exclusions MacAppScopeExclusions `xml:"exclusions"` +} + +// Define structs for each scope component (Building, Department, Computer, etc.) +type MacAppScopeBuilding struct { + Building MacAppBuilding `xml:"building"` +} + +type MacAppBuilding struct { + ID int `xml:"id"` + Name string `xml:"name"` +} + +// Struct definitions for Department, Computer, ComputerGroup, User, UserGroup + +type MacAppScopeDepartment struct { + Department MacAppDepartment `xml:"department"` +} + +type MacAppDepartment struct { + ID int `xml:"id"` + Name string `xml:"name"` +} + +type MacAppScopeComputer struct { + Computer MacAppComputer `xml:"computer"` +} + +type MacAppComputer struct { + ID int `xml:"id"` + Name string `xml:"name"` + UDID string `xml:"udid"` +} + +type MacAppScopeComputerGroup struct { + ComputerGroup MacAppComputerGroup `xml:"computer_group"` +} + +type MacAppComputerGroup struct { + ID int `xml:"id"` + Name string `xml:"name"` +} + +type MacAppScopeUser struct { + User MacAppUser `xml:"user"` +} + +type MacAppUser struct { + ID int `xml:"id"` + Name string `xml:"name"` +} + +type MacAppScopeUserGroup struct { + UserGroup MacAppUserGroup `xml:"user_group"` +} + +type MacAppUserGroup struct { + ID int `xml:"id"` + Name string `xml:"name"` +} + +type MacAppScopeLimitations struct { + Users []MacAppScopeUser `xml:"users>user"` + UserGroups []MacAppScopeUserGroup `xml:"user_groups>user_group"` + NetworkSegments []MacAppScopeNetworkSegment `xml:"network_segments>network_segment"` +} + +type MacAppScopeExclusions struct { + Buildings []MacAppScopeBuilding `xml:"buildings>building"` + Departments []MacAppScopeDepartment `xml:"departments>department"` + Users []MacAppScopeUser `xml:"users>user"` + UserGroups []MacAppScopeUserGroup `xml:"user_groups>user_group"` + NetworkSegments []MacAppScopeNetworkSegment `xml:"network_segments>network_segment"` + Computers []MacAppScopeComputer `xml:"computers>computer"` + ComputerGroups []MacAppScopeComputerGroup `xml:"computer_groups>computer_group"` + JSSUsers []MacAppScopeUser `xml:"jss_users>user"` + JSSUserGroups []MacAppScopeUserGroup `xml:"jss_user_groups>user_group"` +} + +type MacAppScopeNetworkSegment struct { + ID int `xml:"id"` + UID string `xml:"uid,omitempty"` + Name string `xml:"name"` +} + +type MacAppDataSubsetSelfService struct { + InstallButtonText string `xml:"install_button_text"` + SelfServiceDescription string `xml:"self_service_description"` + ForceUsersToViewDescription bool `xml:"force_users_to_view_description"` + SelfServiceIcon MacAppSelfServiceIcon `xml:"self_service_icon"` + FeatureOnMainPage bool `xml:"feature_on_main_page"` + SelfServiceCategories []MacAppSelfServiceCategory `xml:"self_service_categories>category"` + Notification string `xml:"notification"` + NotificationSubject string `xml:"notification_subject"` + NotificationMessage string `xml:"notification_message"` + VPP MacAppVPP `xml:"vpp"` +} + +type MacAppSelfServiceIcon struct { + ID int `xml:"id"` + URI string `xml:"uri"` + Data string `xml:"data"` +} + +type MacAppSelfServiceCategory struct { + ID int `xml:"id"` + Name string `xml:"name"` + DisplayIn bool `xml:"display_in"` + FeatureIn bool `xml:"feature_in"` +} + +type MacAppVPP struct { + AssignVPPDeviceBasedLicenses bool `xml:"assign_vpp_device_based_licenses"` + VPPAdminAccountID int `xml:"vpp_admin_account_id"` +} + +// GetDockItems retrieves a serialized list of vpp mac applications. +func (c *Client) GetMacApplications() (*ResponseMacApplicationsList, error) { + endpoint := uriVPPMacApplications + + var macApps ResponseMacApplicationsList + resp, err := c.HTTP.DoRequest("GET", endpoint, nil, &macApps) + if err != nil { + return nil, fmt.Errorf("failed to fetch Mac Applications: %v", err) + } + + if resp != nil && resp.Body != nil { + defer resp.Body.Close() + } + + return &macApps, nil +} + +// GetMacApplicationByID retrieves a single Mac application by its ID. +func (c *Client) GetMacApplicationByID(id int) (*ResponseMacApplications, error) { + endpoint := fmt.Sprintf("%s/id/%d", uriVPPMacApplications, id) + + var macApp ResponseMacApplications + resp, err := c.HTTP.DoRequest("GET", endpoint, nil, &macApp) + if err != nil { + return nil, fmt.Errorf("failed to fetch Mac Application by ID: %v", err) + } + + if resp != nil && resp.Body != nil { + defer resp.Body.Close() + } + + return &macApp, nil +} + +// GetMacApplicationByName retrieves a single Mac application by its name. +func (c *Client) GetMacApplicationByName(name string) (*ResponseMacApplications, error) { + endpoint := fmt.Sprintf("%s/name/%s", uriVPPMacApplications, name) + + var macApp ResponseMacApplications + resp, err := c.HTTP.DoRequest("GET", endpoint, nil, &macApp) + if err != nil { + return nil, fmt.Errorf("failed to fetch Mac Application by Name: %v", err) + } + + if resp != nil && resp.Body != nil { + defer resp.Body.Close() + } + + return &macApp, nil +} + +// GetMacApplicationByNameAndDataSubset retrieves a specific Mac Application by its ID and filters by a specific data subset. +// Subset values can be General, Scope, SelfService, VPPCodes and VPP. +func (c *Client) GetMacApplicationByIDAndDataSubset(id int, subset string) (*ResponseMacApplications, error) { + endpoint := fmt.Sprintf("%s/id/%d/subset/%s", uriVPPMacApplications, id, subset) + + var macApp ResponseMacApplications + resp, err := c.HTTP.DoRequest("GET", endpoint, nil, &macApp) + if err != nil { + return nil, fmt.Errorf("failed to fetch Mac Application by Name and Subset: %v", err) + } + + if resp != nil && resp.Body != nil { + defer resp.Body.Close() + } + + return &macApp, nil +} + +// GetMacApplicationByNameAndDataSubset retrieves a specific Mac Application by its name and filters by a specific data subset. +// Subset values can be General, Scope, SelfService, VPPCodes and VPP. +func (c *Client) GetMacApplicationByNameAndDataSubset(name, subset string) (*ResponseMacApplications, error) { + endpoint := fmt.Sprintf("%s/name/%s/subset/%s", uriVPPMacApplications, name, subset) + + var macApp ResponseMacApplications + resp, err := c.HTTP.DoRequest("GET", endpoint, nil, &macApp) + if err != nil { + return nil, fmt.Errorf("failed to fetch Mac Application by Name and Subset: %v", err) + } + + if resp != nil && resp.Body != nil { + defer resp.Body.Close() + } + + return &macApp, nil +} + +// CreateMacApplication creates a new Mac Application. +func (c *Client) CreateMacApplication(macApp ResponseMacApplications) (*ResponseMacApplications, error) { + endpoint := fmt.Sprintf("%s/id/0", uriVPPMacApplications) // '0' typically used for creation in APIs + + // Set default values for site if not included within request + if macApp.General.Site.ID == 0 && macApp.General.Site.Name == "" { + macApp.General.Site = MacAppSite{ + ID: -1, + Name: "None", + } + } + + // The requestBody struct should mirror the ResponseMacApplications struct, including all nested structs + requestBody := struct { + XMLName xml.Name `xml:"mac_application"` + ResponseMacApplications + }{ + ResponseMacApplications: macApp, + } + + var response ResponseMacApplications + resp, err := c.HTTP.DoRequest("POST", endpoint, &requestBody, &response) + if err != nil { + return nil, fmt.Errorf("failed to create Mac Application: %v", err) + } + + if resp != nil && resp.Body != nil { + defer resp.Body.Close() + } + + return &response, nil +} + +// UpdateMacApplicationByID updates an existing Mac Application by its ID. +func (c *Client) UpdateMacApplicationByID(id int, macApp ResponseMacApplications) (*ResponseMacApplications, error) { + endpoint := fmt.Sprintf("%s/id/%d", uriVPPMacApplications, id) + + requestBody := struct { + XMLName xml.Name `xml:"mac_application"` + ResponseMacApplications + }{ + ResponseMacApplications: macApp, + } + + var response ResponseMacApplications + resp, err := c.HTTP.DoRequest("PUT", endpoint, &requestBody, &response) + if err != nil { + return nil, fmt.Errorf("failed to update Mac Application by ID: %v", err) + } + + if resp != nil && resp.Body != nil { + defer resp.Body.Close() + } + + return &response, nil +} + +// UpdateMacApplicationByName updates an existing Mac Application by its name. +func (c *Client) UpdateMacApplicationByName(name string, macApp ResponseMacApplications) (*ResponseMacApplications, error) { + endpoint := fmt.Sprintf("%s/name/%s", uriVPPMacApplications, name) + + requestBody := struct { + XMLName xml.Name `xml:"mac_application"` + ResponseMacApplications + }{ + ResponseMacApplications: macApp, + } + + var response ResponseMacApplications + resp, err := c.HTTP.DoRequest("PUT", endpoint, &requestBody, &response) + if err != nil { + return nil, fmt.Errorf("failed to update Mac Application by Name: %v", err) + } + + if resp != nil && resp.Body != nil { + defer resp.Body.Close() + } + + return &response, nil +} + +// DeleteMacApplicationByID deletes a MacApplication by its ID. +func (c *Client) DeleteMacApplicationByID(id int) error { + endpoint := fmt.Sprintf("%s/id/%d", uriVPPMacApplications, id) + + resp, err := c.HTTP.DoRequest("DELETE", endpoint, nil, nil) + if err != nil { + return fmt.Errorf("failed to delete VPP Mac Application Item by ID: %v", err) + } + + if resp != nil && resp.Body != nil { + defer resp.Body.Close() + } + + return nil +} + +// DeleteMacApplicationByName deletes a MacApplication by its name. +func (c *Client) DeleteMacApplicationByName(name string) error { + endpoint := fmt.Sprintf("%s/name/%s", uriVPPMacApplications, name) + + resp, err := c.HTTP.DoRequest("DELETE", endpoint, nil, nil) + if err != nil { + return fmt.Errorf("failed to delete VPP Mac Application Item by Name: %v", err) + } + + if resp != nil && resp.Body != nil { + defer resp.Body.Close() + } + + return nil +}