The Community Forums

Interact with an entire community of cPanel & WHM users!
  1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Tab Completion for the API

Discussion in 'cPanel Developers' started by cP_Sky, Mar 30, 2017.

  1. cP_Sky

    cP_Sky Technical Analyst II
    Staff Member

    Joined:
    Oct 21, 2014
    Messages:
    10
    Likes Received:
    6
    Trophy Points:
    78
    cPanel Access Level:
    Root Administrator
    When performing API commands from the shell, some of the common methods for the APIs are the cPanel API2, WHM API1, and UAPI shell commands.

    In order to make it faster to identify specific calls from the shell, we can quickly add some simple tab completion for the cpapi2, uapi, and whmapi1 bash shell API commands by using the bash completion files below. (auto-setup script at the bottom of the post)

    Please note, these tab completions do not necessarily execute, as they may not be the proper syntax, but rather attempt to provide a reference for the different API commands available.

    They will provide a link to their function documentation if the argument is a complete match:

    Code:
    [root@tab_completion ~]# cpapi2 Email-list([TAB])
    Email-listaliasbackups         Email-listfilterbackups        Email-listmaildomains          Email-listpopssingle
    Email-listautoresponders       Email-listfilters              Email-listmx                   Email-listpopswithdisk
    Email-listdefaultaddresses     Email-listforwards             Email-listmxs                  Email-listpopswithimage
    Email-listdomainforwards       Email-listlists                Email-listpops                 Email-list_system_filter_info
    
    [root@tab_completion ~]# cpapi2 Email-listmxs([TAB])
    
    [root@tab_completion ~]# cpapi2 Email listmxs --user=$userName # https://documentation.cpanel.net/display/SDK/cPanel+API+2+Functions+-+Email%3A%3Alistmxs
    
    ############### /etc/bash_completion.d/cpapi2.bash #################
    Code:
    _cpapi2()
    {
    
      COMPREPLY=()
      ourAPI="cpapi2";
      local cur=${COMP_WORDS[COMP_CWORD]}
      local prev="${COMP_WORDS[COMP_CWORD-1]}"
    
         if grep -q "^$cur$" /root/.cpanel/cpapi2.list
          then
             COMPREPLY=$(/usr/bin/apitabhandler.pl $ourAPI cur=$cur)
           else
            COMPREPLY=( $(compgen -W "$(cat /root/.cpanel/cpapi2.list)" -- $cur))
         fi
    
         if [[ ${prev} == "--user"* ]]
          then
            COMPREPLY=( $(compgen -W "$(awk -F': ' '{print $2}' /etc/trueuserdomains )" -- $cur ))
         fi
         if [[ ${prev} == "domain"* ]]
          then
           userArgName=$(  awk '{print $1}'  <( grep -oP "(?<=user.)[0-9a-zA-Z\-\.\_].*(?=[\s])" <(echo $COMP_LINE ) )   )
           COMPREPLY=( $(compgen -W "$(awk -F':' '{if (/: '$userArgName'==/) print $1}' /etc/userdatadomains )" -- $cur ))
         fi
    }
    complete -F _cpapi2 cpapi2
    
    
    ############### /etc/bash_completion.d/uapi.bash #################
    Code:
    _uapi()
    {
    
      COMPREPLY=()
      ourAPI="uapi";
      local cur=${COMP_WORDS[COMP_CWORD]}
      local prev="${COMP_WORDS[COMP_CWORD-1]}"
    
         if grep -q "^$cur$" /root/.cpanel/uapi.list
          then
             COMPREPLY=$(/usr/bin/apitabhandler.pl $ourAPI cur=$cur)
           else
            COMPREPLY=( $(compgen -W "$(cat /root/.cpanel/uapi.list)" -- $cur))
         fi
    
         if [[ ${prev} == "--user"* ]]
          then
            COMPREPLY=( $(compgen -W "$(awk -F': ' '{print $2}' /etc/trueuserdomains )" -- $cur ))
         fi
         if [[ ${prev} == "domain"* ]]
          then
           userArgName=$(  awk '{print $1}'  <( grep -oP "(?<=user.)[0-9a-zA-Z\-\.\_].*(?=[\s])" <(echo $COMP_LINE ) )   )
           COMPREPLY=( $(compgen -W "$(awk -F':' '{if (/: '$userArgName'==/) print $1}' /etc/userdatadomains )" -- $cur ))
         fi
    }
    complete -F _uapi uapi
    
    
    ############### /etc/bash_completion.d/whmapi1.bash #################
    Code:
    _whmapi1()
    {
      ourAPI="whmapi1";
      local cur=${COMP_WORDS[COMP_CWORD]}
      if grep -q "^$cur$" /root/.cpanel/whmapi1.list
        then
           COMPREPLY=$(/usr/bin/apitabhandler.pl $ourAPI cur=$cur)
         else
          COMPREPLY=( $(compgen -W "$(cat /root/.cpanel/whmapi1.list)" -- $cur))
      fi
    }
    complete -F _whmapi1 whmapi1
    
    ________________________

    These handle for user/domain args, but pass the $cur variable to a perl script if it's a full match on just the Module-Function tab in an attempt to display the documentation syntax, this should be obtained as below:

    Code:
    wget --verbose -O /usr/bin/apitabhandler.pl https://raw.githubusercontent.com/cpanelsky/apitabs/master/apitabhandler.pl
    
    chmod +x /usr/bin/apitabhandler.pl
    
    We will also need to populate the specific base commands that can be executed per API for our tab completion; we can do that using the commands below, which will add them to the custom files in /root/.cpanel/*api*.list (respectively) :

    cpapi2 commands :
    Code:
       sed 's/::/-/g'  <(/usr/local/cpanel/3rdparty/bin/perl -MCpanel::Template::Plugin::API_Shell -e 'our @apis = (\&Cpanel::Template::Plugin::API_Shell::api2_functions, \&Cpanel::Template::Plugin::API_Shell::whm1_functions, \&Cpanel::Template::Plugin::API_Shell::uapi_functions);  my @elemV =  (0) ; foreach (@elemV) { apiC($_) ;} sub apiC {if($_ == 1){$currentApi="whm1 "}else{if($_ == 2){$currentApi="UAPI "} else {$currentApi="cpapi2 "}}; foreach ( @apis[@_]->() ) { my $snipString = "@$_"; $snipString =~ (s/ /\n/g);  print "\n$snipString\n";}}') > /root/.cpanel/cpapi2.list
    
    whmapi1 commands:
    Code:
       sed 's/::/-/g'  <(/usr/local/cpanel/3rdparty/bin/perl -MCpanel::Template::Plugin::API_Shell -e 'our @apis = (\&Cpanel::Template::Plugin::API_Shell::api2_functions, \&Cpanel::Template::Plugin::API_Shell::whm1_functions, \&Cpanel::Template::Plugin::API_Shell::uapi_functions);  my @elemV =  (1) ; foreach (@elemV) { apiC($_) ;} sub apiC {if($_ == 1){$currentApi="whm1 "}else{if($_ == 2){$currentApi="UAPI "} else {$currentApi="cpapi2 "}}; foreach ( @apis[@_]->() ) { my $snipString = "@$_"; $snipString =~ (s/ /\n/g);  print "\n$snipString\n";}}') > /root/.cpanel/whmapi1.list
    
    uapi commands:
    Code:
       sed 's/::/-/g'  <(/usr/local/cpanel/3rdparty/bin/perl -MCpanel::Template::Plugin::API_Shell -e 'our @apis = (\&Cpanel::Template::Plugin::API_Shell::api2_functions, \&Cpanel::Template::Plugin::API_Shell::whm1_functions, \&Cpanel::Template::Plugin::API_Shell::uapi_functions);  my @elemV =  (2) ; foreach (@elemV) { apiC($_) ;} sub apiC {if($_ == 1){$currentApi="whm1 "}else{if($_ == 2){$currentApi="UAPI "} else {$currentApi="cpapi2 "}}; foreach ( @apis[@_]->() ) { my $snipString = "@$_"; $snipString =~ (s/ /\n/g);  print "\n$snipString\n";}}') > /root/.cpanel/uapi.list
    
    To get the full set of syntax with the command line reference from the documentation portal, the files below should be obtained in addition to the above being created, the above will be first searched, then if matched and tab'd, will expand to the documentation syntax(if it is available) :

    Code:
    wget --verbose -O /root/.cpanel/fullsetcpapi2.list https://raw.githubusercontent.com/cpanelsky/apitabs/master/fullsetcpapi2.list
    wget --verbose -O /root/.cpanel/fullsetuapi.list https://raw.githubusercontent.com/cpanelsky/apitabs/master/fullsetuapi.list
    wget --verbose -O /root/.cpanel/fullsetwhmapi1.list https://raw.githubusercontent.com/cpanelsky/apitabs/master/fullsetwhmapi1.list
    
    Please note : As the /root/.cpanel/ directory is a cPanel managed directory, this may not be an ideal spot, and it may be better to define a known location that is managed and maintained through your infrastructure, which won't necessarily be overwritten in the future.

    In order to have our bash completion files load, we need to populate them into a file as below:

    ############### cat /etc/bash_completion #################
    Code:
    . /etc/bash_completion.d/cpapi2.bash
    . /etc/bash_completion.d/whmapi1.bash
    . /etc/bash_completion.d/uapi.bash
    
    ###############


    If the tab completion isn't working yet, it may be that tab completion is not defined in the shell .rc file for the loaded profile's environment, this can usually be added through a ~/.bashrc or ~/.bash_profile file, for instance as below:

    [#] head -n 3 ~/.bashrc
    Code:
       if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
           . /etc/bash_completion
       fi
    
    Afterwards, you may need to source the noted file(source ~/.bashrc), and then should see that the completion is present for each API(if the source command still didn't work, it may need to have the user log out and log back into the shell to re-load the environment):

    Code:
    [root@tab_completion ~]# uapi ([TAB][TAB])
    Display all 302 possibilities? (y or n)
    
    [root@tab_completion ~]# cpapi2 ([TAB][TAB])
    Display all 372 possibilities? (y or n)
    
    [root@tab_completion ~]# whmapi1 ([TAB][TAB])
    Display all 449 possibilities? (y or n)
    
    
    It should be noted, module level functions are separated by a dash "-" character, this was done as the "::" syntax does not parse through the "complete" command with the provided completion scripts, tabbing with an exact command match should expand and provide the documentation link.

    This can be setup with the script below, though if you have any pre-existing custom bash completion setup, it will replace the /etc/bash_completion(after backing it up), so manual merging may be required in that case.
    Code:
    bash <(curl -sL https://raw.githubusercontent.com/cpanelsky/apitabs/master/apitabs.sh)
    
    A quick demo of it in use can be seen here :



    Feel free to post any issues, errors, or improvements, and enjoy!
     
    #1 cP_Sky, Mar 30, 2017
    Last edited: Apr 2, 2017
    cPMikeB, cPanelBenny, Infopro and 2 others like this.

Share This Page