source: LATMOS-Accounts/lib/LATMOS/Accounts/Cli.pm @ 844

Last change on this file since 844 was 844, checked in by nanardon, 14 years ago
  • split la-cli into specific package
  • Property svn:keywords set to Id
File size: 9.2 KB
Line 
1package LATMOS::Accounts::Cli;
2
3use strict;
4use warnings;
5use LATMOS::Accounts::Log;
6use Term::ReadLine;
7use Text::ParseWords;
8
9my $term = Term::ReadLine->new('LA CLI');
10my $OUT = $term->OUT || \*STDOUT;
11
12sub globalenv {
13    my ($labase) = @_;
14    my $env = LATMOS::Accounts::Cli->new({ prompt => sub { "LA cli > " }, },
15        $labase);
16    $env->add_func('ls', {
17            help => 'ls object_type - list object of type object_type', 
18            completion => sub {
19                if(!$_[3]) {
20                    return grep { /^\Q$_[1]\E/ } $_[0]->base->list_supported_objects
21                } else { () }
22            },
23            code => sub {
24                if ($_[1]) {
25                    print $OUT map { "$_\n" } $_[0]->base->list_objects($_[1]);
26                } else {
27                    print $OUT "Object type missing";
28                }
29            },
30        });
31    $env->add_func('select', {
32            help => 'select object_type - select objects to perform action on it',
33            completion => sub {
34                if ($_[2]) {
35                    return $_[0]->base->list_objects($_[2]);
36                } else {
37                    return $_[0]->base->list_supported_objects;
38                }
39            },
40            code => sub {
41                my ($env, $otype, @ids) = @_;
42                my @objs;
43                if (!@ids) {
44                    print $OUT 'not enough arguments';
45                    return;
46                }
47                foreach (@ids) {
48                    my $obj = $env->base->get_object($otype, $_) or do {
49                        print $OUT "Cannot get $otype $_";
50                        return;
51                    };
52                    push(@objs, $obj);
53                }
54                print $OUT "Selecting $otype " . join(', ', @ids);
55                objenv($_[0]->base, $otype, @objs)->cli();
56            },
57        });
58    $env->add_func('user',  { alias => [qw'select user' ] });
59    $env->add_func('group', { alias => [qw'select group'] });
60    return $env
61}
62
63sub objenv {
64    my ($labase, $otype, @objs) = @_;
65    my $objenv = LATMOS::Accounts::Cli->new(
66        {
67            prompt => sub {
68                sprintf("%s (%s) > ",
69                    $_[0]->{_otype},
70                    @{$_[0]->{_objects}} > 1 ? '...' : $_[0]->{_objects}[0]->id,
71                );
72            },
73        },
74        $labase
75    );
76    $objenv->{_otype} = $otype;
77    $objenv->{_objects} = [ @objs ];
78    $objenv->add_func('show', {
79        help => 'show attributes - show an attributes of object',
80        code => sub {
81            my ($env, $attr) = @_;
82            if (!$attr) {
83                foreach (@{$env->{_objects}}) {
84                    print $OUT $_->dump;
85                }
86            } else {
87                foreach (@{$env->{_objects}}) {
88                    print $OUT sort map { ($_ || '') . "\n" } $_->get_attributes($attr);
89                }
90            }
91        },
92        completion => sub {
93            if (!$_[2]) {
94                return $_[0]->base->list_canonical_fields($_[0]->{_otype}, 'r')
95            }
96        },
97    });
98    $objenv->add_func('set', {
99        help => 'set attribute value - set an attributes to single value "value"',
100        code => sub {
101            my ($env, $attr, $value) = @_;
102            foreach (@{$env->{_objects}}) {
103                defined $_->set_c_fields($attr => $value) or do {
104                    $_->base->rollback;
105                    print $OUT "Cannot set $attr to $value for " . $_->id;
106                    return;
107                };
108            }
109            $env->base->commit;
110            print $OUT "done";
111        },
112        completion => sub {
113            my ($env, $lastw, @args) = @_;
114            if (!$args[0]) {
115                return $env->base->list_canonical_fields($env->{_otype}, 'w')
116            } else {
117                for ($args[0]) {
118                    /^manager|managedBy$/ and return
119                        $env->base->search_objects('user');
120                    /^department$/ and return
121                        $env->base->search_objects('group', 'sutype=dpmt');
122                    if (@{$env->{_objects}} == 1) {
123                        return $env->{_objects}[0]->get_attributes($args[0]);
124                    }
125                }
126            }
127        },
128    });
129    if (lc($otype) eq 'user') {
130        $objenv->add_func('group', {
131            help => 'group add|remove goupname',
132            code => sub {
133                my ($env, $action, @groups) = @_;
134                foreach my $obj (@{$env->{_objects}}) {
135                    my %gr;
136                    foreach ($obj->get_attributes('memberOf')) {
137                        $gr{$_} = 1;
138                    }
139                    if ($action eq 'add') {
140                        $gr{$_} = 1 foreach(@groups);
141                    } elsif ($action eq 'remove') {
142                        delete($gr{$_}) foreach(@groups);
143                    } else {
144                        print $OUT 'invalid action';
145                        return;
146                    }
147                    defined $obj->set_c_fields('memberOf' => [ keys %gr ]) or do {
148                        print $OUT "cannot set memberOf attributes for " .
149                        $obj->id;
150                        return;
151                    };
152                }
153                $env->base->commit;
154            },
155            completion => sub {
156                if (!$_[2]) {
157                    return (qw(add remove));
158                } else {
159                    return $_[0]->base->search_objects('group');
160                }
161            },
162        });
163    } elsif ($otype eq 'group') {
164        $objenv->add_func('member', {
165            help => 'member add|remove user',
166            code => sub {
167                my ($env, $action, @groups) = @_;
168                foreach my $obj (@{$env->{_objects}}) {
169                    my %gr;
170                    foreach ($obj->get_attributes('memberUID')) {
171                        $gr{$_} = 1;
172                    }
173                    if ($action eq 'add') {
174                        $gr{$_} = 1 foreach(@groups);
175                    } elsif ($action eq 'remove') {
176                        delete($gr{$_}) foreach(@groups);
177                    } else {
178                        print $OUT 'invalid action';
179                        return;
180                    }
181                    defined $obj->set_c_fields('memberUID' => [ keys %gr ]) or do {
182                        print $OUT "cannot set memberUID attributes for " .
183                        $obj->id;
184                        return;
185                    };
186                }
187                $env->base->commit;
188            },
189            completion => sub {
190                if (!$_[2]) {
191                    return (qw(add remove));
192                } else {
193                    return $_[0]->base->search_objects('user');
194                }
195            },
196        });
197    }
198
199    return $objenv;
200}
201
202
203sub new {
204    my ($class, $env, $labase) = @_;
205    bless($env, $class);
206    $env->{_labase} = $labase;
207    $env->add_func('quit', { help => 'quit - exit the tool',
208            code => sub { print "\n"; exit(0) }, });
209    $env;
210}
211
212sub base { $_[0]->{_labase} }
213
214sub cli {
215    my ($self) = @_;
216    while (1) {
217        $term->Attribs->{completion_function} = sub {
218            $self->complete($_[0], shellwords(substr($_[1], 0, $_[2])));
219        };
220        defined (my $line = $term->readline($self->prompt)) or return;
221        $self->run(shellwords($line));
222        $self->base->rollback;
223    }
224}
225
226sub prompt {
227    my ($self) = @_;
228    if (!$self->{prompt}) {
229        return "LA cli > ";
230    } else {
231        $self->{prompt}->($self);
232    }
233}
234
235sub add_func {
236    my ($self, $name, $param) = @_;
237    $self->{funcs}{$name} = $param;
238}
239
240sub parse_arg {
241    my ($self, $name, @args) = @_;
242    if ($self->{funcs}{$name}{opt}) {
243        @ARGV = @args;
244    } else {
245        return @args;
246    }
247    return @ARGV;
248}
249
250sub complete {
251    my ($self, $lastw, $name, @args) = @_;
252    if (!$name) {
253        return grep { /^\Q$lastw\E/ } sort
254            ('help', keys %{ $self->{funcs} || {}});
255    } elsif ($name eq 'help') {
256        return grep { /^\Q$lastw\E/ } sort keys %{ $self->{funcs} || {}};
257    } elsif ($self->{funcs}{$name}{alias}) {
258        $self->complete($lastw, @{$self->{funcs}{$name}{alias}}, @args);
259    } elsif ($self->{funcs}{$name}{completion}) {
260        my @pargs = $self->parse_arg($name, @args);
261        return map { my $t = $_; $t =~ s/\s/\\ /g; $t } grep { $_ && /^\Q$lastw\E/ } $self->{funcs}{$name}{completion}->($self, $lastw, @pargs);
262    } else {
263        return ();
264    }
265}
266
267sub run {
268    my ($self, $name, @args) = @_;
269    return if (!$name);
270    if ($name eq 'help') {
271        $self->help(@args);
272    } elsif ($self->{funcs}{$name}{alias}) {
273        $self->run(@{$self->{funcs}{$name}{alias}}, @args);
274    } elsif ($self->{funcs}{$name}{code}) {
275        my @pargs = $self->parse_arg($name, @args);
276        $self->{funcs}{$name}{code}->($self, @args);
277    }
278}
279
280sub help {
281    my ($self, $name) = @_;
282    if (!$name) {
283        print $OUT join(', ', sort keys %{ $self->{funcs} || {}});
284    } elsif ($self->{funcs}{$name}{alias}) {
285        print $OUT "$name is an alias for `$self->{funcs}{$name}{alias} $name'";
286    } elsif ($self->{funcs}{$name}{help}) {
287        print $OUT $self->{funcs}{$name}{help};
288    } else {
289        print $OUT "No help availlable";
290    }
291}
292
293
2941;
Note: See TracBrowser for help on using the repository browser.