source: LATMOS-Accounts/bin/la-cli @ 843

Last change on this file since 843 was 843, checked in by nanardon, 14 years ago
  • fix readline completion
  • add a global quit function
  • Property svn:executable set to *
  • Property svn:keywords set to Id
File size: 6.2 KB
Line 
1#!/usr/bin/perl
2
3use strict;
4use warnings;
5use LATMOS::Accounts;
6use Getopt::Long;
7use Pod::Usage;
8use Term::ReadLine;
9use Text::ParseWords;
10
11=head1 NAME
12
13    la-query - Tools to query base in LATMOS::Accounts system
14
15=head1 SYNOPSIS
16
17    la-query [options] [obj_id]
18
19=item [obj_id] : If present, all set attributes (rw) will be displayed for that obj_id.
20        If none is given, all obj_ids will be printed.
21
22For the default object_type (user), obj_id = login.
23
24Example : la-query lambda
25
26=cut
27
28GetOptions(
29    'c|config=s' => \my $config,
30    'b|base=s'   => \my $base,
31    'noexp'      => \my $noexp,
32    'exp'        => \my $exp,
33    'help'       => sub { pod2usage(0) },
34) or pod2usage();
35
36=head1 OPTIONS
37
38=over 4
39
40=item -c|--config configfile
41
42Use this configuration file instead of the default one.
43
44=item -b|--base basename
45
46Query this specific base instead of the default one.
47
48=item --noexp
49
50Take into account all objects (even non propagated ones, with attribute 'exported'=0)
51
52=item --exp
53
54Take into account only propagated objects (attribute 'exported'=1) (default)
55
56=back
57
58=cut
59
60my $LA = LATMOS::Accounts->new($config, noacl => 1);
61my $labase = $base ? $LA->base($base) : $LA->default_base;
62$labase && $labase->load or die "Cannot load base";
63
64$labase->wexported($noexp ? 0 : 1);
65
66my $term = Term::ReadLine->new('LA CLI');
67my $attribs = $term->Attribs;
68my $OUT = $term->OUT || \*STDOUT;
69
70my $globalenv = LATMOS::Accounts::Clienv->new(
71    {
72        prompt => sub { "LA cli > " },
73    }
74);
75$globalenv->add_func('ls', {
76    help => 'ls object_type - list object of type object_type', 
77    completion => sub {
78        if(!$_[3]) {
79            return grep { /^\Q$_[1]\E/ } $labase->list_supported_objects
80        } else { () }
81    },
82    code => sub {
83        if ($_[1]) {
84            print $OUT map { "$_\n" } $labase->list_objects($_[1]);
85        } else {
86            print $OUT "Object type missing";
87        }
88    },
89});
90$globalenv->add_func('select', {
91    help => 'select object_type - select objects to perform action on it',
92    completion => sub {
93        if ($_[2]) {
94            return grep { /^\Q$_[1]\E/ } $labase->list_objects($_[2]);
95        } else {
96            return grep { /^\Q$_[1]\E/ } $labase->list_supported_objects;
97        }
98    },
99    code => sub {
100        my ($env, $otype, @ids) = @_;
101        my @objs;
102        if (!@ids) {
103            print $OUT 'not enough arguments';
104            return;
105        }
106        foreach (@ids) {
107            my $obj = $labase->get_object($otype, $_) or do {
108                print $OUT "Cannot get $otype $_";
109                return;
110            };
111            push(@objs, $obj);
112        }
113        cli(_obj_env($otype, @objs));
114    },
115});
116$globalenv->add_func('user',  { alias => 'select' });
117$globalenv->add_func('group', { alias => 'select' });
118
119
120sub _obj_env {
121    my ($otype, @objs) = @_;
122    my $objenv = LATMOS::Accounts::Clienv->new(
123        {
124            prompt => sub {
125                sprintf("%s (%s) > ",
126                    $_[0]->{_otype},
127                    @{$_[0]->{_objects}} > 1 ? '...' : $_[0]->{_objects}[0]->id,
128                );
129            },
130        }
131    );
132    $objenv->{_otype} = $otype;
133    $objenv->{_objects} = [ @objs ];
134    $objenv->add_func('show', {
135        help => 'show attributes - show an attributes of object',
136        code => sub {
137            my ($env, $attr) = @_;
138            if (!$attr) {
139                foreach (@{$env->{_objects}}) {
140                    print $OUT $_->dump;
141                }
142            } else {
143                foreach (@{$env->{_objects}}) {
144                    print $OUT sort map { ($_ || '') . "\n" } $_->get_attributes($attr);
145                }
146            }
147        },
148        completion => sub {
149            if (!$_[2]) {
150                return grep { /^\Q$_[1]\E/ }
151                $labase->list_canonical_fields($_[0]->{_otype}, 'r')
152            }
153        },
154    });
155
156    return $objenv;
157}
158
159sub cli {
160    my ($env) = @_;
161    my $prompt = $env->prompt;
162   
163    while (1) {
164        $attribs->{completion_function} = sub {
165            $env->complete($_[0], shellwords(substr($_[1], 0, $_[2])));
166        };
167        defined (my $line = $term->readline($prompt)) or return;
168        $env->run(shellwords($line));
169        $labase->rollback;
170    }
171}
172
173cli($globalenv);
174print "\n";
175
176exit 0;
177
178package LATMOS::Accounts::Clienv;
179
180sub new {
181    my ($class, $env) = @_;
182    bless($env, $class);
183    $env->add_func('quit', { help => 'quit - exit the tool',
184            code => sub { print "\n"; exit(0) }, });
185    $env;
186}
187
188sub prompt {
189    my ($self) = @_;
190    if (!$self->{prompt}) {
191        return "LA cli > ";
192    } else {
193        $self->{prompt}->($self);
194    }
195}
196
197sub add_func {
198    my ($self, $name, $param) = @_;
199    $self->{funcs}{$name} = $param;
200}
201
202sub parse_arg {
203    my ($self, $name, @args) = @_;
204    if ($self->{funcs}{$name}{opt}) {
205        @ARGV = @args;
206    } else {
207        return @args;
208    }
209    return @ARGV;
210}
211
212sub complete {
213    my ($self, $lastw, $name, @args) = @_;
214    if (!$name) {
215        return grep { /^\Q$lastw\E/ } sort
216            ('help', keys %{ $self->{funcs} || {}});
217    } elsif ($name eq 'help') {
218        return grep { /^\Q$lastw\E/ } sort keys %{ $self->{funcs} || {}};
219    } elsif ($self->{funcs}{$name}{alias}) {
220        $self->complete($lastw, $self->{funcs}{$name}{alias}, $name, @args);
221    } elsif ($self->{funcs}{$name}{completion}) {
222        my @pargs = $self->parse_arg($name, @args);
223        return $self->{funcs}{$name}{completion}->($self, $lastw, @pargs);
224    } else {
225        return ();
226    }
227}
228
229sub run {
230    my ($self, $name, @args) = @_;
231    return if (!$name);
232    if ($name eq 'help') {
233        $self->help(@args);
234    } elsif ($self->{funcs}{$name}{alias}) {
235        $self->run($self->{funcs}{$name}{alias}, $name, @args);
236    } elsif ($self->{funcs}{$name}{code}) {
237        my @pargs = $self->parse_arg($name, @args);
238        $self->{funcs}{$name}{code}->($self, @args);
239    }
240}
241
242sub help {
243    my ($self, $name) = @_;
244    if (!$name) {
245        print $OUT join(', ', sort keys %{ $self->{funcs} || {}});
246    } elsif ($self->{funcs}{$name}{alias}) {
247        print $OUT "$name is an alias for `$self->{funcs}{$name}{alias} $name'";
248    } elsif ($self->{funcs}{$name}{help}) {
249        print $OUT $self->{funcs}{$name}{help};
250    } else {
251        print $OUT "No help availlable";
252    }
253}
254
255
2561;
Note: See TracBrowser for help on using the repository browser.