iotservice

package
v0.0.0-...-3c60561 Latest Latest
Warning

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

Go to latest
Published: Mar 28, 2024 License: MIT Imports: 21 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FromAMQPMessage

func FromAMQPMessage(msg *amqp.Message) *common.Message

FromAMQPMessage converts a amqp.Message into common.Message.

Exported to use with a custom stream when devices telemetry is routed for example to an EventhHub instance.

func ParseConnectionString

func ParseConnectionString(cs string) (*common.SharedAccessKey, error)

Types

type AckType

type AckType string

AckType is event feedback acknowledgement type.

const (
	// AckNone no feedback.
	AckNone AckType = "none"

	// AckPositive receive a feedback message if the message was completed.
	AckPositive AckType = "positive"

	// AckNegative receive a feedback message if the message expired
	// (or maximum delivery count was reached) without being completed by the device.
	AckNegative AckType = "negative"

	// AckFull both positive and negative.
	AckFull AckType = "full"
)

type AuthType

type AuthType string

AuthType is device authentication type.

const (
	// AuthSAS uses symmetric keys to sign requests.
	AuthSAS AuthType = "sas"

	// AuthSelfSigned self signed certificate with a thumbprint.
	AuthSelfSigned AuthType = "selfSigned"

	// AuthCA certificate signed by a registered certificate authority.
	AuthCA AuthType = "certificateAuthority"
)

type Authentication

type Authentication struct {
	SymmetricKey   *SymmetricKey   `json:"symmetricKey,omitempty"`
	X509Thumbprint *X509Thumbprint `json:"x509Thumbprint,omitempty"`
	Type           AuthType        `json:"type,omitempty"`
}

type BadRequestError

type BadRequestError struct {
	Message          string `json:"Message"`
	ExceptionMessage string `json:"ExceptionMessage"`
}

func (*BadRequestError) Error

func (e *BadRequestError) Error() string

type BulkError

type BulkError struct {
	DeviceID    string `json:"deviceId"`
	ErrorCode   uint   `json:"errorCode"`
	ErrorStatus string `json:"errorStatus"`
}

type BulkResult

type BulkResult struct {
	IsSuccessful bool         `json:"isSuccessful"`
	Errors       []*BulkError `json:"errors"`

	// TODO: figure out the structure of a warning
	Warnings []interface{} `json:"warnings"`
}

type CallDigitalTwinOption

type CallDigitalTwinOption func(q url.Values)

func WithCallDigitalTwinConnectTimeout

func WithCallDigitalTwinConnectTimeout(seconds int) CallDigitalTwinOption

func WithCallDigitalTwinResponseTimeout

func WithCallDigitalTwinResponseTimeout(seconds int) CallDigitalTwinOption

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client is IoT Hub service client.

func New

func New(sak *common.SharedAccessKey, opts ...ClientOption) (*Client, error)

New creates new iothub service client.

func NewFromConnectionString

func NewFromConnectionString(cs string, opts ...ClientOption) (*Client, error)

func (*Client) ApplyConfigurationContentOnDevice

func (c *Client) ApplyConfigurationContentOnDevice(
	ctx context.Context,
	deviceID string,
	content *ConfigurationContent,
) error

func (*Client) CallDeviceMethod

func (c *Client) CallDeviceMethod(
	ctx context.Context,
	deviceID string,
	call *MethodCall,
) (*MethodResult, error)

func (*Client) CallDigitalTwin

func (c *Client) CallDigitalTwin(ctx context.Context,
	digitalTwinID, command string, payload []byte, opts ...CallDigitalTwinOption,
) (int, map[string]interface{}, error)

func (*Client) CallDigitalTwinComponent

func (c *Client) CallDigitalTwinComponent(ctx context.Context,
	digitalTwinID, component, command string, payload []byte, opts ...CallDigitalTwinOption,
) (int, map[string]interface{}, error)

func (*Client) CallModuleMethod

func (c *Client) CallModuleMethod(
	ctx context.Context,
	deviceID,
	moduleID string,
	call *MethodCall,
) (*MethodResult, error)

func (*Client) CancelJob

func (c *Client) CancelJob(ctx context.Context, jobID string) (map[string]interface{}, error)

func (*Client) CancelJobV2

func (c *Client) CancelJobV2(ctx context.Context, jobID string) (*JobV2, error)

func (*Client) Close

func (c *Client) Close() error

Close closes transport.

func (*Client) CreateConfiguration

func (c *Client) CreateConfiguration(ctx context.Context, config *Configuration) (
	*Configuration, error,
)

CreateConfiguration adds the given configuration to the registry.

func (*Client) CreateDevice

func (c *Client) CreateDevice(ctx context.Context, device *Device) (*Device, error)

CreateDevice creates a new device.

func (*Client) CreateDevices

func (c *Client) CreateDevices(
	ctx context.Context, devices []*Device,
) (*BulkResult, error)

CreateDevices creates array of devices in bulk mode.

func (*Client) CreateJob

func (c *Client) CreateJob(ctx context.Context, job *Job) (map[string]interface{}, error)

CreateJob creates import / export jobs.

https://docs.microsoft.com/en-us/azure/iot-hub/iot-hub-bulk-identity-mgmt#get-the-container-sas-uri

func (*Client) CreateJobV2

func (c *Client) CreateJobV2(ctx context.Context, job *JobV2) (*JobV2, error)

func (*Client) CreateModule

func (c *Client) CreateModule(ctx context.Context, module *Module) (*Module, error)

CreateModule adds the given module to the registry.

func (*Client) DeleteConfiguration

func (c *Client) DeleteConfiguration(ctx context.Context, config *Configuration) error

DeleteConfiguration removes the given configuration from the registry.

func (*Client) DeleteDevice

func (c *Client) DeleteDevice(ctx context.Context, device *Device) error

DeleteDevice deletes the named device.

func (*Client) DeleteDevices

func (c *Client) DeleteDevices(
	ctx context.Context, devices []*Device, force bool,
) (*BulkResult, error)

DeleteDevices deletes array of devices in bulk mode.

func (*Client) DeleteModule

func (c *Client) DeleteModule(ctx context.Context, module *Module) error

DeleteModule removes the named device module.

func (*Client) DeviceConnectionString

func (c *Client) DeviceConnectionString(device *Device, secondary bool) (string, error)

DeviceConnectionString builds up a connection string for the given device.

func (*Client) DeviceSAS

func (c *Client) DeviceSAS(
	device *Device, resource string, duration time.Duration, secondary bool,
) (string, error)

DeviceSAS generates a GenerateToken token for the named device.

Resource shouldn't include hostname.

func (*Client) DeviceStats

func (c *Client) DeviceStats(ctx context.Context) (*DeviceStats, error)

DeviceStats retrieves the device registry statistic.

func (*Client) GetConfiguration

func (c *Client) GetConfiguration(ctx context.Context, configID string) (
	*Configuration, error,
)

GetConfiguration gets the named configuration from the registry.

func (*Client) GetDevice

func (c *Client) GetDevice(ctx context.Context, deviceID string) (*Device, error)

GetDevice retrieves the named device.

func (*Client) GetDeviceTwin

func (c *Client) GetDeviceTwin(ctx context.Context, deviceID string) (*Twin, error)

GetDeviceTwin retrieves the named twin device from the registry.

func (*Client) GetDigitalTwin

func (c *Client) GetDigitalTwin(
	ctx context.Context, digitalTwinID string,
) (map[string]interface{}, error)

func (*Client) GetJob

func (c *Client) GetJob(ctx context.Context, jobID string) (map[string]interface{}, error)

func (*Client) GetJobV2

func (c *Client) GetJobV2(ctx context.Context, jobID string) (*JobV2, error)

func (*Client) GetModule

func (c *Client) GetModule(ctx context.Context, deviceID, moduleID string) (
	*Module, error,
)

GetModule retrieves the named module.

func (*Client) GetModuleTwin

func (c *Client) GetModuleTwin(ctx context.Context, deviceID, moduleID string) (
	*ModuleTwin, error,
)

GetModuleTwin retrieves the named module's path.

func (*Client) HostName

func (c *Client) HostName() string

HostName returns service's hostname.

func (*Client) ListConfigurations

func (c *Client) ListConfigurations(ctx context.Context) ([]*Configuration, error)

ListConfigurations gets all available configurations from the registry.

func (*Client) ListDevices

func (c *Client) ListDevices(ctx context.Context) ([]*Device, error)

ListDevices lists all registered devices.

func (*Client) ListJobs

func (c *Client) ListJobs(ctx context.Context) ([]map[string]interface{}, error)

ListJobs lists all running jobs.

func (*Client) ListModules

func (c *Client) ListModules(ctx context.Context, deviceID string) ([]*Module, error)

ListModules list all the registered modules on the named device.

func (*Client) ModuleConnectionString

func (c *Client) ModuleConnectionString(module *Module, secondary bool) (string, error)

func (*Client) PurgeQueue

func (c *Client) PurgeQueue(ctx context.Context, deviceID string) (*PurgeMessageQueueResult, error)

func (*Client) QueryDevices

func (c *Client) QueryDevices(
	ctx context.Context, query string, fn func(v map[string]interface{}) error,
) error

func (*Client) QueryJobsV2

func (c *Client) QueryJobsV2(
	ctx context.Context, q *JobV2Query, fn func(*JobV2) error,
) error

func (*Client) SendEvent

func (c *Client) SendEvent(
	ctx context.Context,
	deviceID string,
	payload []byte,
	opts ...SendOption,
) error

SendEvent sends the given cloud-to-device message and returns its id. Panics when event is nil.

func (*Client) ServiceStats

func (c *Client) ServiceStats(ctx context.Context) (*ServiceStats, error)

func (*Client) SubscribeEvents

func (c *Client) SubscribeEvents(ctx context.Context, fn EventHandler) error

SubscribeEvents subscribes to D2C events.

Event handler is blocking, handle asynchronous processing on your own.

func (*Client) SubscribeFeedback

func (c *Client) SubscribeFeedback(ctx context.Context, fn FeedbackHandler) error

SubscribeFeedback subscribes to feedback of messages that ack was requested.

func (*Client) SubscribeFileNotifications

func (c *Client) SubscribeFileNotifications(
	ctx context.Context,
	fn FileNotificationHandler,
) error

SubscribeFileNotifications subscribes to file notifications.

The feature has to be enabled in the console.

func (*Client) UpdateConfiguration

func (c *Client) UpdateConfiguration(ctx context.Context, config *Configuration) (
	*Configuration, error,
)

UpdateConfiguration updates the given configuration in the registry.

func (*Client) UpdateDevice

func (c *Client) UpdateDevice(ctx context.Context, device *Device) (*Device, error)

UpdateDevice updates the named device.

func (*Client) UpdateDeviceTwin

func (c *Client) UpdateDeviceTwin(ctx context.Context, twin *Twin) (*Twin, error)

UpdateDeviceTwin updates the named twin desired properties.

func (*Client) UpdateDeviceTwins

func (c *Client) UpdateDeviceTwins(
	ctx context.Context, devices []*Device, force bool,
) (*BulkResult, error)

UpdateDeviceTwins updates an array of device twins or tags in bulk mode.

func (*Client) UpdateDevices

func (c *Client) UpdateDevices(
	ctx context.Context, devices []*Device, force bool,
) (*BulkResult, error)

UpdateDevices updates array of devices in bulk mode.

func (*Client) UpdateDigitalTwin

func (c *Client) UpdateDigitalTwin(
	ctx context.Context, digitalTwinID string, patch []map[string]interface{},
) (map[string]interface{}, error)

func (*Client) UpdateModule

func (c *Client) UpdateModule(ctx context.Context, module *Module) (*Module, error)

UpdateModule updates the given module.

func (*Client) UpdateModuleTwin

func (c *Client) UpdateModuleTwin(ctx context.Context, twin *ModuleTwin) (
	*ModuleTwin, error,
)

UpdateModuleTwin updates the named module twin's desired attributes.

type ClientOption

type ClientOption func(c *Client)

ClientOption is a client configuration option.

func WithHTTPClient

func WithHTTPClient(client *http.Client) ClientOption

WithHTTPClient changes default http rest client.

func WithLogger

func WithLogger(l logger.Logger) ClientOption

WithLogger sets client logger.

func WithTLSConfig

func WithTLSConfig(config *tls.Config) ClientOption

WithTLSConfig sets TLS config that's used by REST HTTP and AMQP clients.

type Configuration

type Configuration struct {
	ID                 string                `json:"id,omitempty"`
	SchemaVersion      string                `json:"schemaVersion,omitempty"`
	Labels             map[string]string     `json:"labels,omitempty"`
	Content            *ConfigurationContent `json:"content,omitempty"`
	TargetCondition    string                `json:"targetCondition,omitempty"`
	CreatedTimeUTC     *time.Time            `json:"createdTimeUtc,omitempty"`
	LastUpdatedTimeUTC *time.Time            `json:"lastUpdatedTimeUtc,omitempty"`
	Priority           uint                  `json:"priority,omitempty"`
	SystemMetrics      *ConfigurationMetrics `json:"systemMetrics,omitempty"`
	Metrics            *ConfigurationMetrics `json:"metrics,omitempty"`
	ETag               string                `json:"etag,omitempty"`
}

type ConfigurationContent

type ConfigurationContent struct {
	ModulesContent map[string]interface{} `json:"modulesContent,omitempty"`
	DeviceContent  map[string]interface{} `json:"deviceContent,omitempty"`
}

type ConfigurationMetrics

type ConfigurationMetrics struct {
	Results map[string]uint   `json:"results,omitempty"`
	Queries map[string]string `json:"queries,omitempty"`
}

type ConnectionState

type ConnectionState string
const (
	Connected    ConnectionState = "Connected"
	Disconnected ConnectionState = "Disconnected"
)

type Deployment

type Deployment struct {
	ID              string                `json:"id"`
	Labels          map[string]string     `json:"labels"`
	Priority        uint                  `json:"priority"`
	TargetCondition string                `json:"targetCondition"`
	Content         *DeploymentContent    `json:"content"`
	Metrics         *ConfigurationMetrics `json:"metrics"`
	ETag            string                `json:"etag"`
}

type DeploymentContent

type DeploymentContent struct {
	ModulesContent map[string]interface{} `json:"modulesContent"`
}

type Device

type Device struct {
	DeviceID                   string                 `json:"deviceId,omitempty"`
	GenerationID               string                 `json:"generationId,omitempty"`
	ETag                       string                 `json:"etag,omitempty"`
	ConnectionState            ConnectionState        `json:"connectionState,omitempty"`
	Status                     DeviceStatus           `json:"status,omitempty"`
	StatusReason               string                 `json:"statusReason,omitempty"`
	ConnectionStateUpdatedTime *MicrosoftTime         `json:"connectionStateUpdatedTime,omitempty"`
	StatusUpdatedTime          *MicrosoftTime         `json:"statusUpdatedTime,omitempty"`
	LastActivityTime           *MicrosoftTime         `json:"lastActivityTime,omitempty"`
	CloudToDeviceMessageCount  uint                   `json:"cloudToDeviceMessageCount,omitempty"`
	Authentication             *Authentication        `json:"authentication,omitempty"`
	Capabilities               map[string]interface{} `json:"capabilities,omitempty"`
	Tags                       map[string]interface{} `json:"tags,omitempty"`
	Properties                 *Properties            `json:"properties,omitempty"`
}

type DeviceMethodParams

type DeviceMethodParams struct {
	MethodName       string      `json:"methodName"`
	Payload          interface{} `json:"payload"`
	TimeoutInSeconds uint        `json:"timeoutInSeconds"`
}

type DeviceStats

type DeviceStats struct {
	DisabledDeviceCount uint `json:"disabledDeviceCount,omitempty"`
	EnabledDeviceCount  uint `json:"enabledDeviceCount,omitempty"`
	TotalDeviceCount    uint `json:"totalDeviceCount,omitempty"`
}

type DeviceStatus

type DeviceStatus string
const (
	Enabled  DeviceStatus = "enabled"
	Disabled DeviceStatus = "disabled"
)

type Event

type Event struct {
	*common.Message
}

Event is a device-to-cloud message.

type EventHandler

type EventHandler func(e *Event) error

EventHandler handles incoming cloud-to-device events.

type Feedback

type Feedback struct {
	OriginalMessageID  string    `json:"originalMessageId"`
	Description        string    `json:"description"`
	DeviceGenerationID string    `json:"deviceGenerationId"`
	DeviceID           string    `json:"deviceId"`
	EnqueuedTimeUTC    time.Time `json:"enqueuedTimeUtc"`
	StatusCode         string    `json:"statusCode"`
}

Feedback is message feedback.

type FeedbackHandler

type FeedbackHandler func(f *Feedback) error

FeedbackHandler handles message feedback.

type FileNotification

type FileNotification struct {
	DeviceID        string    `json:"deviceId"`
	BlobURI         string    `json:"blobUri"`
	BlobName        string    `json:"blobName"`
	LastUpdatedTime time.Time `json:"lastUpdatedTime"`
	BlobSizeInBytes int64     `json:"blobSizeInBytes"`
	EnqueuedTime    time.Time `json:"enqueuedTimeUtc"`
}

FileNotification is emitted once a blob file is uploaded to the hub.

type FileNotificationHandler

type FileNotificationHandler func(event *FileNotification) error

FileNotificationHandler handles file upload notifications.

type Job

type Job struct {
	Type                   JobType `json:"type"`
	InputBlobContainerURI  string  `json:"inputBlobContainerUri"`
	OutputBlobContainerURI string  `json:"outputBlobContainerUri,omitempty"`
	ExcludeKeysInExport    bool    `json:"excludeKeysInExport"`
}

type JobType

type JobType string
const (
	JobExport JobType = "export"
	JobImport JobType = "import"
)

type JobV2

type JobV2 struct {
	JobID  string      `json:"jobId"`
	Type   JobV2Type   `json:"type"`
	Status JobV2Status `json:"status,omitempty"`

	CloudToDeviceMethod *DeviceMethodParams `json:"cloudToDeviceMethod,omitempty"`
	UpdateTwin          interface{}         `json:"updateTwin,omitempty"`

	QueryCondition            string    `json:"queryCondition"`
	StartTime                 time.Time `json:"startTime"`
	MaxExecutionTimeInSeconds uint      `json:"maxExecutionTimeInSeconds"`
}

type JobV2Query

type JobV2Query struct {
	Type   JobV2Type
	Status JobV2Status
}

type JobV2Status

type JobV2Status string
const (
	JobStatusUnknown   JobV2Status = "unknown"
	JobStatusQueued    JobV2Status = "queued"
	JobStatusScheduled JobV2Status = "scheduled"
	JobStatusRunning   JobV2Status = "running"
	JobStatusCancelled JobV2Status = "cancelled"
	JobStatusCompleted JobV2Status = "completed"
)

type JobV2Type

type JobV2Type string
const (
	JobTypeUnknown      JobV2Type = "unknown"
	JobTypeUpdateTwin   JobV2Type = "scheduleUpdateTwin"
	JobTypeDeviceMethod JobV2Type = "scheduleDeviceMethod"
)

type MethodCall

type MethodCall struct {
	MethodName      string                 `json:"methodName,omitempty"`
	ConnectTimeout  uint                   `json:"connectTimeoutInSeconds,omitempty"`
	ResponseTimeout uint                   `json:"responseTimeoutInSeconds,omitempty"`
	Payload         map[string]interface{} `json:"payload,omitempty"`
}

type MethodResult

type MethodResult struct {
	Status  int                    `json:"status,omitempty"`
	Payload map[string]interface{} `json:"payload,omitempty"`
}

type MicrosoftTime

type MicrosoftTime struct {
	time.Time
}

MicrosoftTime is a hack to parse time json attributes that don't follow RFC3339 and don't put timezone at the end of timestamp.

func (*MicrosoftTime) UnmarshalJSON

func (t *MicrosoftTime) UnmarshalJSON(b []byte) error

type Module

type Module struct {
	ModuleID                   string          `json:"moduleId,omitempty"`
	DeviceID                   string          `json:"deviceId,omitempty"`
	GenerationID               string          `json:"generationId,omitempty"`
	ETag                       string          `json:"etag,omitempty"`
	ConnectionState            ConnectionState `json:"connectionState,omitempty"`
	ConnectionStateUpdatedTime *MicrosoftTime  `json:"connectionStateUpdatedTime,omitempty"`
	LastActivityTime           *MicrosoftTime  `json:"lastActivityTime,omitempty"`
	CloudToDeviceMessageCount  uint            `json:"cloudToDeviceMessageCount,omitempty"`
	Authentication             *Authentication `json:"authentication,omitempty"`
	ManagedBy                  string          `json:"managedBy,omitempty"`
}

type ModuleTwin

type ModuleTwin struct {
	DeviceID           string                 `json:"deviceId,omitempty"`
	ModuleID           string                 `json:"moduleId,omitempty"`
	ETag               string                 `json:"etag,omitempty"`
	DeviceETag         string                 `json:"deviceEtag,omitempty"`
	Status             DeviceStatus           `json:"status,omitempty"`
	StatusUpdateTime   *MicrosoftTime         `json:"statusUpdateTime,omitempty"`
	ConnectionState    ConnectionState        `json:"connectionState,omitempty"`
	LastActivityTime   *MicrosoftTime         `json:"lastActivityTime,omitempty"`
	AuthenticationType string                 `json:"authenticationType,omitempty"`
	X509Thumbprint     *X509Thumbprint        `json:"x509Thumbprint,omitempty"`
	Version            uint                   `json:"version,omitempty"`
	Tags               map[string]interface{} `json:"tags,omitempty"`
	Properties         *Properties            `json:"properties,omitempty"`
}

type Properties

type Properties struct {
	Desired  map[string]interface{} `json:"desired,omitempty"`
	Reported map[string]interface{} `json:"reported,omitempty"`
}

type PurgeMessageQueueResult

type PurgeMessageQueueResult struct {
	DeviceID            string `json:"deviceID,omitempty"`
	ModuleID            string `json:"moduleID,omitempty"`
	TotalMessagesPurged int    `json:"totalMessagesPurged,omitempty"`
}

type RequestError

type RequestError struct {
	Code int
	Body []byte
}

RequestError is an API request error.

Response body is already read out to Body attribute, so there's no need read it manually and call `e.Res.Body.Close()`

func (*RequestError) Error

func (e *RequestError) Error() string

type SendOption

type SendOption func(msg *common.Message) error

SendOption is a send option.

func WithSendAck

func WithSendAck(ack AckType) SendOption

WithSendAck sets message confirmation type.

func WithSendCorrelationID

func WithSendCorrelationID(cid string) SendOption

WithSendCorrelationID sets correlation id.

func WithSendExpiryTime

func WithSendExpiryTime(t time.Time) SendOption

WithSendExpiryTime sets message expiration time.

func WithSendMessageID

func WithSendMessageID(mid string) SendOption

WithSendMessageID sets message id.

func WithSendProperties

func WithSendProperties(m map[string]string) SendOption

WithSendProperties same as `WithSendProperty` but accepts map of keys and values.

func WithSendProperty

func WithSendProperty(k, v string) SendOption

WithSendProperty sets a message property.

func WithSendUserID

func WithSendUserID(uid string) SendOption

WithSendUserID sets user id.

type ServiceStats

type ServiceStats struct {
	ConnectedDeviceCount uint `json:"connectedDeviceCount"`
}

type SymmetricKey

type SymmetricKey struct {
	PrimaryKey   string `json:"primaryKey,omitempty"`
	SecondaryKey string `json:"secondaryKey,omitempty"`
}

type Twin

type Twin struct {
	DeviceID                  string                 `json:"deviceId,omitempty"`
	ETag                      string                 `json:"etag,omitempty"`
	DeviceETag                string                 `json:"deviceEtag,omitempty"`
	Status                    DeviceStatus           `json:"status,omitempty"`
	StatusReason              string                 `json:"statusReason,omitempty"`
	StatusUpdateTime          *MicrosoftTime         `json:"statusUpdateTime,omitempty"`
	ConnectionState           ConnectionState        `json:"connectionState,omitempty"`
	LastActivityTime          *MicrosoftTime         `json:"lastActivityTime,omitempty"`
	CloudToDeviceMessageCount uint                   `json:"cloudToDeviceMessageCount,omitempty"`
	AuthenticationType        string                 `json:"authenticationType,omitempty"`
	X509Thumbprint            *X509Thumbprint        `json:"x509Thumbprint,omitempty"`
	Version                   int                    `json:"version,omitempty"`
	Tags                      map[string]interface{} `json:"tags,omitempty"`
	Properties                *Properties            `json:"properties,omitempty"`
	Capabilities              map[string]interface{} `json:"capabilities,omitempty"`
}

type X509Thumbprint

type X509Thumbprint struct {
	PrimaryThumbprint   string `json:"primaryThumbprint,omitempty"`
	SecondaryThumbprint string `json:"secondaryThumbprint,omitempty"`
}

Jump to

Keyboard shortcuts

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