client

package
v0.7.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 1, 2026 License: MIT Imports: 23 Imported by: 0

Documentation

Index

Constants

View Source
const (
	AuthMethodOAuth2 = "oauth2"
	AuthMethodBasic  = "basic"
)

AuthMethod constants for the Jamf Pro authentication methods.

View Source
const (
	DefaultTimeout   = 120 * time.Second
	MaxRetries       = 3
	RetryWaitTime    = 2 * time.Second
	RetryMaxWaitTime = 30 * time.Second

	// DefaultMaxConcurrentRequests is the Jamf-recommended maximum of 5
	// concurrent API connections. Set to 0 to use WithMaxConcurrentRequests.
	DefaultMaxConcurrentRequests = 5

	// DefaultPageSize is the number of results fetched per page in GetPaginated.
	DefaultPageSize = 200
)

HTTP client defaults. Aligned with Jamf Pro API scalability guidance: max 5 concurrent connections, exponential backoff for transient errors.

View Source
const (
	StatusBadRequest          = 400
	StatusUnauthorized        = 401
	StatusForbidden           = 403
	StatusNotFound            = 404
	StatusConflict            = 409
	StatusPreconditionFailed  = 412
	StatusUnprocessableEntity = 422
	StatusTooManyRequests     = 429
	StatusInternalServerError = 500
	StatusServiceUnavailable  = 503
)
View Source
const (
	UserAgentBase = "go-sdk-jamfpro-v2"
)
View Source
const Version = "0.1.0"

Version is the SDK version.

Variables

This section is empty.

Functions

func ExtractParamsFromURL

func ExtractParamsFromURL(urlStr string) (map[string]string, error)

ExtractParamsFromURL extracts query parameters from a URL string.

func GetResponseHeader

func GetResponseHeader(resp *interfaces.Response, key string) string

GetResponseHeader returns a header value from the response by key.

func GetResponseHeaders

func GetResponseHeaders(resp *interfaces.Response) http.Header

GetResponseHeaders returns all headers from the response.

func HasNextPage

func HasNextPage(links *PaginationLinks) bool

HasNextPage checks if there is a next page (for link-based pagination).

func IsBadRequest

func IsBadRequest(err error) bool

IsBadRequest checks if the error is a bad request error (400).

func IsNotFound

func IsNotFound(err error) bool

IsNotFound checks if the error is a not found error (404).

func IsResponseError

func IsResponseError(resp *interfaces.Response) bool

IsResponseError returns true if the response status code is 4xx or 5xx.

func IsResponseSuccess

func IsResponseSuccess(resp *interfaces.Response) bool

IsResponseSuccess returns true if the response status code is 2xx.

func IsServerError

func IsServerError(err error) bool

IsServerError checks if the error is a server error (5xx).

func IsUnauthorized

func IsUnauthorized(err error) bool

IsUnauthorized checks if the error is an authentication error (401).

func NewRSQLFilterBuilder

func NewRSQLFilterBuilder() interfaces.RSQLFilterBuilder

NewRSQLFilterBuilder returns a new, empty RSQL filter expression builder.

func ParseErrorResponse

func ParseErrorResponse(body []byte, statusCode int, status, method, endpoint string, logger *zap.Logger) error

ParseErrorResponse parses an error response from the API.

func SetupAuthentication

func SetupAuthentication(restyClient *resty.Client, authConfig *AuthConfig, logger *zap.Logger) (*tokenHolder, error)

SetupAuthentication configures the resty client with Jamf Pro bearer token authentication. A token is fetched immediately to surface misconfiguration at startup. Subsequent requests refresh the token automatically via middleware.

Returns the tokenHolder so the Transport can expose InvalidateToken and KeepAliveToken.

See: https://developer.jamf.com/jamf-pro/docs/classic-api-authentication-changes

Types

type APIError

type APIError struct {
	Code       string
	Message    string
	StatusCode int
	Status     string
	Endpoint   string
	Method     string
}

APIError represents an error response from the Jamf Pro API.

func (*APIError) Error

func (e *APIError) Error() string

Error implements the error interface.

type AuthConfig

type AuthConfig struct {
	// InstanceDomain is the Jamf Pro instance base URL (e.g. https://example.jamfcloud.com).
	InstanceDomain string

	// AuthMethod selects the authentication flow: "oauth2" or "basic".
	AuthMethod string

	// OAuth2 credentials (required when AuthMethod == "oauth2").
	ClientID     string
	ClientSecret string

	// Basic auth credentials (required when AuthMethod == "basic").
	Username string
	Password string

	// TokenRefreshBufferPeriod is how far before expiry to proactively refresh
	// the token. Defaults to 5 minutes if zero.
	TokenRefreshBufferPeriod time.Duration

	// HideSensitiveData suppresses bearer token values in log output.
	// Enable in production to prevent tokens from appearing in log files.
	HideSensitiveData bool
}

AuthConfig holds authentication configuration for the Jamf Pro API.

Two authentication flows are supported:

  • OAuth2 client credentials (recommended): POST /api/v1/oauth/token
  • Basic auth to bearer token exchange: POST /api/v1/auth/token

See: https://developer.jamf.com/jamf-pro/docs/classic-api-authentication-changes

func AuthConfigFromEnv

func AuthConfigFromEnv() *AuthConfig

AuthConfigFromEnv builds AuthConfig from environment variables. Required: INSTANCE_DOMAIN, AUTH_METHOD; for oauth2: CLIENT_ID, CLIENT_SECRET; for basic: BASIC_AUTH_USERNAME, BASIC_AUTH_PASSWORD. Optional: TOKEN_REFRESH_BUFFER_SECONDS (default 300), HIDE_SENSITIVE_DATA (default false).

func LoadAuthConfigFromFile

func LoadAuthConfigFromFile(path string) (*AuthConfig, error)

LoadAuthConfigFromFile loads AuthConfig from a JSON file. Expected keys: instance_domain, auth_method; for oauth2: client_id, client_secret; for basic: basic_auth_username, basic_auth_password. Optional: token_refresh_buffer_period_seconds (default 300).

func (*AuthConfig) Validate

func (a *AuthConfig) Validate() error

Validate checks the auth configuration for required fields.

type ClientOption

type ClientOption func(*Transport) error

ClientOption configures the Transport.

func WithBaseURL

func WithBaseURL(baseURL string) ClientOption

WithBaseURL sets a custom base URL for the API client.

func WithDebug

func WithDebug() ClientOption

WithDebug enables debug mode which logs request and response details.

func WithGlobalHeader

func WithGlobalHeader(key, value string) ClientOption

WithGlobalHeader sets a global header included in all requests.

func WithGlobalHeaders

func WithGlobalHeaders(headers map[string]string) ClientOption

WithGlobalHeaders sets multiple global headers at once.

func WithInsecureSkipVerify

func WithInsecureSkipVerify() ClientOption

WithInsecureSkipVerify disables TLS certificate verification (use only for testing).

func WithLogger

func WithLogger(logger *zap.Logger) ClientOption

WithLogger sets a custom logger for the client.

func WithMandatoryRequestDelay

func WithMandatoryRequestDelay(d time.Duration) ClientOption

WithMandatoryRequestDelay sets a fixed delay after every successful request. Use for bulk operations to avoid hitting Jamf Pro rate limits.

func WithMaxConcurrentRequests

func WithMaxConcurrentRequests(n int) ClientOption

WithMaxConcurrentRequests sets the maximum number of concurrent API requests. Jamf Pro guidance recommends no more than 5 concurrent connections to avoid disrupting other Jamf Pro tasks and managed devices. Pass 0 to disable.

func WithProxy

func WithProxy(proxyURL string) ClientOption

WithProxy sets an HTTP proxy for all requests.

func WithRetryCount

func WithRetryCount(count int) ClientOption

WithRetryCount sets the number of retries for failed requests.

func WithRetryMaxWaitTime

func WithRetryMaxWaitTime(maxWaitTime time.Duration) ClientOption

WithRetryMaxWaitTime sets the maximum wait time between retries.

func WithRetryWaitTime

func WithRetryWaitTime(waitTime time.Duration) ClientOption

WithRetryWaitTime sets the wait time between retry attempts.

func WithTLSClientConfig

func WithTLSClientConfig(tlsConfig *tls.Config) ClientOption

WithTLSClientConfig sets custom TLS configuration.

func WithTimeout

func WithTimeout(timeout time.Duration) ClientOption

WithTimeout sets a custom timeout for HTTP requests.

func WithTotalRetryDuration

func WithTotalRetryDuration(d time.Duration) ClientOption

WithTotalRetryDuration sets a maximum total wall-clock budget for a request including all retry attempts. Requests that exceed this duration are cancelled.

func WithTransport

func WithTransport(transport http.RoundTripper) ClientOption

WithTransport sets a custom HTTP transport (http.RoundTripper).

func WithUserAgent

func WithUserAgent(userAgent string) ClientOption

WithUserAgent sets a custom user agent string.

type OTelConfig

type OTelConfig struct {
	// TracerProvider is the OpenTelemetry tracer provider to use.
	// If nil, the global tracer provider will be used.
	TracerProvider trace.TracerProvider

	// Propagators is the propagator to use for context propagation.
	// If nil, the global propagator will be used.
	Propagators propagation.TextMapPropagator

	// ServiceName is the name of the service for tracing spans.
	// Defaults to "jamfpro-client".
	ServiceName string

	// SpanNameFormatter allows customizing span names.
	// If nil, defaults to "HTTP {method}" format.
	SpanNameFormatter func(operation string, req *http.Request) string
}

OTelConfig holds OpenTelemetry configuration options.

func DefaultOTelConfig

func DefaultOTelConfig() *OTelConfig

DefaultOTelConfig returns a default OpenTelemetry configuration.

type PaginationLinks struct {
	Self string `json:"self"`
	Next string `json:"next,omitempty"`
}

PaginationLinks contains pagination navigation links (for cursor-style APIs).

type Transport

type Transport struct {
	BaseURL string
	// contains filtered or unexported fields
}

Transport is the HTTP transport layer for the Jamf Pro API. It wraps a resty.Client with Jamf-specific behaviour: bearer token auth, idempotent-only retries with exponential backoff, adaptive response-time throttling, sticky-session cookie jar, optional concurrency limiting, and structured logging.

func NewTransport

func NewTransport(authConfig *AuthConfig, options ...ClientOption) (*Transport, error)

NewTransport creates and fully configures a Jamf Pro API transport.

Behaviour applied at construction time (resty native where possible):

  • Bearer token authentication with automatic refresh
  • Idempotent-only retry (GET/PUT/DELETE) with exponential backoff
  • Sticky-session cookie jar (handles jpro-ingress, APBALANCEID, JSESSIONID)
  • Deprecation header warning logged on every response
  • Adaptive inter-request delay derived from response-time EMA tracking

Jamf Pro does not emit rate-limit HTTP headers. Throttling is inferred from observed response times per Jamf scalability best practices.

func (*Transport) Delete

func (t *Transport) Delete(ctx context.Context, path string, rsqlQuery map[string]string, headers map[string]string, result any) (*interfaces.Response, error)

Delete executes a DELETE request.

func (*Transport) DeleteWithBody

func (t *Transport) DeleteWithBody(ctx context.Context, path string, body any, headers map[string]string, result any) (*interfaces.Response, error)

DeleteWithBody executes a DELETE request with a JSON body.

func (*Transport) EnableTracing

func (t *Transport) EnableTracing(config *OTelConfig) error

EnableTracing wraps the HTTP client transport with OpenTelemetry instrumentation. This provides automatic tracing for all HTTP requests made by the client.

The instrumentation captures: - HTTP method, URL, status code - Request and response headers (configurable) - Error details - Request/response timing

All spans follow OpenTelemetry semantic conventions for HTTP clients.

func (*Transport) Get

func (t *Transport) Get(ctx context.Context, path string, rsqlQuery map[string]string, headers map[string]string, result any) (*interfaces.Response, error)

Get executes a GET request.

func (*Transport) GetBytes

func (t *Transport) GetBytes(ctx context.Context, path string, rsqlQuery map[string]string, headers map[string]string) (*interfaces.Response, []byte, error)

GetBytes performs a GET request and returns raw bytes without unmarshaling.

func (*Transport) GetHTTPClient

func (t *Transport) GetHTTPClient() *resty.Client

GetHTTPClient returns the underlying resty client for advanced use.

func (*Transport) GetLogger

func (t *Transport) GetLogger() *zap.Logger

GetLogger returns the configured logger.

func (*Transport) GetPaginated

func (t *Transport) GetPaginated(ctx context.Context, path string, rsqlQuery map[string]string, headers map[string]string, mergePage func(pageData []byte) error) (*interfaces.Response, error)

GetPaginated executes a paginated GET request, transparently fetching all pages and merging them via the caller-supplied mergePage function.

Jamf Pro paginated endpoints return a JSON envelope with "totalCount" and "results". Page numbering is zero-based; page-size defaults to DefaultPageSize. rsqlQuery may include:

  • "filter" – RSQL expression to narrow results (use RSQLBuilder)
  • "sort" – sort field and direction (e.g. "general.name:asc")
  • "page" – override starting page (default 0)
  • "page-size" – override page size (default DefaultPageSize)

Pagination is only available on endpoints that explicitly support it. Example: GET /api/v3/computers-inventory See: https://developer.jamf.com/jamf-pro/reference/get_v3-computers-inventory

func (*Transport) InvalidateToken

func (t *Transport) InvalidateToken() error

InvalidateToken revokes the current bearer token at the Jamf Pro API and clears the local cache. The next request triggers a full re-authentication.

func (*Transport) KeepAliveToken

func (t *Transport) KeepAliveToken() error

KeepAliveToken extends the current bearer token lifetime without re-auth. Use before long-running operations to prevent mid-operation token expiry.

func (*Transport) Patch

func (t *Transport) Patch(ctx context.Context, path string, body any, headers map[string]string, result any) (*interfaces.Response, error)

Patch executes a PATCH request.

func (*Transport) Post

func (t *Transport) Post(ctx context.Context, path string, body any, headers map[string]string, result any) (*interfaces.Response, error)

Post executes a POST request with JSON body.

func (*Transport) PostForm

func (t *Transport) PostForm(ctx context.Context, path string, formData map[string]string, headers map[string]string, result any) (*interfaces.Response, error)

PostForm executes a POST request with form-urlencoded data.

func (*Transport) PostMultipart

func (t *Transport) PostMultipart(ctx context.Context, path string, fileField string, fileName string, fileReader io.Reader, fileSize int64, formFields map[string]string, headers map[string]string, progressCallback interfaces.MultipartProgressCallback, result any) (*interfaces.Response, error)

PostMultipart executes a POST request with multipart/form-data.

func (*Transport) PostWithQuery

func (t *Transport) PostWithQuery(ctx context.Context, path string, rsqlQuery map[string]string, body any, headers map[string]string, result any) (*interfaces.Response, error)

PostWithQuery executes a POST request with both body and query parameters.

func (*Transport) Put

func (t *Transport) Put(ctx context.Context, path string, body any, headers map[string]string, result any) (*interfaces.Response, error)

Put executes a PUT request.

func (*Transport) RSQLBuilder

func (t *Transport) RSQLBuilder() interfaces.RSQLFilterBuilder

RSQLBuilder returns a new RSQL filter expression builder. Pass the Build() result as rsqlQuery["filter"] to filter endpoint results.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL