Repository: hashicorp/nomad
File: api/keyring.go (Go)

Code before:
	RootKeyStatePrepublished              = "prepublished"
)

// List lists all the keyring metadata
func (k *Keyring) List(q *QueryOptions) ([]*RootKeyMeta, *QueryMeta, error) {
	var resp []*RootKeyMeta
	qm, err := k.client.query("/v1/operator/keyring/keys", &resp, q)
	if err != nil {
		return nil, nil, err
	}
	return resp, qm, nil
}

// Delete deletes a specific inactive key from the keyring
func (k *Keyring) Delete(opts *KeyringDeleteOptions, w *WriteOptions) (*WriteMeta, error) {
	wm, err := k.client.delete(fmt.Sprintf("/v1/operator/keyring/key/%v?force=%v",
		url.PathEscape(opts.KeyID), strconv.FormatBool(opts.Force)), nil, nil, w)
	return wm, err
}

// KeyringDeleteOptions are parameters for the Delete API
type KeyringDeleteOptions struct {
	KeyID string // UUID
	Force bool
}

// Rotate requests a key rotation
func (k *Keyring) Rotate(opts *KeyringRotateOptions, w *WriteOptions) (*RootKeyMeta, *WriteMeta, error) {
	qp := url.Values{}
	if opts != nil {
		if opts.Algorithm != "" {
			qp.Set("algo", string(opts.Algorithm))
		}
		if opts.Full {
			qp.Set("full", "true")
		}
		if opts.PublishTime > 0 {
			qp.Set("publish_time", fmt.Sprintf("%d", opts.PublishTime))
		}
	}
	resp := &struct{ Key *RootKeyMeta }{}
	wm, err := k.client.put("/v1/operator/keyring/rotate?"+qp.Encode(), nil, resp, w)
	return resp.Key, wm, err
}

// KeyringRotateOptions are parameters for the Rotate API
type KeyringRotateOptions struct {
	Full        bool
	Algorithm   EncryptionAlgorithm
	PublishTime int64
}

Review comment (suggestion):
I know not many options have this, but could we add a comment to this explaining what the force boolean does? It means external tool developers have an easy time knowing and understanding.

Code after:
	RootKeyStatePrepublished              = "prepublished"
)

// List lists all the keyring metadata
func (k *Keyring) List(q *QueryOptions) ([]*RootKeyMeta, *QueryMeta, error) {
	var resp []*RootKeyMeta
	qm, err := k.client.query("/v1/operator/keyring/keys", &resp, q)
	if err != nil {
		return nil, nil, err
	}
	return resp, qm, nil
}

// Delete deletes a specific inactive key from the keyring
func (k *Keyring) Delete(opts *KeyringDeleteOptions, w *WriteOptions) (*WriteMeta, error) {
	wm, err := k.client.delete(fmt.Sprintf("/v1/operator/keyring/key/%v?force=%v",
		url.PathEscape(opts.KeyID), strconv.FormatBool(opts.Force)), nil, nil, w)
	return wm, err
}

// KeyringDeleteOptions are parameters for the Delete API
type KeyringDeleteOptions struct {
	KeyID string // UUID
	// Force can be used to force deletion of a root keyring that was used to encrypt
	// an existing variable or to sign a workload identity
	Force bool
}

// Rotate requests a key rotation
func (k *Keyring) Rotate(opts *KeyringRotateOptions, w *WriteOptions) (*RootKeyMeta, *WriteMeta, error) {
	qp := url.Values{}
	if opts != nil {
		if opts.Algorithm != "" {
			qp.Set("algo", string(opts.Algorithm))
		}
		if opts.Full {
			qp.Set("full", "true")
		}
		if opts.PublishTime > 0 {
			qp.Set("publish_time", fmt.Sprintf("%d", opts.PublishTime))
		}
	}
	resp := &struct{ Key *RootKeyMeta }{}
	wm, err := k.client.put("/v1/operator/keyring/rotate?"+qp.Encode(), nil, resp, w)
	return resp.Key, wm, err
}

// KeyringRotateOptions are parameters for the Rotate API
type KeyringRotateOptions struct {
	Full        bool
	Algorithm   EncryptionAlgorithm