feat: port org members commands from influxdb (#97)

This commit is contained in:
Daniel Moran 2021-05-19 11:02:59 -04:00 committed by GitHub
parent 8ab34d59e6
commit d8ef442b64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 1620 additions and 0 deletions

View File

@ -16,6 +16,7 @@ func newOrgCmd() *cli.Command {
newOrgCreateCmd(),
newOrgDeleteCmd(),
newOrgListCmd(),
newOrgMembersCmd(),
newOrgUpdateCmd(),
},
}

134
cmd/influx/org_members.go Normal file
View File

@ -0,0 +1,134 @@
package main
import (
"github.com/influxdata/influx-cli/v2/internal/cmd/org"
"github.com/influxdata/influx-cli/v2/pkg/cli/middleware"
"github.com/urfave/cli/v2"
)
func newOrgMembersCmd() *cli.Command {
return &cli.Command{
Name: "members",
Usage: "Organization membership commands",
Subcommands: []*cli.Command{
newOrgMembersAddCmd(),
newOrgMembersListCmd(),
newOrgMembersRemoveCmd(),
},
}
}
func newOrgMembersAddCmd() *cli.Command {
var params org.AddMemberParams
return &cli.Command{
Name: "add",
Usage: "Add organization member",
Before: middleware.WithBeforeFns(withCli(), withApi(true)),
Flags: append(
commonFlagsNoPrint(),
&cli.GenericFlag{
Name: "member",
Usage: "The member ID",
Aliases: []string{"m"},
Required: true,
Value: &params.MemberId,
},
&cli.StringFlag{
Name: "name",
Usage: "The organization name",
Aliases: []string{"n"},
EnvVars: []string{"INFLUX_ORG"},
Destination: &params.OrgName,
},
&cli.GenericFlag{
Name: "id",
Usage: "The organization ID",
Aliases: []string{"i"},
EnvVars: []string{"INFLUX_ORG_ID"},
Value: &params.OrgID,
},
),
Action: func(ctx *cli.Context) error {
client := org.Client{
CLI: getCLI(ctx),
OrganizationsApi: getAPI(ctx).OrganizationsApi,
}
return client.AddMember(ctx.Context, &params)
},
}
}
func newOrgMembersListCmd() *cli.Command {
var params org.ListMemberParams
return &cli.Command{
Name: "list",
Aliases: []string{"find", "ls"},
Usage: "List organization members",
Before: middleware.WithBeforeFns(withCli(), withApi(true)),
Flags: append(
commonFlags(),
&cli.StringFlag{
Name: "name",
Usage: "The organization name",
Aliases: []string{"n"},
EnvVars: []string{"INFLUX_ORG"},
Destination: &params.OrgName,
},
&cli.GenericFlag{
Name: "id",
Usage: "The organization ID",
Aliases: []string{"i"},
EnvVars: []string{"INFLUX_ORG_ID"},
Value: &params.OrgID,
},
),
Action: func(ctx *cli.Context) error {
client := org.Client{
CLI: getCLI(ctx),
OrganizationsApi: getAPI(ctx).OrganizationsApi,
UsersApi: getAPI(ctx).UsersApi,
}
return client.ListMembers(ctx.Context, &params)
},
}
}
func newOrgMembersRemoveCmd() *cli.Command {
var params org.RemoveMemberParams
return &cli.Command{
Name: "remove",
Usage: "Remove organization member",
Before: middleware.WithBeforeFns(withCli(), withApi(true)),
Flags: append(
commonFlagsNoPrint(),
&cli.GenericFlag{
Name: "member",
Usage: "The member ID",
Aliases: []string{"m"},
Required: true,
Value: &params.MemberId,
},
&cli.StringFlag{
Name: "name",
Usage: "The organization name",
Aliases: []string{"n"},
EnvVars: []string{"INFLUX_ORG"},
Destination: &params.OrgName,
},
&cli.GenericFlag{
Name: "id",
Usage: "The organization ID",
Aliases: []string{"i"},
EnvVars: []string{"INFLUX_ORG_ID"},
Value: &params.OrgID,
},
),
Action: func(ctx *cli.Context) error {
client := org.Client{
CLI: getCLI(ctx),
OrganizationsApi: getAPI(ctx).OrganizationsApi,
}
return client.RemoveMember(ctx.Context, &params)
},
}
}

View File

@ -0,0 +1,519 @@
/*
* 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 (
_gzip "compress/gzip"
_context "context"
_io "io"
_ioutil "io/ioutil"
_nethttp "net/http"
_neturl "net/url"
"strings"
)
// Linger please
var (
_ _context.Context
)
type UsersApi interface {
/*
* DeleteUsersID Delete a user
* @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
* @param userID The ID of the user to delete.
* @return ApiDeleteUsersIDRequest
*/
DeleteUsersID(ctx _context.Context, userID string) ApiDeleteUsersIDRequest
/*
* DeleteUsersIDExecute executes the request
*/
DeleteUsersIDExecute(r ApiDeleteUsersIDRequest) error
/*
* GetUsersID Retrieve a user
* @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
* @param userID The user ID.
* @return ApiGetUsersIDRequest
*/
GetUsersID(ctx _context.Context, userID string) ApiGetUsersIDRequest
/*
* GetUsersIDExecute executes the request
* @return UserResponse
*/
GetUsersIDExecute(r ApiGetUsersIDRequest) (UserResponse, error)
/*
* PatchUsersID Update a user
* @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
* @param userID The ID of the user to update.
* @return ApiPatchUsersIDRequest
*/
PatchUsersID(ctx _context.Context, userID string) ApiPatchUsersIDRequest
/*
* PatchUsersIDExecute executes the request
* @return UserResponse
*/
PatchUsersIDExecute(r ApiPatchUsersIDRequest) (UserResponse, error)
}
// usersApiGzipReadCloser supports streaming gzip response-bodies directly from the server.
type usersApiGzipReadCloser struct {
underlying _io.ReadCloser
gzip _io.ReadCloser
}
func (gzrc *usersApiGzipReadCloser) Read(p []byte) (int, error) {
return gzrc.gzip.Read(p)
}
func (gzrc *usersApiGzipReadCloser) Close() error {
if err := gzrc.gzip.Close(); err != nil {
return err
}
return gzrc.underlying.Close()
}
// UsersApiService UsersApi service
type UsersApiService service
type ApiDeleteUsersIDRequest struct {
ctx _context.Context
ApiService UsersApi
userID string
zapTraceSpan *string
}
func (r ApiDeleteUsersIDRequest) UserID(userID string) ApiDeleteUsersIDRequest {
r.userID = userID
return r
}
func (r ApiDeleteUsersIDRequest) GetUserID() string {
return r.userID
}
func (r ApiDeleteUsersIDRequest) ZapTraceSpan(zapTraceSpan string) ApiDeleteUsersIDRequest {
r.zapTraceSpan = &zapTraceSpan
return r
}
func (r ApiDeleteUsersIDRequest) GetZapTraceSpan() *string {
return r.zapTraceSpan
}
func (r ApiDeleteUsersIDRequest) Execute() error {
return r.ApiService.DeleteUsersIDExecute(r)
}
/*
* DeleteUsersID Delete a user
* @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
* @param userID The ID of the user to delete.
* @return ApiDeleteUsersIDRequest
*/
func (a *UsersApiService) DeleteUsersID(ctx _context.Context, userID string) ApiDeleteUsersIDRequest {
return ApiDeleteUsersIDRequest{
ApiService: a,
ctx: ctx,
userID: userID,
}
}
/*
* Execute executes the request
*/
func (a *UsersApiService) DeleteUsersIDExecute(r ApiDeleteUsersIDRequest) error {
var (
localVarHTTPMethod = _nethttp.MethodDelete
localVarPostBody interface{}
localVarFormFileName string
localVarFileName string
localVarFileBytes []byte
)
localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "UsersApiService.DeleteUsersID")
if err != nil {
return GenericOpenAPIError{error: err.Error()}
}
localVarPath := localBasePath + "/users/{userID}"
localVarPath = strings.Replace(localVarPath, "{"+"userID"+"}", _neturl.PathEscape(parameterToString(r.userID, "")), -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 err
}
localVarHTTPResponse, err := a.client.callAPI(req)
if err != nil || localVarHTTPResponse == nil {
return err
}
var body _io.ReadCloser = localVarHTTPResponse.Body
if localVarHTTPResponse.Header.Get("Content-Encoding") == "gzip" {
gzr, err := _gzip.NewReader(body)
if err != nil {
body.Close()
return err
}
body = &usersApiGzipReadCloser{underlying: body, gzip: gzr}
}
if localVarHTTPResponse.StatusCode >= 300 {
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 ApiGetUsersIDRequest struct {
ctx _context.Context
ApiService UsersApi
userID string
zapTraceSpan *string
}
func (r ApiGetUsersIDRequest) UserID(userID string) ApiGetUsersIDRequest {
r.userID = userID
return r
}
func (r ApiGetUsersIDRequest) GetUserID() string {
return r.userID
}
func (r ApiGetUsersIDRequest) ZapTraceSpan(zapTraceSpan string) ApiGetUsersIDRequest {
r.zapTraceSpan = &zapTraceSpan
return r
}
func (r ApiGetUsersIDRequest) GetZapTraceSpan() *string {
return r.zapTraceSpan
}
func (r ApiGetUsersIDRequest) Execute() (UserResponse, error) {
return r.ApiService.GetUsersIDExecute(r)
}
/*
* GetUsersID Retrieve a user
* @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
* @param userID The user ID.
* @return ApiGetUsersIDRequest
*/
func (a *UsersApiService) GetUsersID(ctx _context.Context, userID string) ApiGetUsersIDRequest {
return ApiGetUsersIDRequest{
ApiService: a,
ctx: ctx,
userID: userID,
}
}
/*
* Execute executes the request
* @return UserResponse
*/
func (a *UsersApiService) GetUsersIDExecute(r ApiGetUsersIDRequest) (UserResponse, error) {
var (
localVarHTTPMethod = _nethttp.MethodGet
localVarPostBody interface{}
localVarFormFileName string
localVarFileName string
localVarFileBytes []byte
localVarReturnValue UserResponse
)
localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "UsersApiService.GetUsersID")
if err != nil {
return localVarReturnValue, GenericOpenAPIError{error: err.Error()}
}
localVarPath := localBasePath + "/users/{userID}"
localVarPath = strings.Replace(localVarPath, "{"+"userID"+"}", _neturl.PathEscape(parameterToString(r.userID, "")), -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
}
var body _io.ReadCloser = localVarHTTPResponse.Body
if localVarHTTPResponse.Header.Get("Content-Encoding") == "gzip" {
gzr, err := _gzip.NewReader(body)
if err != nil {
body.Close()
return localVarReturnValue, err
}
body = &usersApiGzipReadCloser{underlying: body, gzip: gzr}
}
if localVarHTTPResponse.StatusCode >= 300 {
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
}
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 ApiPatchUsersIDRequest struct {
ctx _context.Context
ApiService UsersApi
userID string
user *User
zapTraceSpan *string
}
func (r ApiPatchUsersIDRequest) UserID(userID string) ApiPatchUsersIDRequest {
r.userID = userID
return r
}
func (r ApiPatchUsersIDRequest) GetUserID() string {
return r.userID
}
func (r ApiPatchUsersIDRequest) User(user User) ApiPatchUsersIDRequest {
r.user = &user
return r
}
func (r ApiPatchUsersIDRequest) GetUser() *User {
return r.user
}
func (r ApiPatchUsersIDRequest) ZapTraceSpan(zapTraceSpan string) ApiPatchUsersIDRequest {
r.zapTraceSpan = &zapTraceSpan
return r
}
func (r ApiPatchUsersIDRequest) GetZapTraceSpan() *string {
return r.zapTraceSpan
}
func (r ApiPatchUsersIDRequest) Execute() (UserResponse, error) {
return r.ApiService.PatchUsersIDExecute(r)
}
/*
* PatchUsersID Update a user
* @param ctx _context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background().
* @param userID The ID of the user to update.
* @return ApiPatchUsersIDRequest
*/
func (a *UsersApiService) PatchUsersID(ctx _context.Context, userID string) ApiPatchUsersIDRequest {
return ApiPatchUsersIDRequest{
ApiService: a,
ctx: ctx,
userID: userID,
}
}
/*
* Execute executes the request
* @return UserResponse
*/
func (a *UsersApiService) PatchUsersIDExecute(r ApiPatchUsersIDRequest) (UserResponse, error) {
var (
localVarHTTPMethod = _nethttp.MethodPatch
localVarPostBody interface{}
localVarFormFileName string
localVarFileName string
localVarFileBytes []byte
localVarReturnValue UserResponse
)
localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "UsersApiService.PatchUsersID")
if err != nil {
return localVarReturnValue, GenericOpenAPIError{error: err.Error()}
}
localVarPath := localBasePath + "/users/{userID}"
localVarPath = strings.Replace(localVarPath, "{"+"userID"+"}", _neturl.PathEscape(parameterToString(r.userID, "")), -1)
localVarHeaderParams := make(map[string]string)
localVarQueryParams := _neturl.Values{}
localVarFormParams := _neturl.Values{}
if r.user == nil {
return localVarReturnValue, reportError("user 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.user
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
}
var body _io.ReadCloser = localVarHTTPResponse.Body
if localVarHTTPResponse.Header.Get("Content-Encoding") == "gzip" {
gzr, err := _gzip.NewReader(body)
if err != nil {
body.Close()
return localVarReturnValue, err
}
body = &usersApiGzipReadCloser{underlying: body, gzip: gzr}
}
if localVarHTTPResponse.StatusCode >= 300 {
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
}
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
}

View File

@ -59,6 +59,8 @@ type APIClient struct {
SetupApi SetupApi
UsersApi UsersApi
WriteApi WriteApi
}
@ -84,6 +86,7 @@ func NewAPIClient(cfg *Configuration) *APIClient {
c.OrganizationsApi = (*OrganizationsApiService)(&c.common)
c.QueryApi = (*QueryApiService)(&c.common)
c.SetupApi = (*SetupApiService)(&c.common)
c.UsersApi = (*UsersApiService)(&c.common)
c.WriteApi = (*WriteApiService)(&c.common)
return c

View File

@ -31,6 +31,8 @@ paths:
$ref: "./openapi/src/cloud/paths/measurements_measurementID.yml"
/query:
$ref: "./overrides/paths/query.yml"
/users/{userID}:
$ref: "./openapi/src/common/paths/users_userID.yml"
components:
parameters:
TraceSpan:
@ -56,6 +58,8 @@ components:
$ref: "./openapi/src/common/schemas/OnboardingRequest.yml"
OnboardingResponse:
$ref: "./openapi/src/common/schemas/OnboardingResponse.yml"
User:
$ref: "./openapi/src/common/schemas/User.yml"
UserResponse:
$ref: "./openapi/src/common/schemas/UserResponse.yml"
Links:

View File

@ -0,0 +1,219 @@
/*
* 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"
)
// User struct for User
type User struct {
Id *string `json:"id,omitempty"`
OauthID *string `json:"oauthID,omitempty"`
Name string `json:"name"`
// If inactive the user is inactive.
Status *string `json:"status,omitempty"`
}
// NewUser instantiates a new User 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 NewUser(name string) *User {
this := User{}
this.Name = name
var status string = "active"
this.Status = &status
return &this
}
// NewUserWithDefaults instantiates a new User 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 NewUserWithDefaults() *User {
this := User{}
var status string = "active"
this.Status = &status
return &this
}
// GetId returns the Id field value if set, zero value otherwise.
func (o *User) GetId() string {
if o == nil || o.Id == nil {
var ret string
return ret
}
return *o.Id
}
// GetIdOk returns a tuple with the Id field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *User) GetIdOk() (*string, bool) {
if o == nil || o.Id == nil {
return nil, false
}
return o.Id, true
}
// HasId returns a boolean if a field has been set.
func (o *User) HasId() bool {
if o != nil && o.Id != nil {
return true
}
return false
}
// SetId gets a reference to the given string and assigns it to the Id field.
func (o *User) SetId(v string) {
o.Id = &v
}
// GetOauthID returns the OauthID field value if set, zero value otherwise.
func (o *User) GetOauthID() string {
if o == nil || o.OauthID == nil {
var ret string
return ret
}
return *o.OauthID
}
// GetOauthIDOk returns a tuple with the OauthID field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *User) GetOauthIDOk() (*string, bool) {
if o == nil || o.OauthID == nil {
return nil, false
}
return o.OauthID, true
}
// HasOauthID returns a boolean if a field has been set.
func (o *User) HasOauthID() bool {
if o != nil && o.OauthID != nil {
return true
}
return false
}
// SetOauthID gets a reference to the given string and assigns it to the OauthID field.
func (o *User) SetOauthID(v string) {
o.OauthID = &v
}
// GetName returns the Name field value
func (o *User) GetName() string {
if o == nil {
var ret string
return ret
}
return o.Name
}
// GetNameOk returns a tuple with the Name field value
// and a boolean to check if the value has been set.
func (o *User) GetNameOk() (*string, bool) {
if o == nil {
return nil, false
}
return &o.Name, true
}
// SetName sets field value
func (o *User) SetName(v string) {
o.Name = v
}
// GetStatus returns the Status field value if set, zero value otherwise.
func (o *User) GetStatus() string {
if o == nil || o.Status == nil {
var ret string
return ret
}
return *o.Status
}
// GetStatusOk returns a tuple with the Status field value if set, nil otherwise
// and a boolean to check if the value has been set.
func (o *User) GetStatusOk() (*string, bool) {
if o == nil || o.Status == nil {
return nil, false
}
return o.Status, true
}
// HasStatus returns a boolean if a field has been set.
func (o *User) HasStatus() bool {
if o != nil && o.Status != nil {
return true
}
return false
}
// SetStatus gets a reference to the given string and assigns it to the Status field.
func (o *User) SetStatus(v string) {
o.Status = &v
}
func (o User) MarshalJSON() ([]byte, error) {
toSerialize := map[string]interface{}{}
if o.Id != nil {
toSerialize["id"] = o.Id
}
if o.OauthID != nil {
toSerialize["oauthID"] = o.OauthID
}
if true {
toSerialize["name"] = o.Name
}
if o.Status != nil {
toSerialize["status"] = o.Status
}
return json.Marshal(toSerialize)
}
type NullableUser struct {
value *User
isSet bool
}
func (v NullableUser) Get() *User {
return v.value
}
func (v *NullableUser) Set(val *User) {
v.value = val
v.isSet = true
}
func (v NullableUser) IsSet() bool {
return v.isSet
}
func (v *NullableUser) Unset() {
v.value = nil
v.isSet = false
}
func NewNullableUser(val *User) *NullableUser {
return &NullableUser{value: val, isSet: true}
}
func (v NullableUser) MarshalJSON() ([]byte, error) {
return json.Marshal(v.value)
}
func (v *NullableUser) UnmarshalJSON(src []byte) error {
v.isSet = true
return json.Unmarshal(src, &v.value)
}

View File

@ -8,6 +8,7 @@ import (
type Client struct {
cmd.CLI
api.OrganizationsApi
api.UsersApi
}
type printOrgOpts struct {

View File

@ -0,0 +1,164 @@
package org
import (
"context"
"errors"
"fmt"
"github.com/influxdata/influx-cli/v2/internal/api"
"github.com/influxdata/influx-cli/v2/pkg/influxid"
)
var ErrMustSpecifyOrg = errors.New("must specify org ID or org name")
type AddMemberParams struct {
MemberId influxid.ID
OrgName string
OrgID influxid.ID
}
func (c Client) AddMember(ctx context.Context, params *AddMemberParams) (err error) {
if !params.OrgID.Valid() && params.OrgName == "" && c.ActiveConfig.Org == "" {
return ErrMustSpecifyOrg
}
orgID := params.OrgID.String()
if !params.OrgID.Valid() {
if orgID, err = c.getOrgId(ctx, params.OrgName); err != nil {
return err
}
}
member, err := c.PostOrgsIDMembers(ctx, orgID).
AddResourceMemberRequestBody(*api.NewAddResourceMemberRequestBody(params.MemberId.String())).
Execute()
if err != nil {
return fmt.Errorf("failed to add user %q to org %q: %w", params.MemberId.String(), orgID, err)
}
_, err = c.StdIO.Write([]byte(fmt.Sprintf("user %q has been added as a member of org %q\n", *member.Id, orgID)))
return err
}
type ListMemberParams struct {
OrgName string
OrgID influxid.ID
}
const maxConcurrentGetUserRequests = 10
func (c Client) ListMembers(ctx context.Context, params *ListMemberParams) (err error) {
if !params.OrgID.Valid() && params.OrgName == "" && c.ActiveConfig.Org == "" {
return ErrMustSpecifyOrg
}
orgID := params.OrgID.String()
if !params.OrgID.Valid() {
if orgID, err = c.getOrgId(ctx, params.OrgName); err != nil {
return err
}
}
members, err := c.GetOrgsIDMembers(ctx, orgID).Execute()
if err != nil {
return fmt.Errorf("failed to find members of org %q: %w", orgID, err)
}
type indexedUser struct {
user api.UserResponse
index int
}
userChan := make(chan indexedUser, maxConcurrentGetUserRequests)
semChan := make(chan struct{}, maxConcurrentGetUserRequests)
errChan := make(chan error)
var resourceMembers []api.ResourceMember
if members.Users != nil {
resourceMembers = *members.Users
}
// Fetch user details about all members of the org.
for i, member := range resourceMembers {
go func(i int, memberId string) {
semChan <- struct{}{}
defer func() { <-semChan }()
user, err := c.GetUsersID(ctx, memberId).Execute()
if err != nil {
errChan <- fmt.Errorf("failed to retrieve details for user %q: %w", memberId, err)
return
}
userChan <- indexedUser{user: user, index: i}
}(i, member.GetId())
}
users := make([]api.UserResponse, len(resourceMembers))
for range resourceMembers {
select {
case <-ctx.Done():
return ctx.Err()
case err := <-errChan:
return err
case user := <-userChan:
users[user.index] = user.user
}
}
if c.PrintAsJSON {
return c.PrintJSON(users)
}
rows := make([]map[string]interface{}, len(resourceMembers))
for i, user := range users {
rows[i] = map[string]interface{}{
"ID": user.GetId(),
"Name": user.GetName(),
"User Type": "member",
"Status": user.GetStatus(),
}
}
return c.PrintTable([]string{"ID", "Name", "User Type", "Status"}, rows...)
}
type RemoveMemberParams struct {
MemberId influxid.ID
OrgName string
OrgID influxid.ID
}
func (c Client) RemoveMember(ctx context.Context, params *RemoveMemberParams) (err error) {
if !params.OrgID.Valid() && params.OrgName == "" && c.ActiveConfig.Org == "" {
return ErrMustSpecifyOrg
}
orgID := params.OrgID.String()
if !params.OrgID.Valid() {
if orgID, err = c.getOrgId(ctx, params.OrgName); err != nil {
return err
}
}
if err = c.DeleteOrgsIDMembersID(ctx, orgID, params.MemberId.String()).Execute(); err != nil {
return fmt.Errorf("failed to remove member %q from org %q", params.MemberId, orgID)
}
_, err = c.StdIO.Write([]byte(fmt.Sprintf("user %q has been removed from org %q\n", params.MemberId, orgID)))
return err
}
func (c Client) getOrgId(ctx context.Context, orgName string) (string, error) {
req := c.GetOrgs(ctx)
if orgName != "" {
req = req.Org(orgName)
} else {
req = req.Org(c.ActiveConfig.Org)
}
orgs, err := req.Execute()
if err != nil {
return "", fmt.Errorf("failed to find org %q: %w", orgName, err)
}
if orgs.Orgs == nil || len(*orgs.Orgs) == 0 {
return "", fmt.Errorf("no org found with name %q", orgName)
}
return *(*orgs.Orgs)[0].Id, nil
}

View File

@ -0,0 +1,452 @@
package org_test
import (
"bytes"
"context"
"errors"
"fmt"
"strings"
"testing"
"github.com/golang/mock/gomock"
"github.com/influxdata/influx-cli/v2/internal/api"
"github.com/influxdata/influx-cli/v2/internal/cmd"
"github.com/influxdata/influx-cli/v2/internal/cmd/org"
"github.com/influxdata/influx-cli/v2/internal/config"
"github.com/influxdata/influx-cli/v2/internal/mock"
"github.com/influxdata/influx-cli/v2/internal/testutils"
"github.com/influxdata/influx-cli/v2/pkg/influxid"
"github.com/stretchr/testify/assert"
tmock "github.com/stretchr/testify/mock"
"github.com/stretchr/testify/require"
)
var id1, _ = influxid.IDFromString("1111111111111111")
var id2, _ = influxid.IDFromString("2222222222222222")
func TestClient_AddMember(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
params org.AddMemberParams
defaultOrgName string
registerExpectations func(*testing.T, *mock.MockOrganizationsApi)
expectedOut string
expectedErr string
}{
{
name: "org by ID",
params: org.AddMemberParams{
OrgID: id1,
MemberId: id2,
},
defaultOrgName: "my-org",
registerExpectations: func(t *testing.T, orgApi *mock.MockOrganizationsApi) {
orgApi.EXPECT().PostOrgsIDMembers(gomock.Any(), gomock.Eq(id1.String())).
Return(api.ApiPostOrgsIDMembersRequest{ApiService: orgApi}.OrgID(id1.String()))
orgApi.EXPECT().PostOrgsIDMembersExecute(tmock.MatchedBy(func(in api.ApiPostOrgsIDMembersRequest) bool {
body := in.GetAddResourceMemberRequestBody()
return assert.Equal(t, id1.String(), in.GetOrgID()) &&
assert.NotNil(t, body) &&
assert.Equal(t, id2.String(), body.GetId())
})).Return(api.ResourceMember{Id: api.PtrString(id2.String())}, nil)
},
expectedOut: "user \"2222222222222222\" has been added as a member of org \"1111111111111111\"",
},
{
name: "org by name",
params: org.AddMemberParams{
OrgName: "org",
MemberId: id2,
},
defaultOrgName: "my-org",
registerExpectations: func(t *testing.T, orgApi *mock.MockOrganizationsApi) {
orgApi.EXPECT().GetOrgs(gomock.Any()).Return(api.ApiGetOrgsRequest{ApiService: orgApi})
orgApi.EXPECT().GetOrgsExecute(tmock.MatchedBy(func(in api.ApiGetOrgsRequest) bool {
return assert.Equal(t, "org", *in.GetOrg())
})).Return(api.Organizations{
Orgs: &[]api.Organization{{Id: api.PtrString(id1.String())}},
}, nil)
orgApi.EXPECT().PostOrgsIDMembers(gomock.Any(), gomock.Eq(id1.String())).
Return(api.ApiPostOrgsIDMembersRequest{ApiService: orgApi}.OrgID(id1.String()))
orgApi.EXPECT().PostOrgsIDMembersExecute(tmock.MatchedBy(func(in api.ApiPostOrgsIDMembersRequest) bool {
body := in.GetAddResourceMemberRequestBody()
return assert.Equal(t, id1.String(), in.GetOrgID()) &&
assert.NotNil(t, body) &&
assert.Equal(t, id2.String(), body.GetId())
})).Return(api.ResourceMember{Id: api.PtrString(id2.String())}, nil)
},
expectedOut: "user \"2222222222222222\" has been added as a member of org \"1111111111111111\"",
},
{
name: "by config org",
params: org.AddMemberParams{
MemberId: id2,
},
defaultOrgName: "my-org",
registerExpectations: func(t *testing.T, orgApi *mock.MockOrganizationsApi) {
orgApi.EXPECT().GetOrgs(gomock.Any()).Return(api.ApiGetOrgsRequest{ApiService: orgApi})
orgApi.EXPECT().GetOrgsExecute(tmock.MatchedBy(func(in api.ApiGetOrgsRequest) bool {
return assert.Equal(t, "my-org", *in.GetOrg())
})).Return(api.Organizations{
Orgs: &[]api.Organization{{Id: api.PtrString(id1.String())}},
}, nil)
orgApi.EXPECT().PostOrgsIDMembers(gomock.Any(), gomock.Eq(id1.String())).
Return(api.ApiPostOrgsIDMembersRequest{ApiService: orgApi}.OrgID(id1.String()))
orgApi.EXPECT().PostOrgsIDMembersExecute(tmock.MatchedBy(func(in api.ApiPostOrgsIDMembersRequest) bool {
body := in.GetAddResourceMemberRequestBody()
return assert.Equal(t, id1.String(), in.GetOrgID()) &&
assert.NotNil(t, body) &&
assert.Equal(t, id2.String(), body.GetId())
})).Return(api.ResourceMember{Id: api.PtrString(id2.String())}, nil)
},
expectedOut: "user \"2222222222222222\" has been added as a member of org \"1111111111111111\"",
},
{
name: "no such org",
params: org.AddMemberParams{
MemberId: id2,
},
defaultOrgName: "my-org",
registerExpectations: func(t *testing.T, orgApi *mock.MockOrganizationsApi) {
orgApi.EXPECT().GetOrgs(gomock.Any()).Return(api.ApiGetOrgsRequest{ApiService: orgApi})
orgApi.EXPECT().GetOrgsExecute(tmock.MatchedBy(func(in api.ApiGetOrgsRequest) bool {
return assert.Equal(t, "my-org", *in.GetOrg())
})).Return(api.Organizations{}, errors.New("not found"))
},
expectedErr: "not found",
},
{
name: "missing org",
expectedErr: org.ErrMustSpecifyOrg.Error(),
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
ctrl := gomock.NewController(t)
api := mock.NewMockOrganizationsApi(ctrl)
if tc.registerExpectations != nil {
tc.registerExpectations(t, api)
}
stdout := bytes.Buffer{}
stdio := mock.NewMockStdIO(ctrl)
stdio.EXPECT().Write(gomock.Any()).DoAndReturn(stdout.Write).AnyTimes()
cli := org.Client{
CLI: cmd.CLI{StdIO: stdio, ActiveConfig: config.Config{Org: tc.defaultOrgName}},
OrganizationsApi: api,
}
err := cli.AddMember(context.Background(), &tc.params)
if tc.expectedErr != "" {
require.Error(t, err)
require.Contains(t, err.Error(), tc.expectedErr)
return
}
require.NoError(t, err)
require.Equal(t, tc.expectedOut, strings.TrimSpace(stdout.String()))
})
}
}
func TestClient_ListMembers(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
params org.ListMemberParams
defaultOrgName string
registerOrgExpectations func(*testing.T, *mock.MockOrganizationsApi)
registerUserExpectations func(*testing.T, *mock.MockUsersApi)
expectedOut []string
expectedErr string
}{
{
name: "no members",
defaultOrgName: "my-org",
registerOrgExpectations: func(t *testing.T, orgApi *mock.MockOrganizationsApi) {
orgApi.EXPECT().GetOrgs(gomock.Any()).Return(api.ApiGetOrgsRequest{ApiService: orgApi})
orgApi.EXPECT().GetOrgsExecute(tmock.MatchedBy(func(in api.ApiGetOrgsRequest) bool {
return assert.Equal(t, "my-org", *in.GetOrg())
})).Return(api.Organizations{
Orgs: &[]api.Organization{{Id: api.PtrString(id1.String())}},
}, nil)
req := api.ApiGetOrgsIDMembersRequest{ApiService: orgApi}.OrgID(id1.String())
orgApi.EXPECT().GetOrgsIDMembers(gomock.Any(), gomock.Eq(id1.String())).Return(req)
orgApi.EXPECT().GetOrgsIDMembersExecute(gomock.Eq(req)).Return(api.ResourceMembers{}, nil)
},
},
{
name: "one member",
params: org.ListMemberParams{
OrgName: "org",
},
defaultOrgName: "my-org",
registerOrgExpectations: func(t *testing.T, orgApi *mock.MockOrganizationsApi) {
orgApi.EXPECT().GetOrgs(gomock.Any()).Return(api.ApiGetOrgsRequest{ApiService: orgApi})
orgApi.EXPECT().GetOrgsExecute(tmock.MatchedBy(func(in api.ApiGetOrgsRequest) bool {
return assert.Equal(t, "org", *in.GetOrg())
})).Return(api.Organizations{
Orgs: &[]api.Organization{{Id: api.PtrString(id1.String())}},
}, nil)
req := api.ApiGetOrgsIDMembersRequest{ApiService: orgApi}.OrgID(id1.String())
orgApi.EXPECT().GetOrgsIDMembers(gomock.Any(), gomock.Eq(id1.String())).Return(req)
orgApi.EXPECT().GetOrgsIDMembersExecute(gomock.Eq(req)).
Return(api.ResourceMembers{Users: &[]api.ResourceMember{{Id: api.PtrString(id2.String())}}}, nil)
},
registerUserExpectations: func(t *testing.T, userApi *mock.MockUsersApi) {
req := api.ApiGetUsersIDRequest{ApiService: userApi}.UserID(id2.String())
userApi.EXPECT().GetUsersID(gomock.Any(), gomock.Eq(id2.String())).Return(req)
userApi.EXPECT().GetUsersIDExecute(gomock.Eq(req)).Return(api.UserResponse{
Id: api.PtrString(id2.String()),
Name: "user1",
Status: api.PtrString("active"),
}, nil)
},
expectedOut: []string{`2222222222222222\s+user1\s+member\s+active`},
},
{
name: "many members",
params: org.ListMemberParams{
OrgID: id1,
},
// NOTE: We previously saw a deadlock when # members was > 10, so test that here.
registerOrgExpectations: func(t *testing.T, orgApi *mock.MockOrganizationsApi) {
req := api.ApiGetOrgsIDMembersRequest{ApiService: orgApi}.OrgID(id1.String())
orgApi.EXPECT().GetOrgsIDMembers(gomock.Any(), gomock.Eq(id1.String())).Return(req)
members := make([]api.ResourceMember, 11)
for i := 0; i < 11; i++ {
members[i] = api.ResourceMember{Id: api.PtrString(fmt.Sprintf("%016d", i))}
}
orgApi.EXPECT().GetOrgsIDMembersExecute(gomock.Eq(req)).Return(api.ResourceMembers{Users: &members}, nil)
},
registerUserExpectations: func(t *testing.T, userApi *mock.MockUsersApi) {
for i := 0; i < 11; i++ {
id := fmt.Sprintf("%016d", i)
status := "active"
if i%2 == 0 {
status = "inactive"
}
req := api.ApiGetUsersIDRequest{ApiService: userApi}.UserID(id)
userApi.EXPECT().GetUsersID(gomock.Any(), gomock.Eq(id)).Return(req)
userApi.EXPECT().GetUsersIDExecute(gomock.Eq(req)).Return(api.UserResponse{
Id: &id,
Name: fmt.Sprintf("user%d", i),
Status: &status,
}, nil)
}
},
expectedOut: []string{
`0000000000000000\s+user0\s+member\s+inactive`,
`0000000000000001\s+user1\s+member\s+active`,
`0000000000000002\s+user2\s+member\s+inactive`,
`0000000000000003\s+user3\s+member\s+active`,
`0000000000000004\s+user4\s+member\s+inactive`,
`0000000000000005\s+user5\s+member\s+active`,
`0000000000000006\s+user6\s+member\s+inactive`,
`0000000000000007\s+user7\s+member\s+active`,
`0000000000000008\s+user8\s+member\s+inactive`,
`0000000000000009\s+user9\s+member\s+active`,
`0000000000000010\s+user10\s+member\s+inactive`,
},
},
{
name: "no such org",
defaultOrgName: "my-org",
registerOrgExpectations: func(t *testing.T, orgApi *mock.MockOrganizationsApi) {
orgApi.EXPECT().GetOrgs(gomock.Any()).Return(api.ApiGetOrgsRequest{ApiService: orgApi})
orgApi.EXPECT().GetOrgsExecute(tmock.MatchedBy(func(in api.ApiGetOrgsRequest) bool {
return assert.Equal(t, "my-org", *in.GetOrg())
})).Return(api.Organizations{}, errors.New("not found"))
},
expectedErr: "not found",
},
{
name: "no such user",
params: org.ListMemberParams{
OrgID: id1,
},
registerOrgExpectations: func(t *testing.T, orgApi *mock.MockOrganizationsApi) {
req := api.ApiGetOrgsIDMembersRequest{ApiService: orgApi}.OrgID(id1.String())
orgApi.EXPECT().GetOrgsIDMembers(gomock.Any(), gomock.Eq(id1.String())).Return(req)
orgApi.EXPECT().GetOrgsIDMembersExecute(gomock.Eq(req)).
Return(api.ResourceMembers{Users: &[]api.ResourceMember{{Id: api.PtrString(id2.String())}}}, nil)
},
registerUserExpectations: func(t *testing.T, userApi *mock.MockUsersApi) {
req := api.ApiGetUsersIDRequest{ApiService: userApi}.UserID(id2.String())
userApi.EXPECT().GetUsersID(gomock.Any(), gomock.Eq(id2.String())).Return(req)
userApi.EXPECT().GetUsersIDExecute(gomock.Eq(req)).Return(api.UserResponse{}, errors.New("not found"))
},
expectedErr: "user \"2222222222222222\": not found",
},
{
name: "missing org",
expectedErr: org.ErrMustSpecifyOrg.Error(),
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
ctrl := gomock.NewController(t)
orgApi := mock.NewMockOrganizationsApi(ctrl)
userApi := mock.NewMockUsersApi(ctrl)
if tc.registerOrgExpectations != nil {
tc.registerOrgExpectations(t, orgApi)
}
if tc.registerUserExpectations != nil {
tc.registerUserExpectations(t, userApi)
}
stdout := bytes.Buffer{}
stdio := mock.NewMockStdIO(ctrl)
stdio.EXPECT().Write(gomock.Any()).DoAndReturn(stdout.Write).AnyTimes()
cli := org.Client{
CLI: cmd.CLI{StdIO: stdio, ActiveConfig: config.Config{Org: tc.defaultOrgName}},
OrganizationsApi: orgApi,
UsersApi: userApi,
}
err := cli.ListMembers(context.Background(), &tc.params)
if tc.expectedErr != "" {
require.Error(t, err)
require.Contains(t, err.Error(), tc.expectedErr)
return
}
require.NoError(t, err)
testutils.MatchLines(t, append([]string{`ID\s+Name\s+User Type\s+Status`}, tc.expectedOut...),
strings.Split(stdout.String(), "\n"))
})
}
}
func TestClient_RemoveMembers(t *testing.T) {
t.Parallel()
testCases := []struct {
name string
params org.RemoveMemberParams
defaultOrgName string
registerExpectations func(*testing.T, *mock.MockOrganizationsApi)
expectedOut string
expectedErr string
}{
{
name: "org by ID",
params: org.RemoveMemberParams{
OrgID: id1,
MemberId: id2,
},
defaultOrgName: "my-org",
registerExpectations: func(t *testing.T, orgApi *mock.MockOrganizationsApi) {
req := api.ApiDeleteOrgsIDMembersIDRequest{ApiService: orgApi}.OrgID(id1.String()).UserID(id2.String())
orgApi.EXPECT().
DeleteOrgsIDMembersID(gomock.Any(), gomock.Eq(id1.String()), gomock.Eq(id2.String())).Return(req)
orgApi.EXPECT().DeleteOrgsIDMembersIDExecute(gomock.Eq(req)).Return(nil)
},
expectedOut: "user \"2222222222222222\" has been removed from org \"1111111111111111\"",
},
{
name: "org by name",
params: org.RemoveMemberParams{
OrgName: "org",
MemberId: id2,
},
defaultOrgName: "my-org",
registerExpectations: func(t *testing.T, orgApi *mock.MockOrganizationsApi) {
orgApi.EXPECT().GetOrgs(gomock.Any()).Return(api.ApiGetOrgsRequest{ApiService: orgApi})
orgApi.EXPECT().GetOrgsExecute(tmock.MatchedBy(func(in api.ApiGetOrgsRequest) bool {
return assert.Equal(t, "org", *in.GetOrg())
})).Return(api.Organizations{
Orgs: &[]api.Organization{{Id: api.PtrString(id1.String())}},
}, nil)
req := api.ApiDeleteOrgsIDMembersIDRequest{ApiService: orgApi}.OrgID(id1.String()).UserID(id2.String())
orgApi.EXPECT().
DeleteOrgsIDMembersID(gomock.Any(), gomock.Eq(id1.String()), gomock.Eq(id2.String())).Return(req)
orgApi.EXPECT().DeleteOrgsIDMembersIDExecute(gomock.Eq(req)).Return(nil)
},
expectedOut: "user \"2222222222222222\" has been removed from org \"1111111111111111\"",
},
{
name: "by config org",
params: org.RemoveMemberParams{
MemberId: id2,
},
defaultOrgName: "my-org",
registerExpectations: func(t *testing.T, orgApi *mock.MockOrganizationsApi) {
orgApi.EXPECT().GetOrgs(gomock.Any()).Return(api.ApiGetOrgsRequest{ApiService: orgApi})
orgApi.EXPECT().GetOrgsExecute(tmock.MatchedBy(func(in api.ApiGetOrgsRequest) bool {
return assert.Equal(t, "my-org", *in.GetOrg())
})).Return(api.Organizations{
Orgs: &[]api.Organization{{Id: api.PtrString(id1.String())}},
}, nil)
req := api.ApiDeleteOrgsIDMembersIDRequest{ApiService: orgApi}.OrgID(id1.String()).UserID(id2.String())
orgApi.EXPECT().
DeleteOrgsIDMembersID(gomock.Any(), gomock.Eq(id1.String()), gomock.Eq(id2.String())).Return(req)
orgApi.EXPECT().DeleteOrgsIDMembersIDExecute(gomock.Eq(req)).Return(nil)
},
expectedOut: "user \"2222222222222222\" has been removed from org \"1111111111111111\"",
},
{
name: "no such org",
params: org.RemoveMemberParams{
MemberId: id2,
},
defaultOrgName: "my-org",
registerExpectations: func(t *testing.T, orgApi *mock.MockOrganizationsApi) {
orgApi.EXPECT().GetOrgs(gomock.Any()).Return(api.ApiGetOrgsRequest{ApiService: orgApi})
orgApi.EXPECT().GetOrgsExecute(tmock.MatchedBy(func(in api.ApiGetOrgsRequest) bool {
return assert.Equal(t, "my-org", *in.GetOrg())
})).Return(api.Organizations{}, errors.New("not found"))
},
expectedErr: "not found",
},
{
name: "missing org",
expectedErr: org.ErrMustSpecifyOrg.Error(),
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
t.Parallel()
ctrl := gomock.NewController(t)
api := mock.NewMockOrganizationsApi(ctrl)
if tc.registerExpectations != nil {
tc.registerExpectations(t, api)
}
stdout := bytes.Buffer{}
stdio := mock.NewMockStdIO(ctrl)
stdio.EXPECT().Write(gomock.Any()).DoAndReturn(stdout.Write).AnyTimes()
cli := org.Client{
CLI: cmd.CLI{StdIO: stdio, ActiveConfig: config.Config{Org: tc.defaultOrgName}},
OrganizationsApi: api,
}
err := cli.RemoveMember(context.Background(), &tc.params)
if tc.expectedErr != "" {
require.Error(t, err)
require.Contains(t, err.Error(), tc.expectedErr)
return
}
require.NoError(t, err)
require.Equal(t, tc.expectedOut, strings.TrimSpace(stdout.String()))
})
}
}

View File

@ -0,0 +1,122 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: github.com/influxdata/influx-cli/v2/internal/api (interfaces: UsersApi)
// 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/internal/api"
)
// MockUsersApi is a mock of UsersApi interface.
type MockUsersApi struct {
ctrl *gomock.Controller
recorder *MockUsersApiMockRecorder
}
// MockUsersApiMockRecorder is the mock recorder for MockUsersApi.
type MockUsersApiMockRecorder struct {
mock *MockUsersApi
}
// NewMockUsersApi creates a new mock instance.
func NewMockUsersApi(ctrl *gomock.Controller) *MockUsersApi {
mock := &MockUsersApi{ctrl: ctrl}
mock.recorder = &MockUsersApiMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockUsersApi) EXPECT() *MockUsersApiMockRecorder {
return m.recorder
}
// DeleteUsersID mocks base method.
func (m *MockUsersApi) DeleteUsersID(arg0 context.Context, arg1 string) api.ApiDeleteUsersIDRequest {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "DeleteUsersID", arg0, arg1)
ret0, _ := ret[0].(api.ApiDeleteUsersIDRequest)
return ret0
}
// DeleteUsersID indicates an expected call of DeleteUsersID.
func (mr *MockUsersApiMockRecorder) DeleteUsersID(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteUsersID", reflect.TypeOf((*MockUsersApi)(nil).DeleteUsersID), arg0, arg1)
}
// DeleteUsersIDExecute mocks base method.
func (m *MockUsersApi) DeleteUsersIDExecute(arg0 api.ApiDeleteUsersIDRequest) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "DeleteUsersIDExecute", arg0)
ret0, _ := ret[0].(error)
return ret0
}
// DeleteUsersIDExecute indicates an expected call of DeleteUsersIDExecute.
func (mr *MockUsersApiMockRecorder) DeleteUsersIDExecute(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteUsersIDExecute", reflect.TypeOf((*MockUsersApi)(nil).DeleteUsersIDExecute), arg0)
}
// GetUsersID mocks base method.
func (m *MockUsersApi) GetUsersID(arg0 context.Context, arg1 string) api.ApiGetUsersIDRequest {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetUsersID", arg0, arg1)
ret0, _ := ret[0].(api.ApiGetUsersIDRequest)
return ret0
}
// GetUsersID indicates an expected call of GetUsersID.
func (mr *MockUsersApiMockRecorder) GetUsersID(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUsersID", reflect.TypeOf((*MockUsersApi)(nil).GetUsersID), arg0, arg1)
}
// GetUsersIDExecute mocks base method.
func (m *MockUsersApi) GetUsersIDExecute(arg0 api.ApiGetUsersIDRequest) (api.UserResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetUsersIDExecute", arg0)
ret0, _ := ret[0].(api.UserResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// GetUsersIDExecute indicates an expected call of GetUsersIDExecute.
func (mr *MockUsersApiMockRecorder) GetUsersIDExecute(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetUsersIDExecute", reflect.TypeOf((*MockUsersApi)(nil).GetUsersIDExecute), arg0)
}
// PatchUsersID mocks base method.
func (m *MockUsersApi) PatchUsersID(arg0 context.Context, arg1 string) api.ApiPatchUsersIDRequest {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "PatchUsersID", arg0, arg1)
ret0, _ := ret[0].(api.ApiPatchUsersIDRequest)
return ret0
}
// PatchUsersID indicates an expected call of PatchUsersID.
func (mr *MockUsersApiMockRecorder) PatchUsersID(arg0, arg1 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchUsersID", reflect.TypeOf((*MockUsersApi)(nil).PatchUsersID), arg0, arg1)
}
// PatchUsersIDExecute mocks base method.
func (m *MockUsersApi) PatchUsersIDExecute(arg0 api.ApiPatchUsersIDRequest) (api.UserResponse, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "PatchUsersIDExecute", arg0)
ret0, _ := ret[0].(api.UserResponse)
ret1, _ := ret[1].(error)
return ret0, ret1
}
// PatchUsersIDExecute indicates an expected call of PatchUsersIDExecute.
func (mr *MockUsersApiMockRecorder) PatchUsersIDExecute(arg0 interface{}) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PatchUsersIDExecute", reflect.TypeOf((*MockUsersApi)(nil).PatchUsersIDExecute), arg0)
}

View File

@ -8,6 +8,7 @@ package mock
//go:generate go run github.com/golang/mock/mockgen -package mock -destination api_setup.gen.go github.com/influxdata/influx-cli/v2/internal/api SetupApi
//go:generate go run github.com/golang/mock/mockgen -package mock -destination api_write.gen.go github.com/influxdata/influx-cli/v2/internal/api WriteApi
//go:generate go run github.com/golang/mock/mockgen -package mock -destination api_query.gen.go github.com/influxdata/influx-cli/v2/internal/api QueryApi
//go:generate go run github.com/golang/mock/mockgen -package mock -destination api_users.gen.go github.com/influxdata/influx-cli/v2/internal/api UsersApi
// 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/internal/config Service