feat: reimplement influx secret CLI command (#125)

* refactor: rename `getPassword` to `getSecret`
This commit is contained in:
Dane Strandboge
2021-06-21 13:33:51 -05:00
committed by GitHub
parent a4fdefc392
commit 23e73e9146
21 changed files with 1777 additions and 20 deletions

488
api/api_secrets.gen.go Normal file
View File

@ -0,0 +1,488 @@
/*
* Subset of Influx API covered by Influx CLI
*
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* API version: 2.0.0
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package api
import (
_context "context"
_ioutil "io/ioutil"
_nethttp "net/http"
_neturl "net/url"
"strings"
)
// Linger please
var (
_ _context.Context
)
type SecretsApi interface {
/*
* GetOrgsIDSecrets List all secret keys for an organization
* @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
* @param orgID The organization ID.
* @return ApiGetOrgsIDSecretsRequest
*/
GetOrgsIDSecrets(ctx _context.Context, orgID string) ApiGetOrgsIDSecretsRequest
/*
* GetOrgsIDSecretsExecute executes the request
* @return SecretKeysResponse
*/
GetOrgsIDSecretsExecute(r ApiGetOrgsIDSecretsRequest) (SecretKeysResponse, error)
/*
* PatchOrgsIDSecrets Update secrets in an organization
* @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
* @param orgID The organization ID.
* @return ApiPatchOrgsIDSecretsRequest
*/
PatchOrgsIDSecrets(ctx _context.Context, orgID string) ApiPatchOrgsIDSecretsRequest
/*
* PatchOrgsIDSecretsExecute executes the request
*/
PatchOrgsIDSecretsExecute(r ApiPatchOrgsIDSecretsRequest) error
/*
* PostOrgsIDSecrets Delete secrets from an organization
* @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
* @param orgID The organization ID.
* @return ApiPostOrgsIDSecretsRequest
*/
PostOrgsIDSecrets(ctx _context.Context, orgID string) ApiPostOrgsIDSecretsRequest
/*
* PostOrgsIDSecretsExecute executes the request
*/
PostOrgsIDSecretsExecute(r ApiPostOrgsIDSecretsRequest) error
}
// SecretsApiService SecretsApi service
type SecretsApiService service
type ApiGetOrgsIDSecretsRequest struct {
ctx _context.Context
ApiService SecretsApi
orgID string
zapTraceSpan *string
}
func (r ApiGetOrgsIDSecretsRequest) OrgID(orgID string) ApiGetOrgsIDSecretsRequest {
r.orgID = orgID
return r
}
func (r ApiGetOrgsIDSecretsRequest) GetOrgID() string {
return r.orgID
}
func (r ApiGetOrgsIDSecretsRequest) ZapTraceSpan(zapTraceSpan string) ApiGetOrgsIDSecretsRequest {
r.zapTraceSpan = &zapTraceSpan
return r
}
func (r ApiGetOrgsIDSecretsRequest) GetZapTraceSpan() *string {
return r.zapTraceSpan
}
func (r ApiGetOrgsIDSecretsRequest) Execute() (SecretKeysResponse, error) {
return r.ApiService.GetOrgsIDSecretsExecute(r)
}
/*
* GetOrgsIDSecrets List all secret keys for an organization
* @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
* @param orgID The organization ID.
* @return ApiGetOrgsIDSecretsRequest
*/
func (a *SecretsApiService) GetOrgsIDSecrets(ctx _context.Context, orgID string) ApiGetOrgsIDSecretsRequest {
return ApiGetOrgsIDSecretsRequest{
ApiService: a,
ctx: ctx,
orgID: orgID,
}
}
/*
* Execute executes the request
* @return SecretKeysResponse
*/
func (a *SecretsApiService) GetOrgsIDSecretsExecute(r ApiGetOrgsIDSecretsRequest) (SecretKeysResponse, error) {
var (
localVarHTTPMethod = _nethttp.MethodGet
localVarPostBody interface{}
localVarFormFileName string
localVarFileName string
localVarFileBytes []byte
localVarReturnValue SecretKeysResponse
)
localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "SecretsApiService.GetOrgsIDSecrets")
if err != nil {
return localVarReturnValue, GenericOpenAPIError{error: err.Error()}
}
localVarPath := localBasePath + "/orgs/{orgID}/secrets"
localVarPath = strings.Replace(localVarPath, "{"+"orgID"+"}", _neturl.PathEscape(parameterToString(r.orgID, "")), -1)
localVarHeaderParams := make(map[string]string)
localVarQueryParams := _neturl.Values{}
localVarFormParams := _neturl.Values{}
// to determine the Content-Type header
localVarHTTPContentTypes := []string{}
// set Content-Type header
localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes)
if localVarHTTPContentType != "" {
localVarHeaderParams["Content-Type"] = localVarHTTPContentType
}
// to determine the Accept header
localVarHTTPHeaderAccepts := []string{"application/json"}
// set Accept header
localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts)
if localVarHTTPHeaderAccept != "" {
localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept
}
if r.zapTraceSpan != nil {
localVarHeaderParams["Zap-Trace-Span"] = parameterToString(*r.zapTraceSpan, "")
}
req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes)
if err != nil {
return localVarReturnValue, err
}
localVarHTTPResponse, err := a.client.callAPI(req)
if err != nil || localVarHTTPResponse == nil {
return localVarReturnValue, err
}
if localVarHTTPResponse.StatusCode >= 300 {
body, err := GunzipIfNeeded(localVarHTTPResponse)
if err != nil {
body.Close()
return localVarReturnValue, err
}
localVarBody, err := _ioutil.ReadAll(body)
body.Close()
if err != nil {
return localVarReturnValue, err
}
newErr := GenericOpenAPIError{
body: localVarBody,
error: localVarHTTPResponse.Status,
}
var v Error
err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
if err != nil {
newErr.error = err.Error()
return localVarReturnValue, newErr
}
newErr.model = &v
return localVarReturnValue, newErr
}
body, err := GunzipIfNeeded(localVarHTTPResponse)
if err != nil {
body.Close()
return localVarReturnValue, err
}
localVarBody, err := _ioutil.ReadAll(body)
body.Close()
if err != nil {
return localVarReturnValue, err
}
err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
if err != nil {
newErr := GenericOpenAPIError{
body: localVarBody,
error: err.Error(),
}
return localVarReturnValue, newErr
}
return localVarReturnValue, nil
}
type ApiPatchOrgsIDSecretsRequest struct {
ctx _context.Context
ApiService SecretsApi
orgID string
requestBody *map[string]string
zapTraceSpan *string
}
func (r ApiPatchOrgsIDSecretsRequest) OrgID(orgID string) ApiPatchOrgsIDSecretsRequest {
r.orgID = orgID
return r
}
func (r ApiPatchOrgsIDSecretsRequest) GetOrgID() string {
return r.orgID
}
func (r ApiPatchOrgsIDSecretsRequest) RequestBody(requestBody map[string]string) ApiPatchOrgsIDSecretsRequest {
r.requestBody = &requestBody
return r
}
func (r ApiPatchOrgsIDSecretsRequest) GetRequestBody() *map[string]string {
return r.requestBody
}
func (r ApiPatchOrgsIDSecretsRequest) ZapTraceSpan(zapTraceSpan string) ApiPatchOrgsIDSecretsRequest {
r.zapTraceSpan = &zapTraceSpan
return r
}
func (r ApiPatchOrgsIDSecretsRequest) GetZapTraceSpan() *string {
return r.zapTraceSpan
}
func (r ApiPatchOrgsIDSecretsRequest) Execute() error {
return r.ApiService.PatchOrgsIDSecretsExecute(r)
}
/*
* PatchOrgsIDSecrets Update secrets in an organization
* @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
* @param orgID The organization ID.
* @return ApiPatchOrgsIDSecretsRequest
*/
func (a *SecretsApiService) PatchOrgsIDSecrets(ctx _context.Context, orgID string) ApiPatchOrgsIDSecretsRequest {
return ApiPatchOrgsIDSecretsRequest{
ApiService: a,
ctx: ctx,
orgID: orgID,
}
}
/*
* Execute executes the request
*/
func (a *SecretsApiService) PatchOrgsIDSecretsExecute(r ApiPatchOrgsIDSecretsRequest) error {
var (
localVarHTTPMethod = _nethttp.MethodPatch
localVarPostBody interface{}
localVarFormFileName string
localVarFileName string
localVarFileBytes []byte
)
localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "SecretsApiService.PatchOrgsIDSecrets")
if err != nil {
return GenericOpenAPIError{error: err.Error()}
}
localVarPath := localBasePath + "/orgs/{orgID}/secrets"
localVarPath = strings.Replace(localVarPath, "{"+"orgID"+"}", _neturl.PathEscape(parameterToString(r.orgID, "")), -1)
localVarHeaderParams := make(map[string]string)
localVarQueryParams := _neturl.Values{}
localVarFormParams := _neturl.Values{}
if r.requestBody == nil {
return reportError("requestBody is required and must be specified")
}
// to determine the Content-Type header
localVarHTTPContentTypes := []string{"application/json"}
// set Content-Type header
localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes)
if localVarHTTPContentType != "" {
localVarHeaderParams["Content-Type"] = localVarHTTPContentType
}
// to determine the Accept header
localVarHTTPHeaderAccepts := []string{"application/json"}
// set Accept header
localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts)
if localVarHTTPHeaderAccept != "" {
localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept
}
if r.zapTraceSpan != nil {
localVarHeaderParams["Zap-Trace-Span"] = parameterToString(*r.zapTraceSpan, "")
}
// body params
localVarPostBody = r.requestBody
req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes)
if err != nil {
return err
}
localVarHTTPResponse, err := a.client.callAPI(req)
if err != nil || localVarHTTPResponse == nil {
return err
}
if localVarHTTPResponse.StatusCode >= 300 {
body, err := GunzipIfNeeded(localVarHTTPResponse)
if err != nil {
body.Close()
return err
}
localVarBody, err := _ioutil.ReadAll(body)
body.Close()
if err != nil {
return err
}
newErr := GenericOpenAPIError{
body: localVarBody,
error: localVarHTTPResponse.Status,
}
var v Error
err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
if err != nil {
newErr.error = err.Error()
return newErr
}
newErr.model = &v
return newErr
}
return nil
}
type ApiPostOrgsIDSecretsRequest struct {
ctx _context.Context
ApiService SecretsApi
orgID string
secretKeys *SecretKeys
zapTraceSpan *string
}
func (r ApiPostOrgsIDSecretsRequest) OrgID(orgID string) ApiPostOrgsIDSecretsRequest {
r.orgID = orgID
return r
}
func (r ApiPostOrgsIDSecretsRequest) GetOrgID() string {
return r.orgID
}
func (r ApiPostOrgsIDSecretsRequest) SecretKeys(secretKeys SecretKeys) ApiPostOrgsIDSecretsRequest {
r.secretKeys = &secretKeys
return r
}
func (r ApiPostOrgsIDSecretsRequest) GetSecretKeys() *SecretKeys {
return r.secretKeys
}
func (r ApiPostOrgsIDSecretsRequest) ZapTraceSpan(zapTraceSpan string) ApiPostOrgsIDSecretsRequest {
r.zapTraceSpan = &zapTraceSpan
return r
}
func (r ApiPostOrgsIDSecretsRequest) GetZapTraceSpan() *string {
return r.zapTraceSpan
}
func (r ApiPostOrgsIDSecretsRequest) Execute() error {
return r.ApiService.PostOrgsIDSecretsExecute(r)
}
/*
* PostOrgsIDSecrets Delete secrets from an organization
* @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
* @param orgID The organization ID.
* @return ApiPostOrgsIDSecretsRequest
*/
func (a *SecretsApiService) PostOrgsIDSecrets(ctx _context.Context, orgID string) ApiPostOrgsIDSecretsRequest {
return ApiPostOrgsIDSecretsRequest{
ApiService: a,
ctx: ctx,
orgID: orgID,
}
}
/*
* Execute executes the request
*/
func (a *SecretsApiService) PostOrgsIDSecretsExecute(r ApiPostOrgsIDSecretsRequest) error {
var (
localVarHTTPMethod = _nethttp.MethodPost
localVarPostBody interface{}
localVarFormFileName string
localVarFileName string
localVarFileBytes []byte
)
localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "SecretsApiService.PostOrgsIDSecrets")
if err != nil {
return GenericOpenAPIError{error: err.Error()}
}
localVarPath := localBasePath + "/orgs/{orgID}/secrets/{delete}"
localVarPath = strings.Replace(localVarPath, "{"+"orgID"+"}", _neturl.PathEscape(parameterToString(r.orgID, "")), -1)
localVarHeaderParams := make(map[string]string)
localVarQueryParams := _neturl.Values{}
localVarFormParams := _neturl.Values{}
if r.secretKeys == nil {
return reportError("secretKeys is required and must be specified")
}
// to determine the Content-Type header
localVarHTTPContentTypes := []string{"application/json"}
// set Content-Type header
localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes)
if localVarHTTPContentType != "" {
localVarHeaderParams["Content-Type"] = localVarHTTPContentType
}
// to determine the Accept header
localVarHTTPHeaderAccepts := []string{"application/json"}
// set Accept header
localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts)
if localVarHTTPHeaderAccept != "" {
localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept
}
if r.zapTraceSpan != nil {
localVarHeaderParams["Zap-Trace-Span"] = parameterToString(*r.zapTraceSpan, "")
}
// body params
localVarPostBody = r.secretKeys
req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, localVarFormFileName, localVarFileName, localVarFileBytes)
if err != nil {
return err
}
localVarHTTPResponse, err := a.client.callAPI(req)
if err != nil || localVarHTTPResponse == nil {
return err
}
if localVarHTTPResponse.StatusCode >= 300 {
body, err := GunzipIfNeeded(localVarHTTPResponse)
if err != nil {
body.Close()
return err
}
localVarBody, err := _ioutil.ReadAll(body)
body.Close()
if err != nil {
return err
}
newErr := GenericOpenAPIError{
body: localVarBody,
error: localVarHTTPResponse.Status,
}
var v Error
err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type"))
if err != nil {
newErr.error = err.Error()
return newErr
}
newErr.model = &v
return newErr
}
return nil
}

View File

@ -65,6 +65,8 @@ type APIClient struct {
RestoreApi RestoreApi RestoreApi RestoreApi
SecretsApi SecretsApi
SetupApi SetupApi SetupApi SetupApi
TasksApi TasksApi TasksApi TasksApi
@ -103,6 +105,7 @@ func NewAPIClient(cfg *Configuration) *APIClient {
c.OrganizationsApi = (*OrganizationsApiService)(&c.common) c.OrganizationsApi = (*OrganizationsApiService)(&c.common)
c.QueryApi = (*QueryApiService)(&c.common) c.QueryApi = (*QueryApiService)(&c.common)
c.RestoreApi = (*RestoreApiService)(&c.common) c.RestoreApi = (*RestoreApiService)(&c.common)
c.SecretsApi = (*SecretsApiService)(&c.common)
c.SetupApi = (*SetupApiService)(&c.common) c.SetupApi = (*SetupApiService)(&c.common)
c.TasksApi = (*TasksApiService)(&c.common) c.TasksApi = (*TasksApiService)(&c.common)
c.TelegrafsApi = (*TelegrafsApiService)(&c.common) c.TelegrafsApi = (*TelegrafsApiService)(&c.common)

View File

@ -25,6 +25,10 @@ paths:
$ref: "./openapi/src/common/paths/orgs_orgID_members.yml" $ref: "./openapi/src/common/paths/orgs_orgID_members.yml"
/orgs/{orgID}/members/{userID}: /orgs/{orgID}/members/{userID}:
$ref: "./openapi/src/common/paths/orgs_orgID_members_userID.yml" $ref: "./openapi/src/common/paths/orgs_orgID_members_userID.yml"
/orgs/{orgID}/secrets:
$ref: "./openapi/src/common/paths/orgs_orgID_secrets.yml"
/orgs/{orgID}/secrets/{delete}:
$ref: "./openapi/src/common/paths/orgs_orgID_secrets_delete.yml"
/buckets/{bucketID}/schema/measurements: /buckets/{bucketID}/schema/measurements:
$ref: "./openapi/src/cloud/paths/measurements.yml" $ref: "./openapi/src/cloud/paths/measurements.yml"
/buckets/{bucketID}/schema/measurements/{measurementID}: /buckets/{bucketID}/schema/measurements/{measurementID}:
@ -263,3 +267,9 @@ components:
$ref: "./openapi/src/common/schemas/TemplateKind.yml" $ref: "./openapi/src/common/schemas/TemplateKind.yml"
TemplateEntry: TemplateEntry:
$ref: "./openapi/src/common/schemas/TemplateEntry.yml" $ref: "./openapi/src/common/schemas/TemplateEntry.yml"
SecretKeysResponse:
$ref: "./openapi/src/common/schemas/SecretKeysResponse.yml"
SecretKeys:
$ref: "./openapi/src/common/schemas/SecretKeys.yml"
Secrets:
$ref: "./openapi/src/common/schemas/Secrets.yml"

View File

@ -0,0 +1,113 @@
/*
* Subset of Influx API covered by Influx CLI
*
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* API version: 2.0.0
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package api
import (
"encoding/json"
)
// SecretKeys struct for SecretKeys
type SecretKeys struct {
Secrets *[]string `json:"secrets,omitempty"`
}
// NewSecretKeys instantiates a new SecretKeys object
// This constructor will assign default values to properties that have it defined,
// and makes sure properties required by API are set, but the set of arguments
// will change when the set of required properties is changed
func NewSecretKeys() *SecretKeys {
this := SecretKeys{}
return &this
}
// NewSecretKeysWithDefaults instantiates a new SecretKeys object
// This constructor will only assign default values to properties that have it defined,
// but it doesn't guarantee that properties required by API are set
func NewSecretKeysWithDefaults() *SecretKeys {
this := SecretKeys{}
return &this
}
// GetSecrets returns the Secrets field value if set, zero value otherwise.
func (o *SecretKeys) GetSecrets() []string {
if o == nil || o.Secrets == nil {
var ret []string
return ret
}
return *o.Secrets
}
// GetSecretsOk returns a tuple with the Secrets field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *SecretKeys) GetSecretsOk() (*[]string, bool) {
if o == nil || o.Secrets == nil {
return nil, false
}
return o.Secrets, true
}
// HasSecrets returns a boolean if a field has been set.
func (o *SecretKeys) HasSecrets() bool {
if o != nil && o.Secrets != nil {
return true
}
return false
}
// SetSecrets gets a reference to the given []string and assigns it to the Secrets field.
func (o *SecretKeys) SetSecrets(v []string) {
o.Secrets = &v
}
func (o SecretKeys) MarshalJSON() ([]byte, error) {
toSerialize := map[string]interface{}{}
if o.Secrets != nil {
toSerialize["secrets"] = o.Secrets
}
return json.Marshal(toSerialize)
}
type NullableSecretKeys struct {
value *SecretKeys
isSet bool
}
func (v NullableSecretKeys) Get() *SecretKeys {
return v.value
}
func (v *NullableSecretKeys) Set(val *SecretKeys) {
v.value = val
v.isSet = true
}
func (v NullableSecretKeys) IsSet() bool {
return v.isSet
}
func (v *NullableSecretKeys) Unset() {
v.value = nil
v.isSet = false
}
func NewNullableSecretKeys(val *SecretKeys) *NullableSecretKeys {
return &NullableSecretKeys{value: val, isSet: true}
}
func (v NullableSecretKeys) MarshalJSON() ([]byte, error) {
return json.Marshal(v.value)
}
func (v *NullableSecretKeys) UnmarshalJSON(src []byte) error {
v.isSet = true
return json.Unmarshal(src, &v.value)
}

View File

@ -0,0 +1,149 @@
/*
* Subset of Influx API covered by Influx CLI
*
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* API version: 2.0.0
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package api
import (
"encoding/json"
)
// SecretKeysResponse struct for SecretKeysResponse
type SecretKeysResponse struct {
Secrets *[]string `json:"secrets,omitempty"`
Links *SecretKeysResponseAllOfLinks `json:"links,omitempty"`
}
// NewSecretKeysResponse instantiates a new SecretKeysResponse object
// This constructor will assign default values to properties that have it defined,
// and makes sure properties required by API are set, but the set of arguments
// will change when the set of required properties is changed
func NewSecretKeysResponse() *SecretKeysResponse {
this := SecretKeysResponse{}
return &this
}
// NewSecretKeysResponseWithDefaults instantiates a new SecretKeysResponse object
// This constructor will only assign default values to properties that have it defined,
// but it doesn't guarantee that properties required by API are set
func NewSecretKeysResponseWithDefaults() *SecretKeysResponse {
this := SecretKeysResponse{}
return &this
}
// GetSecrets returns the Secrets field value if set, zero value otherwise.
func (o *SecretKeysResponse) GetSecrets() []string {
if o == nil || o.Secrets == nil {
var ret []string
return ret
}
return *o.Secrets
}
// GetSecretsOk returns a tuple with the Secrets field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *SecretKeysResponse) GetSecretsOk() (*[]string, bool) {
if o == nil || o.Secrets == nil {
return nil, false
}
return o.Secrets, true
}
// HasSecrets returns a boolean if a field has been set.
func (o *SecretKeysResponse) HasSecrets() bool {
if o != nil && o.Secrets != nil {
return true
}
return false
}
// SetSecrets gets a reference to the given []string and assigns it to the Secrets field.
func (o *SecretKeysResponse) SetSecrets(v []string) {
o.Secrets = &v
}
// GetLinks returns the Links field value if set, zero value otherwise.
func (o *SecretKeysResponse) GetLinks() SecretKeysResponseAllOfLinks {
if o == nil || o.Links == nil {
var ret SecretKeysResponseAllOfLinks
return ret
}
return *o.Links
}
// GetLinksOk returns a tuple with the Links field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *SecretKeysResponse) GetLinksOk() (*SecretKeysResponseAllOfLinks, bool) {
if o == nil || o.Links == nil {
return nil, false
}
return o.Links, true
}
// HasLinks returns a boolean if a field has been set.
func (o *SecretKeysResponse) HasLinks() bool {
if o != nil && o.Links != nil {
return true
}
return false
}
// SetLinks gets a reference to the given SecretKeysResponseAllOfLinks and assigns it to the Links field.
func (o *SecretKeysResponse) SetLinks(v SecretKeysResponseAllOfLinks) {
o.Links = &v
}
func (o SecretKeysResponse) MarshalJSON() ([]byte, error) {
toSerialize := map[string]interface{}{}
if o.Secrets != nil {
toSerialize["secrets"] = o.Secrets
}
if o.Links != nil {
toSerialize["links"] = o.Links
}
return json.Marshal(toSerialize)
}
type NullableSecretKeysResponse struct {
value *SecretKeysResponse
isSet bool
}
func (v NullableSecretKeysResponse) Get() *SecretKeysResponse {
return v.value
}
func (v *NullableSecretKeysResponse) Set(val *SecretKeysResponse) {
v.value = val
v.isSet = true
}
func (v NullableSecretKeysResponse) IsSet() bool {
return v.isSet
}
func (v *NullableSecretKeysResponse) Unset() {
v.value = nil
v.isSet = false
}
func NewNullableSecretKeysResponse(val *SecretKeysResponse) *NullableSecretKeysResponse {
return &NullableSecretKeysResponse{value: val, isSet: true}
}
func (v NullableSecretKeysResponse) MarshalJSON() ([]byte, error) {
return json.Marshal(v.value)
}
func (v *NullableSecretKeysResponse) UnmarshalJSON(src []byte) error {
v.isSet = true
return json.Unmarshal(src, &v.value)
}

View File

@ -0,0 +1,113 @@
/*
* Subset of Influx API covered by Influx CLI
*
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* API version: 2.0.0
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package api
import (
"encoding/json"
)
// SecretKeysResponseAllOf struct for SecretKeysResponseAllOf
type SecretKeysResponseAllOf struct {
Links *SecretKeysResponseAllOfLinks `json:"links,omitempty"`
}
// NewSecretKeysResponseAllOf instantiates a new SecretKeysResponseAllOf object
// This constructor will assign default values to properties that have it defined,
// and makes sure properties required by API are set, but the set of arguments
// will change when the set of required properties is changed
func NewSecretKeysResponseAllOf() *SecretKeysResponseAllOf {
this := SecretKeysResponseAllOf{}
return &this
}
// NewSecretKeysResponseAllOfWithDefaults instantiates a new SecretKeysResponseAllOf object
// This constructor will only assign default values to properties that have it defined,
// but it doesn't guarantee that properties required by API are set
func NewSecretKeysResponseAllOfWithDefaults() *SecretKeysResponseAllOf {
this := SecretKeysResponseAllOf{}
return &this
}
// GetLinks returns the Links field value if set, zero value otherwise.
func (o *SecretKeysResponseAllOf) GetLinks() SecretKeysResponseAllOfLinks {
if o == nil || o.Links == nil {
var ret SecretKeysResponseAllOfLinks
return ret
}
return *o.Links
}
// GetLinksOk returns a tuple with the Links field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *SecretKeysResponseAllOf) GetLinksOk() (*SecretKeysResponseAllOfLinks, bool) {
if o == nil || o.Links == nil {
return nil, false
}
return o.Links, true
}
// HasLinks returns a boolean if a field has been set.
func (o *SecretKeysResponseAllOf) HasLinks() bool {
if o != nil && o.Links != nil {
return true
}
return false
}
// SetLinks gets a reference to the given SecretKeysResponseAllOfLinks and assigns it to the Links field.
func (o *SecretKeysResponseAllOf) SetLinks(v SecretKeysResponseAllOfLinks) {
o.Links = &v
}
func (o SecretKeysResponseAllOf) MarshalJSON() ([]byte, error) {
toSerialize := map[string]interface{}{}
if o.Links != nil {
toSerialize["links"] = o.Links
}
return json.Marshal(toSerialize)
}
type NullableSecretKeysResponseAllOf struct {
value *SecretKeysResponseAllOf
isSet bool
}
func (v NullableSecretKeysResponseAllOf) Get() *SecretKeysResponseAllOf {
return v.value
}
func (v *NullableSecretKeysResponseAllOf) Set(val *SecretKeysResponseAllOf) {
v.value = val
v.isSet = true
}
func (v NullableSecretKeysResponseAllOf) IsSet() bool {
return v.isSet
}
func (v *NullableSecretKeysResponseAllOf) Unset() {
v.value = nil
v.isSet = false
}
func NewNullableSecretKeysResponseAllOf(val *SecretKeysResponseAllOf) *NullableSecretKeysResponseAllOf {
return &NullableSecretKeysResponseAllOf{value: val, isSet: true}
}
func (v NullableSecretKeysResponseAllOf) MarshalJSON() ([]byte, error) {
return json.Marshal(v.value)
}
func (v *NullableSecretKeysResponseAllOf) UnmarshalJSON(src []byte) error {
v.isSet = true
return json.Unmarshal(src, &v.value)
}

View File

@ -0,0 +1,149 @@
/*
* Subset of Influx API covered by Influx CLI
*
* No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator)
*
* API version: 2.0.0
*/
// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT.
package api
import (
"encoding/json"
)
// SecretKeysResponseAllOfLinks struct for SecretKeysResponseAllOfLinks
type SecretKeysResponseAllOfLinks struct {
Self *string `json:"self,omitempty"`
Org *string `json:"org,omitempty"`
}
// NewSecretKeysResponseAllOfLinks instantiates a new SecretKeysResponseAllOfLinks object
// This constructor will assign default values to properties that have it defined,
// and makes sure properties required by API are set, but the set of arguments
// will change when the set of required properties is changed
func NewSecretKeysResponseAllOfLinks() *SecretKeysResponseAllOfLinks {
this := SecretKeysResponseAllOfLinks{}
return &this
}
// NewSecretKeysResponseAllOfLinksWithDefaults instantiates a new SecretKeysResponseAllOfLinks object
// This constructor will only assign default values to properties that have it defined,
// but it doesn't guarantee that properties required by API are set
func NewSecretKeysResponseAllOfLinksWithDefaults() *SecretKeysResponseAllOfLinks {
this := SecretKeysResponseAllOfLinks{}
return &this
}
// GetSelf returns the Self field value if set, zero value otherwise.
func (o *SecretKeysResponseAllOfLinks) GetSelf() string {
if o == nil || o.Self == nil {
var ret string
return ret
}
return *o.Self
}
// GetSelfOk returns a tuple with the Self field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *SecretKeysResponseAllOfLinks) GetSelfOk() (*string, bool) {
if o == nil || o.Self == nil {
return nil, false
}
return o.Self, true
}
// HasSelf returns a boolean if a field has been set.
func (o *SecretKeysResponseAllOfLinks) HasSelf() bool {
if o != nil && o.Self != nil {
return true
}
return false
}
// SetSelf gets a reference to the given string and assigns it to the Self field.
func (o *SecretKeysResponseAllOfLinks) SetSelf(v string) {
o.Self = &v
}
// GetOrg returns the Org field value if set, zero value otherwise.
func (o *SecretKeysResponseAllOfLinks) GetOrg() string {
if o == nil || o.Org == nil {
var ret string
return ret
}
return *o.Org
}
// GetOrgOk returns a tuple with the Org field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *SecretKeysResponseAllOfLinks) GetOrgOk() (*string, bool) {
if o == nil || o.Org == nil {
return nil, false
}
return o.Org, true
}
// HasOrg returns a boolean if a field has been set.
func (o *SecretKeysResponseAllOfLinks) HasOrg() bool {
if o != nil && o.Org != nil {
return true
}
return false
}
// SetOrg gets a reference to the given string and assigns it to the Org field.
func (o *SecretKeysResponseAllOfLinks) SetOrg(v string) {
o.Org = &v
}
func (o SecretKeysResponseAllOfLinks) MarshalJSON() ([]byte, error) {
toSerialize := map[string]interface{}{}
if o.Self != nil {
toSerialize["self"] = o.Self
}
if o.Org != nil {
toSerialize["org"] = o.Org
}
return json.Marshal(toSerialize)
}
type NullableSecretKeysResponseAllOfLinks struct {
value *SecretKeysResponseAllOfLinks
isSet bool
}
func (v NullableSecretKeysResponseAllOfLinks) Get() *SecretKeysResponseAllOfLinks {
return v.value
}
func (v *NullableSecretKeysResponseAllOfLinks) Set(val *SecretKeysResponseAllOfLinks) {
v.value = val
v.isSet = true
}
func (v NullableSecretKeysResponseAllOfLinks) IsSet() bool {
return v.isSet
}
func (v *NullableSecretKeysResponseAllOfLinks) Unset() {
v.value = nil
v.isSet = false
}
func NewNullableSecretKeysResponseAllOfLinks(val *SecretKeysResponseAllOfLinks) *NullableSecretKeysResponseAllOfLinks {
return &NullableSecretKeysResponseAllOfLinks{value: val, isSet: true}
}
func (v NullableSecretKeysResponseAllOfLinks) MarshalJSON() ([]byte, error) {
return json.Marshal(v.value)
}
func (v *NullableSecretKeysResponseAllOfLinks) UnmarshalJSON(src []byte) error {
v.isSet = true
return json.Unmarshal(src, &v.value)
}

172
clients/secret/secret.go Normal file
View File

@ -0,0 +1,172 @@
package secret
import (
"context"
"fmt"
"github.com/influxdata/influx-cli/v2/api"
"github.com/influxdata/influx-cli/v2/clients"
)
type Client struct {
clients.CLI
api.SecretsApi
api.OrganizationsApi
}
type secretPrintOpt struct {
deleted bool
secret *secret
secrets []secret
}
type secret struct {
key string
orgID string
}
type DeleteParams struct {
clients.OrgParams
Key string
}
func (c Client) Delete(ctx context.Context, params *DeleteParams) error {
orgID, err := c.getOrgID(ctx, params.OrgParams)
if err != nil {
return err
}
// PostOrgsIDSecrets is used to remove secrets from an organization.
// The name is generated from the operationId in the
// orgs_orgsID_secrets_delete.yml path.
err = c.PostOrgsIDSecrets(ctx, orgID).
SecretKeys(api.SecretKeys{Secrets: &[]string{params.Key}}).
Execute()
if err != nil {
return fmt.Errorf("failed to delete secret with key %q: %w", params.Key, err)
}
return c.printSecrets(secretPrintOpt{
deleted: true,
secret: &secret{
key: params.Key,
orgID: orgID,
},
})
}
type ListParams struct {
clients.OrgParams
}
func (c Client) List(ctx context.Context, params *ListParams) error {
orgID, err := c.getOrgID(ctx, params.OrgParams)
if err != nil {
return err
}
response, err := c.GetOrgsIDSecrets(ctx, orgID).Execute()
if err != nil {
return fmt.Errorf("failed to retrieve secret keys: %w", err)
}
secrets := response.GetSecrets()
opts := make([]secret, len(secrets))
for i, entry := range secrets {
opts[i] = secret{
key: entry,
orgID: orgID,
}
}
return c.printSecrets(secretPrintOpt{secrets: opts})
}
type UpdateParams struct {
clients.OrgParams
Key string
Value string
}
func (c Client) Update(ctx context.Context, params *UpdateParams) error {
orgID, err := c.getOrgID(ctx, params.OrgParams)
if err != nil {
return err
}
var secretVal string
if params.Value != "" {
secretVal = params.Value
} else {
secretVal, err = c.StdIO.GetSecret("Please type your secret", 0)
if err != nil {
return err
}
}
err = c.PatchOrgsIDSecrets(ctx, orgID).
RequestBody(map[string]string{params.Key: secretVal}).
Execute()
if err != nil {
return fmt.Errorf("failed to update secret with key %q: %w", params.Key, err)
}
return c.printSecrets(secretPrintOpt{
secret: &secret{
key: params.Key,
orgID: orgID,
},
})
}
func (c Client) printSecrets(opts secretPrintOpt) error {
if c.PrintAsJSON {
var v interface{} = opts.secrets
if opts.secrets == nil {
v = opts.secret
}
return c.PrintJSON(v)
}
headers := []string{"Key", "Organization ID"}
if opts.deleted {
headers = append(headers, "Deleted")
}
if opts.secret != nil {
opts.secrets = append(opts.secrets, *opts.secret)
}
var rows []map[string]interface{}
for _, u := range opts.secrets {
row := map[string]interface{}{
"Key": u.key,
"Organization ID": u.orgID,
}
if opts.deleted {
row["Deleted"] = true
}
rows = append(rows, row)
}
return c.PrintTable(headers, rows...)
}
func (c Client) getOrgID(ctx context.Context, params clients.OrgParams) (string, error) {
if params.OrgID.Valid() || params.OrgName != "" || c.ActiveConfig.Org != "" {
if params.OrgID.Valid() {
return params.OrgID.String(), nil
}
for _, name := range []string{params.OrgName, c.ActiveConfig.Org} {
if name != "" {
org, err := c.GetOrgs(ctx).Org(name).Execute()
if err != nil {
return "", fmt.Errorf("failed to lookup org with name %q: %w", name, err)
}
if len(org.GetOrgs()) == 0 {
return "", fmt.Errorf("no organization with name %q: %w", name, err)
}
return org.GetOrgs()[0].GetId(), nil
}
}
}
return "", fmt.Errorf("org or org-id must be provided")
}

View File

@ -0,0 +1,335 @@
package secret_test
import (
"bytes"
"context"
"testing"
"github.com/golang/mock/gomock"
"github.com/influxdata/influx-cli/v2/api"
"github.com/influxdata/influx-cli/v2/clients"
"github.com/influxdata/influx-cli/v2/clients/secret"
"github.com/influxdata/influx-cli/v2/config"
"github.com/influxdata/influx-cli/v2/internal/mock"
"github.com/influxdata/influx-cli/v2/pkg/influxid"
"github.com/stretchr/testify/require"
)
const (
defaultOrgName = "default org"
fakeResults = "data data data"
fakeKey = "key1"
)
func TestSecret_List(t *testing.T) {
t.Parallel()
printHeader := "Key\t\tOrganization ID\n"
id, err := influxid.IDFromString("1111111111111111")
require.NoError(t, err)
testCases := []struct {
name string
params secret.ListParams
defaultOrgName string
registerExpectations func(t *testing.T, secretApi *mock.MockSecretsApi, orgApi *mock.MockOrganizationsApi)
expectMatcher string
expectError string
}{
{
name: "org id",
params: secret.ListParams{
OrgParams: clients.OrgParams{
OrgID: id,
},
},
defaultOrgName: defaultOrgName,
registerExpectations: func(t *testing.T, secretApi *mock.MockSecretsApi, orgApi *mock.MockOrganizationsApi) {
req := api.ApiGetOrgsIDSecretsRequest{ApiService: secretApi}.OrgID(id.String())
secretApi.EXPECT().GetOrgsIDSecrets(gomock.Any(), gomock.Eq(id.String())).Return(req)
secretApi.EXPECT().GetOrgsIDSecretsExecute(gomock.Eq(req)).
Return(api.SecretKeysResponse{Secrets: &[]string{fakeResults}}, nil)
},
expectMatcher: printHeader+fakeResults+"\t"+id.String()+"\n",
},
{
name: "default org",
params: secret.ListParams{
OrgParams: clients.OrgParams{},
},
defaultOrgName: defaultOrgName,
registerExpectations: func(t *testing.T, secretApi *mock.MockSecretsApi, orgApi *mock.MockOrganizationsApi) {
orgReq := api.ApiGetOrgsRequest{ApiService: orgApi}.Org(defaultOrgName)
orgObj := api.Organization{Name: defaultOrgName}
orgApi.EXPECT().GetOrgs(gomock.Any()).Return(orgReq)
orgApi.EXPECT().GetOrgsExecute(orgReq).Return(api.Organizations{Orgs: &[]api.Organization{orgObj}}, nil)
secReq := api.ApiGetOrgsIDSecretsRequest{ApiService: secretApi}.OrgID(orgObj.GetId())
secObj := api.SecretKeysResponse{}
secretApi.EXPECT().GetOrgsIDSecrets(gomock.Any(), orgObj.GetId()).Return(secReq)
secretApi.EXPECT().GetOrgsIDSecretsExecute(secReq).Return(secObj, nil)
},
expectMatcher: "Key\tOrganization ID\n",
},
{
name: "no org provided",
params: secret.ListParams{
OrgParams: clients.OrgParams{},
},
expectError: "org or org-id must be provided",
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
ctrl := gomock.NewController(t)
stdio := mock.NewMockStdIO(ctrl)
writtenBytes := bytes.Buffer{}
stdio.EXPECT().Write(gomock.Any()).DoAndReturn(writtenBytes.Write).AnyTimes()
secretsApi := mock.NewMockSecretsApi(ctrl)
organizationsApi := mock.NewMockOrganizationsApi(ctrl)
if tc.registerExpectations != nil {
tc.registerExpectations(t, secretsApi, organizationsApi)
}
cli := secret.Client{
CLI: clients.CLI{
ActiveConfig: config.Config{
Org: tc.defaultOrgName,
},
StdIO: stdio,
},
SecretsApi: secretsApi,
OrganizationsApi: organizationsApi,
}
err := cli.List(context.Background(), &tc.params)
if tc.expectError != "" {
require.Error(t, err)
require.Equal(t, tc.expectError, err.Error())
return
}
require.NoError(t, err)
require.Equal(t, tc.expectMatcher, writtenBytes.String())
})
}
}
func TestSecret_Delete(t *testing.T) {
t.Parallel()
printHeader := "Key\tOrganization ID\t\tDeleted\n"
id, err := influxid.IDFromString("1111111111111111")
require.NoError(t, err)
testCases := []struct {
name string
params secret.DeleteParams
defaultOrgName string
registerExpectations func(t *testing.T, secretApi *mock.MockSecretsApi)
expectMatcher string
expectError string
}{
{
name: "delete",
params: secret.DeleteParams{
OrgParams: clients.OrgParams{
OrgID: id,
},
Key: fakeKey,
},
defaultOrgName: defaultOrgName,
registerExpectations: func(t *testing.T, secretApi *mock.MockSecretsApi) {
req := api.ApiPostOrgsIDSecretsRequest{ApiService: secretApi}.
OrgID(id.String()).
SecretKeys(api.SecretKeys{Secrets: &[]string{"key1"}})
secretApi.EXPECT().PostOrgsIDSecrets(gomock.Any(), gomock.Eq(id.String())).Return(req)
secretApi.EXPECT().PostOrgsIDSecretsExecute(gomock.Eq(req)).Return(nil)
},
expectMatcher: printHeader+fakeKey+"\t"+id.String()+"\ttrue\n",
},
{
// This situation cannot happen since the CLI will stop it.
// Still worth testing though
name: "delete no key",
params: secret.DeleteParams{
OrgParams: clients.OrgParams{
OrgID: id,
},
},
defaultOrgName: defaultOrgName,
registerExpectations: func(t *testing.T, secretApi *mock.MockSecretsApi) {
req := api.ApiPostOrgsIDSecretsRequest{ApiService: secretApi}.
OrgID(id.String()).
SecretKeys(api.SecretKeys{Secrets: &[]string{""}})
secretApi.EXPECT().PostOrgsIDSecrets(gomock.Any(), gomock.Eq(id.String())).Return(req)
secretApi.EXPECT().PostOrgsIDSecretsExecute(gomock.Eq(req)).Return(nil)
},
expectMatcher: printHeader+"\t"+id.String()+"\ttrue\n",
},
{
name: "delete no org",
params: secret.DeleteParams{
Key: fakeKey,
},
expectError: "org or org-id must be provided",
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
ctrl := gomock.NewController(t)
stdio := mock.NewMockStdIO(ctrl)
writtenBytes := bytes.Buffer{}
stdio.EXPECT().Write(gomock.Any()).DoAndReturn(writtenBytes.Write).AnyTimes()
secretsApi := mock.NewMockSecretsApi(ctrl)
if tc.registerExpectations != nil {
tc.registerExpectations(t, secretsApi)
}
cli := secret.Client{
CLI: clients.CLI{
ActiveConfig: config.Config{
Org: tc.defaultOrgName,
},
StdIO: stdio,
},
SecretsApi: secretsApi,
}
err := cli.Delete(context.Background(), &tc.params)
if tc.expectError != "" {
require.Error(t, err)
require.Equal(t, tc.expectError, err.Error())
return
}
require.NoError(t, err)
require.Equal(t, tc.expectMatcher, writtenBytes.String())
})
}
}
func TestSecret_Update(t *testing.T) {
t.Parallel()
printHeader := "Key\tOrganization ID\n"
fakeValue := "someValue"
id, err := influxid.IDFromString("1111111111111111")
require.NoError(t, err)
testCases := []struct {
name string
params secret.UpdateParams
defaultOrgName string
registerExpectations func(t *testing.T, secretApi *mock.MockSecretsApi, stdio *mock.MockStdIO)
expectMatcher string
expectError string
}{
{
name: "update",
params: secret.UpdateParams{
OrgParams: clients.OrgParams{
OrgID: id,
},
Key: fakeKey,
Value: fakeValue,
},
defaultOrgName: defaultOrgName,
registerExpectations: func(t *testing.T, secretApi *mock.MockSecretsApi, stdio *mock.MockStdIO) {
req := api.ApiPatchOrgsIDSecretsRequest{ApiService: secretApi}.
OrgID(id.String()).
RequestBody(map[string]string{fakeKey: fakeValue})
secretApi.EXPECT().PatchOrgsIDSecrets(gomock.Any(), gomock.Eq(id.String())).Return(req)
secretApi.EXPECT().PatchOrgsIDSecretsExecute(gomock.Eq(req)).Return(nil)
},
expectMatcher: printHeader+fakeKey+"\t"+id.String()+"\n",
},
{
name: "update no key",
params: secret.UpdateParams{
OrgParams: clients.OrgParams{
OrgID: id,
},
Value: fakeValue,
},
defaultOrgName: defaultOrgName,
registerExpectations: func(t *testing.T, secretApi *mock.MockSecretsApi, stdio *mock.MockStdIO) {
req := api.ApiPatchOrgsIDSecretsRequest{ApiService: secretApi}.
OrgID(id.String()).
RequestBody(map[string]string{"": fakeValue})
secretApi.EXPECT().PatchOrgsIDSecrets(gomock.Any(), gomock.Eq(id.String())).Return(req)
secretApi.EXPECT().PatchOrgsIDSecretsExecute(gomock.Eq(req)).Return(nil)
},
expectMatcher: printHeader+"\t"+id.String()+"\n",
},
{
name: "update no value",
params: secret.UpdateParams{
OrgParams: clients.OrgParams{
OrgID: id,
},
Key: fakeKey,
},
defaultOrgName: defaultOrgName,
registerExpectations: func(t *testing.T, secretApi *mock.MockSecretsApi, stdio *mock.MockStdIO) {
stdio.EXPECT().GetSecret(gomock.Eq("Please type your secret"), gomock.Eq(0)).Return(fakeValue, nil)
req := api.ApiPatchOrgsIDSecretsRequest{ApiService: secretApi}.
OrgID(id.String()).
RequestBody(map[string]string{fakeKey: fakeValue})
secretApi.EXPECT().PatchOrgsIDSecrets(gomock.Any(), gomock.Eq(id.String())).Return(req)
secretApi.EXPECT().PatchOrgsIDSecretsExecute(gomock.Eq(req)).Return(nil)
},
expectMatcher: printHeader+fakeKey+"\t"+id.String()+"\n",
},
{
name: "update no org",
params: secret.UpdateParams{
Key: fakeKey,
Value: fakeValue,
},
expectError: "org or org-id must be provided",
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
ctrl := gomock.NewController(t)
stdio := mock.NewMockStdIO(ctrl)
writtenBytes := bytes.Buffer{}
stdio.EXPECT().Write(gomock.Any()).DoAndReturn(writtenBytes.Write).AnyTimes()
secretsApi := mock.NewMockSecretsApi(ctrl)
if tc.registerExpectations != nil {
tc.registerExpectations(t, secretsApi, stdio)
}
cli := secret.Client{
CLI: clients.CLI{
ActiveConfig: config.Config{
Org: tc.defaultOrgName,
},
StdIO: stdio,
},
SecretsApi: secretsApi,
}
err := cli.Update(context.Background(), &tc.params)
if tc.expectError != "" {
require.Error(t, err)
require.Equal(t, tc.expectError, err.Error())
return
}
require.NoError(t, err)
require.Equal(t, tc.expectMatcher, writtenBytes.String())
})
}
}

View File

@ -165,12 +165,12 @@ func (c Client) onboardingRequest(params *Params) (req api.OnboardingRequest, er
} }
if params.Password == "" { if params.Password == "" {
for { for {
pass1, err := c.StdIO.GetPassword("Please type your password", clients.MinPasswordLen) pass1, err := c.StdIO.GetSecret("Please type your password", clients.MinPasswordLen)
if err != nil { if err != nil {
return req, err return req, err
} }
// Don't bother with the length check the 2nd time, since we check equality to pass1. // Don't bother with the length check the 2nd time, since we check equality to pass1.
pass2, err := c.StdIO.GetPassword("Please type your password again", 0) pass2, err := c.StdIO.GetSecret("Please type your password again", 0)
if err != nil { if err != nil {
return req, err return req, err
} }

View File

@ -215,8 +215,8 @@ func Test_SetupSuccessInteractive(t *testing.T) {
stdio.EXPECT().Write(gomock.Any()).DoAndReturn(bytesWritten.Write).AnyTimes() stdio.EXPECT().Write(gomock.Any()).DoAndReturn(bytesWritten.Write).AnyTimes()
stdio.EXPECT().Banner(gomock.Any()) stdio.EXPECT().Banner(gomock.Any())
stdio.EXPECT().GetStringInput(gomock.Eq("Please type your primary username"), gomock.Any()).Return(username, nil) stdio.EXPECT().GetStringInput(gomock.Eq("Please type your primary username"), gomock.Any()).Return(username, nil)
stdio.EXPECT().GetPassword(gomock.Eq("Please type your password"), gomock.Any()).Return(password, nil) stdio.EXPECT().GetSecret(gomock.Eq("Please type your password"), gomock.Any()).Return(password, nil)
stdio.EXPECT().GetPassword(gomock.Eq("Please type your password again"), gomock.Any()).Return(password, nil) stdio.EXPECT().GetSecret(gomock.Eq("Please type your password again"), gomock.Any()).Return(password, nil)
stdio.EXPECT().GetStringInput(gomock.Eq("Please type your primary organization name"), gomock.Any()).Return(org, nil) stdio.EXPECT().GetStringInput(gomock.Eq("Please type your primary organization name"), gomock.Any()).Return(org, nil)
stdio.EXPECT().GetStringInput("Please type your primary bucket name", gomock.Any()).Return(bucket, nil) stdio.EXPECT().GetStringInput("Please type your primary bucket name", gomock.Any()).Return(bucket, nil)
stdio.EXPECT().GetStringInput("Please type your retention period in hours, or 0 for infinite", gomock.Any()).Return(strconv.Itoa(retentionHrs), nil) stdio.EXPECT().GetStringInput("Please type your retention period in hours, or 0 for infinite", gomock.Any()).Return(strconv.Itoa(retentionHrs), nil)

View File

@ -161,12 +161,12 @@ func (c Client) SetPassword(ctx context.Context, params *SetPasswordParams) erro
var password string var password string
for { for {
pass1, err := c.StdIO.GetPassword(fmt.Sprintf("Please type new password for %q", displayName), clients.MinPasswordLen) pass1, err := c.StdIO.GetSecret(fmt.Sprintf("Please type new password for %q", displayName), clients.MinPasswordLen)
if err != nil { if err != nil {
return err return err
} }
// Don't bother with the length check the 2nd time, since we check equality to pass1. // Don't bother with the length check the 2nd time, since we check equality to pass1.
pass2, err := c.StdIO.GetPassword("Please type new password again", 0) pass2, err := c.StdIO.GetSecret("Please type new password again", 0)
if err != nil { if err != nil {
return err return err
} }

View File

@ -573,7 +573,7 @@ func TestClient_SetPassword(t *testing.T) {
stdio := mock.NewMockStdIO(ctrl) stdio := mock.NewMockStdIO(ctrl)
stdio.EXPECT().Write(gomock.Any()).DoAndReturn(stdout.Write).AnyTimes() stdio.EXPECT().Write(gomock.Any()).DoAndReturn(stdout.Write).AnyTimes()
if !tc.noExpectAsk { if !tc.noExpectAsk {
stdio.EXPECT().GetPassword(gomock.Any(), gomock.Any()).Return("mypassword", nil).Times(2) stdio.EXPECT().GetSecret(gomock.Any(), gomock.Any()).Return("mypassword", nil).Times(2)
} }
cli := user.Client{CLI: clients.CLI{StdIO: stdio}, UsersApi: userApi} cli := user.Client{CLI: clients.CLI{StdIO: stdio}, UsersApi: userApi}

View File

@ -49,6 +49,7 @@ var app = cli.App{
newTelegrafsCommand(), newTelegrafsCommand(),
newDashboardsCommand(), newDashboardsCommand(),
newExportCmd(), newExportCmd(),
newSecretCommand(),
}, },
} }

102
cmd/influx/secret.go Normal file
View File

@ -0,0 +1,102 @@
package main
import (
"github.com/influxdata/influx-cli/v2/clients/secret"
"github.com/influxdata/influx-cli/v2/pkg/cli/middleware"
"github.com/urfave/cli/v2"
)
func newSecretCommand() *cli.Command {
return &cli.Command{
Name: "secret",
Usage: "Secret management commands",
Subcommands: []*cli.Command{
newDeleteSecretCmd(),
newListSecretCmd(),
newUpdateSecretCmd(),
},
}
}
func newDeleteSecretCmd() *cli.Command {
var params secret.DeleteParams
flags := append(commonFlags(), getOrgFlags(&params.OrgParams)...)
flags = append(flags, &cli.StringFlag{
Name: "key",
Usage: "The secret key (required)",
Required: true,
Aliases: []string{"k"},
Destination: &params.Key,
})
return &cli.Command{
Name: "delete",
Usage: "Delete secret",
Flags: flags,
Before: middleware.WithBeforeFns(withCli(), withApi(true)),
Action: func(ctx *cli.Context) error {
api := getAPI(ctx)
client := secret.Client{
CLI: getCLI(ctx),
SecretsApi: api.SecretsApi,
OrganizationsApi: api.OrganizationsApi,
}
return client.Delete(ctx.Context, &params)
},
}
}
func newListSecretCmd() *cli.Command {
var params secret.ListParams
flags := append(commonFlags(), getOrgFlags(&params.OrgParams)...)
return &cli.Command{
Name: "list",
Usage: "List secrets",
Aliases: []string{"find", "ls"},
Flags: flags,
Before: middleware.WithBeforeFns(withCli(), withApi(true)),
Action: func(ctx *cli.Context) error {
api := getAPI(ctx)
client := secret.Client{
CLI: getCLI(ctx),
SecretsApi: api.SecretsApi,
OrganizationsApi: api.OrganizationsApi,
}
return client.List(ctx.Context, &params)
},
}
}
func newUpdateSecretCmd() *cli.Command {
var params secret.UpdateParams
flags := append(commonFlags(), getOrgFlags(&params.OrgParams)...)
flags = append(flags,
&cli.StringFlag{
Name: "key",
Usage: "The secret key (required)",
Required: true,
Aliases: []string{"k"},
Destination: &params.Key,
},
&cli.StringFlag{
Name: "value",
Usage: "Optional secret value for scripting convenience, using this might expose the secret to your local history",
Aliases: []string{"v"},
Destination: &params.Value,
},
)
return &cli.Command{
Name: "update",
Usage: "Update secret",
Flags: flags,
Before: middleware.WithBeforeFns(withCli(), withApi(true)),
Action: func(ctx *cli.Context) error {
api := getAPI(ctx)
client := secret.Client{
CLI: getCLI(ctx),
SecretsApi: api.SecretsApi,
OrganizationsApi: api.OrganizationsApi,
}
return client.Update(ctx.Context, &params)
},
}
}

View File

@ -0,0 +1,121 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/influxdata/influx-cli/v2/api (interfaces: SecretsApi)
// Package mock is a generated GoMock package.
package mock
import (
context "context"
reflect "reflect"
gomock "github.com/golang/mock/gomock"
api "github.com/influxdata/influx-cli/v2/api"
)
// MockSecretsApi is a mock of SecretsApi interface.
type MockSecretsApi struct {
ctrl *gomock.Controller
recorder *MockSecretsApiMockRecorder
}
// MockSecretsApiMockRecorder is the mock recorder for MockSecretsApi.
type MockSecretsApiMockRecorder struct {
mock *MockSecretsApi
}
// NewMockSecretsApi creates a new mock instance.
func NewMockSecretsApi(ctrl *gomock.Controller) *MockSecretsApi {
mock := &MockSecretsApi{ctrl: ctrl}
mock.recorder = &MockSecretsApiMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockSecretsApi) EXPECT() *MockSecretsApiMockRecorder {
return m.recorder
}
// GetOrgsIDSecrets mocks base method.
func (m *MockSecretsApi) GetOrgsIDSecrets(arg0 context.Context, arg1 string) api.ApiGetOrgsIDSecretsRequest {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetOrgsIDSecrets", arg0, arg1)
ret0, _ := ret[0].(api.ApiGetOrgsIDSecretsRequest)
return ret0
}
// GetOrgsIDSecrets indicates an expected call of GetOrgsIDSecrets.
func (mr *MockSecretsApiMockRecorder) GetOrgsIDSecrets(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetOrgsIDSecrets", reflect.TypeOf((*MockSecretsApi)(nil).GetOrgsIDSecrets), arg0, arg1)
}
// GetOrgsIDSecretsExecute mocks base method.
func (m *MockSecretsApi) GetOrgsIDSecretsExecute(arg0 api.ApiGetOrgsIDSecretsRequest) (api.SecretKeysResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetOrgsIDSecretsExecute", arg0)
ret0, _ := ret[0].(api.SecretKeysResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetOrgsIDSecretsExecute indicates an expected call of GetOrgsIDSecretsExecute.
func (mr *MockSecretsApiMockRecorder) GetOrgsIDSecretsExecute(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetOrgsIDSecretsExecute", reflect.TypeOf((*MockSecretsApi)(nil).GetOrgsIDSecretsExecute), arg0)
}
// PatchOrgsIDSecrets mocks base method.
func (m *MockSecretsApi) PatchOrgsIDSecrets(arg0 context.Context, arg1 string) api.ApiPatchOrgsIDSecretsRequest {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "PatchOrgsIDSecrets", arg0, arg1)
ret0, _ := ret[0].(api.ApiPatchOrgsIDSecretsRequest)
return ret0
}
// PatchOrgsIDSecrets indicates an expected call of PatchOrgsIDSecrets.
func (mr *MockSecretsApiMockRecorder) PatchOrgsIDSecrets(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchOrgsIDSecrets", reflect.TypeOf((*MockSecretsApi)(nil).PatchOrgsIDSecrets), arg0, arg1)
}
// PatchOrgsIDSecretsExecute mocks base method.
func (m *MockSecretsApi) PatchOrgsIDSecretsExecute(arg0 api.ApiPatchOrgsIDSecretsRequest) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "PatchOrgsIDSecretsExecute", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// PatchOrgsIDSecretsExecute indicates an expected call of PatchOrgsIDSecretsExecute.
func (mr *MockSecretsApiMockRecorder) PatchOrgsIDSecretsExecute(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchOrgsIDSecretsExecute", reflect.TypeOf((*MockSecretsApi)(nil).PatchOrgsIDSecretsExecute), arg0)
}
// PostOrgsIDSecrets mocks base method.
func (m *MockSecretsApi) PostOrgsIDSecrets(arg0 context.Context, arg1 string) api.ApiPostOrgsIDSecretsRequest {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "PostOrgsIDSecrets", arg0, arg1)
ret0, _ := ret[0].(api.ApiPostOrgsIDSecretsRequest)
return ret0
}
// PostOrgsIDSecrets indicates an expected call of PostOrgsIDSecrets.
func (mr *MockSecretsApiMockRecorder) PostOrgsIDSecrets(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PostOrgsIDSecrets", reflect.TypeOf((*MockSecretsApi)(nil).PostOrgsIDSecrets), arg0, arg1)
}
// PostOrgsIDSecretsExecute mocks base method.
func (m *MockSecretsApi) PostOrgsIDSecretsExecute(arg0 api.ApiPostOrgsIDSecretsRequest) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "PostOrgsIDSecretsExecute", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// PostOrgsIDSecretsExecute indicates an expected call of PostOrgsIDSecretsExecute.
func (mr *MockSecretsApiMockRecorder) PostOrgsIDSecretsExecute(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PostOrgsIDSecretsExecute", reflect.TypeOf((*MockSecretsApi)(nil).PostOrgsIDSecretsExecute), arg0)
}

View File

@ -1,14 +1,14 @@
// Code generated by MockGen. DO NOT EDIT. // Code generated by MockGen. DO NOT EDIT.
// Source: github.com/influxdata/influx-cli/v2/internal/config (interfaces: Service) // Source: github.com/influxdata/influx-cli/v2/config (interfaces: Service)
// Package mock is a generated GoMock package. // Package mock is a generated GoMock package.
package mock package mock
import ( import (
"reflect" reflect "reflect"
"github.com/golang/mock/gomock" gomock "github.com/golang/mock/gomock"
"github.com/influxdata/influx-cli/v2/config" config "github.com/influxdata/influx-cli/v2/config"
) )
// MockConfigService is a mock of Service interface. // MockConfigService is a mock of Service interface.

View File

@ -11,6 +11,7 @@ package mock
//go:generate go run github.com/golang/mock/mockgen -package mock -destination api_users.gen.go github.com/influxdata/influx-cli/v2/api UsersApi //go:generate go run github.com/golang/mock/mockgen -package mock -destination api_users.gen.go github.com/influxdata/influx-cli/v2/api UsersApi
//go:generate go run github.com/golang/mock/mockgen -package mock -destination api_delete.gen.go github.com/influxdata/influx-cli/v2/api DeleteApi //go:generate go run github.com/golang/mock/mockgen -package mock -destination api_delete.gen.go github.com/influxdata/influx-cli/v2/api DeleteApi
//go:generate go run github.com/golang/mock/mockgen -package mock -destination api_backup.gen.go github.com/influxdata/influx-cli/v2/api BackupApi //go:generate go run github.com/golang/mock/mockgen -package mock -destination api_backup.gen.go github.com/influxdata/influx-cli/v2/api BackupApi
//go:generate go run github.com/golang/mock/mockgen -package mock -destination api_secret.gen.go github.com/influxdata/influx-cli/v2/api SecretsApi
// Other mocks // Other mocks
//go:generate go run github.com/golang/mock/mockgen -package mock -destination config.gen.go -mock_names Service=MockConfigService github.com/influxdata/influx-cli/v2/config Service //go:generate go run github.com/golang/mock/mockgen -package mock -destination config.gen.go -mock_names Service=MockConfigService github.com/influxdata/influx-cli/v2/config Service

View File

@ -75,19 +75,19 @@ func (mr *MockStdIOMockRecorder) GetConfirm(arg0 interface{}) *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetConfirm", reflect.TypeOf((*MockStdIO)(nil).GetConfirm), arg0) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetConfirm", reflect.TypeOf((*MockStdIO)(nil).GetConfirm), arg0)
} }
// GetPassword mocks base method. // GetSecret mocks base method.
func (m *MockStdIO) GetPassword(arg0 string, arg1 int) (string, error) { func (m *MockStdIO) GetSecret(arg0 string, arg1 int) (string, error) {
m.ctrl.T.Helper() m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetPassword", arg0, arg1) ret := m.ctrl.Call(m, "GetSecret", arg0, arg1)
ret0, _ := ret[0].(string) ret0, _ := ret[0].(string)
ret1, _ := ret[1].(error) ret1, _ := ret[1].(error)
return ret0, ret1 return ret0, ret1
} }
// GetPassword indicates an expected call of GetPassword. // GetSecret indicates an expected call of GetSecret.
func (mr *MockStdIOMockRecorder) GetPassword(arg0, arg1 interface{}) *gomock.Call { func (mr *MockStdIOMockRecorder) GetSecret(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper() mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetPassword", reflect.TypeOf((*MockStdIO)(nil).GetPassword), arg0, arg1) return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSecret", reflect.TypeOf((*MockStdIO)(nil).GetSecret), arg0, arg1)
} }
// GetStringInput mocks base method. // GetStringInput mocks base method.

View File

@ -67,8 +67,8 @@ func (t *terminalStdio) GetStringInput(prompt, defaultValue string) (input strin
return return
} }
// GetPassword prompts the user for a password. // GetSecret prompts the user for a password.
func (t *terminalStdio) GetPassword(prompt string, minLen int) (password string, err error) { func (t *terminalStdio) GetSecret(prompt string, minLen int) (password string, err error) {
question := survey.Password{Message: prompt} question := survey.Password{Message: prompt}
opts := []survey.AskOpt{survey.WithStdio(t.Stdin, t.Stdout, t.Stderr)} opts := []survey.AskOpt{survey.WithStdio(t.Stdin, t.Stdout, t.Stderr)}
if minLen > 0 { if minLen > 0 {

View File

@ -8,6 +8,6 @@ type StdIO interface {
Banner(message string) error Banner(message string) error
Error(message string) error Error(message string) error
GetStringInput(prompt, defaultValue string) (string, error) GetStringInput(prompt, defaultValue string) (string, error)
GetPassword(prompt string, minLen int) (string, error) GetSecret(prompt string, minLen int) (string, error)
GetConfirm(prompt string) bool GetConfirm(prompt string) bool
} }