]> ruderich.org/simon Gitweb - nsscash/nsscash.git/blob - main.go
nsscash: write state on each successful run
[nsscash/nsscash.git] / main.go
1 // Main file for nsscash
2
3 // Copyright (C) 2019  Simon Ruderich
4 //
5 // This program is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU Affero General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU Affero General Public License for more details.
14 //
15 // You should have received a copy of the GNU Affero General Public License
16 // along with this program.  If not, see <https://www.gnu.org/licenses/>.
17
18 package main
19
20 import (
21         "bytes"
22         "flag"
23         "fmt"
24         "io/ioutil"
25         "log"
26         "os"
27 )
28
29 func main() {
30         flag.Usage = func() {
31                 fmt.Fprintf(os.Stderr,
32                         "usage: %[1]s [options] fetch <config>\n"+
33                                 "usage: %[1]s [options] convert <type> <src> <dst>\n"+
34                                 "",
35                         os.Args[0])
36                 flag.PrintDefaults()
37         }
38         flag.Parse()
39
40         args := flag.Args()
41         if len(args) == 0 {
42                 flag.Usage()
43                 os.Exit(1)
44         }
45
46         switch args[0] {
47         case "fetch":
48                 if len(args) != 2 {
49                         break
50                 }
51
52                 cfg, err := LoadConfig(args[1])
53                 if err != nil {
54                         log.Fatal(err)
55                 }
56                 state, err := LoadState(cfg.StatePath)
57                 if err != nil {
58                         log.Fatal(err)
59                 }
60                 err = handleFiles(cfg, state)
61                 if err != nil {
62                         log.Fatal(err)
63                 }
64                 // NOTE: Make sure to call WriteState() only if there were no
65                 // errors (see WriteState() and README)
66                 err = WriteState(cfg.StatePath, state)
67                 if err != nil {
68                         log.Fatal(err)
69                 }
70                 return
71
72         case "convert":
73                 if len(args) != 4 {
74                         break
75                 }
76
77                 var t FileType
78                 err := t.UnmarshalText([]byte(args[1]))
79                 if err != nil {
80                         log.Fatal(err)
81                 }
82
83                 src, err := ioutil.ReadFile(args[2])
84                 if err != nil {
85                         log.Fatal(err)
86                 }
87                 var x bytes.Buffer
88                 if t == FileTypePlain {
89                         x.Write(src)
90                 } else if t == FileTypePasswd {
91                         pws, err := ParsePasswds(bytes.NewReader(src))
92                         if err != nil {
93                                 log.Fatal(err)
94                         }
95                         err = SerializePasswds(&x, pws)
96                         if err != nil {
97                                 log.Fatal(err)
98                         }
99                 } else if t == FileTypeGroup {
100                         grs, err := ParseGroups(bytes.NewReader(src))
101                         if err != nil {
102                                 log.Fatal(err)
103                         }
104                         err = SerializeGroups(&x, grs)
105                         if err != nil {
106                                 log.Fatal(err)
107                         }
108                 } else {
109                         log.Fatalf("unsupported file type %v", t)
110                 }
111
112                 // We must create the file first or deployFile() will abort
113                 f, err := os.Create(args[3])
114                 if err != nil {
115                         log.Fatal(err)
116                 }
117                 f.Close()
118
119                 err = deployFile(&File{
120                         Type: t,
121                         Url:  args[2],
122                         Path: args[3],
123                         body: x.Bytes(),
124                 })
125                 if err != nil {
126                         log.Fatal(err)
127                 }
128                 return
129         }
130
131         flag.Usage()
132         os.Exit(1)
133 }