github.com/vtorhonen/terraform@v0.9.0-beta2.0.20170307220345-5d894e4ffda7/builtin/providers/influxdb/resource_user.go (about) 1 package influxdb 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/hashicorp/terraform/helper/schema" 8 "github.com/influxdata/influxdb/client" 9 ) 10 11 func resourceUser() *schema.Resource { 12 return &schema.Resource{ 13 Create: createUser, 14 Read: readUser, 15 Update: updateUser, 16 Delete: deleteUser, 17 18 Schema: map[string]*schema.Schema{ 19 "name": &schema.Schema{ 20 Type: schema.TypeString, 21 Required: true, 22 ForceNew: true, 23 }, 24 "password": &schema.Schema{ 25 Type: schema.TypeString, 26 Required: true, 27 ForceNew: true, 28 }, 29 "admin": &schema.Schema{ 30 Type: schema.TypeBool, 31 Optional: true, 32 Computed: true, 33 }, 34 "grant": &schema.Schema{ 35 Type: schema.TypeList, 36 Optional: true, 37 Elem: &schema.Resource{ 38 Schema: map[string]*schema.Schema{ 39 "database": &schema.Schema{ 40 Type: schema.TypeString, 41 Required: true, 42 }, 43 "privilege": &schema.Schema{ 44 Type: schema.TypeString, 45 Required: true, 46 }, 47 }, 48 }, 49 }, 50 }, 51 } 52 } 53 54 func createUser(d *schema.ResourceData, meta interface{}) error { 55 conn := meta.(*client.Client) 56 57 name := d.Get("name").(string) 58 password := d.Get("password").(string) 59 60 is_admin := d.Get("admin").(bool) 61 admin_privileges := "" 62 if is_admin { 63 admin_privileges = "WITH ALL PRIVILEGES" 64 } 65 66 queryStr := fmt.Sprintf("CREATE USER %s WITH PASSWORD '%s' %s", name, password, admin_privileges) 67 query := client.Query{ 68 Command: queryStr, 69 } 70 71 resp, err := conn.Query(query) 72 if err != nil { 73 return err 74 } 75 if resp.Err != nil { 76 return resp.Err 77 } 78 79 d.SetId(fmt.Sprintf("influxdb-user:%s", name)) 80 81 if v, ok := d.GetOk("grant"); ok { 82 grants := v.([]interface{}) 83 for _, vv := range grants { 84 grant := vv.(map[string]interface{}) 85 if err := grantPrivilegeOn(conn, grant["privilege"].(string), grant["database"].(string), name); err != nil { 86 return err 87 } 88 } 89 } 90 91 return readUser(d, meta) 92 } 93 94 func exec(conn *client.Client, query string) error { 95 resp, err := conn.Query(client.Query{ 96 Command: query, 97 }) 98 if err != nil { 99 return err 100 } 101 if resp.Err != nil { 102 return resp.Err 103 } 104 return nil 105 } 106 107 func grantPrivilegeOn(conn *client.Client, privilege, database, user string) error { 108 return exec(conn, fmt.Sprintf("GRANT %s ON %s TO %s", privilege, quoteIdentifier(database), user)) 109 } 110 111 func revokePrivilegeOn(conn *client.Client, privilege, database, user string) error { 112 return exec(conn, fmt.Sprintf("REVOKE %s ON %s FROM %s", privilege, quoteIdentifier(database), user)) 113 } 114 115 func grantAllOn(conn *client.Client, user string) error { 116 return exec(conn, fmt.Sprintf("GRANT ALL PRIVILEGES TO %s", user)) 117 } 118 119 func revokeAllOn(conn *client.Client, user string) error { 120 return exec(conn, fmt.Sprintf("REVOKE ALL PRIVILEGES FROM %s", user)) 121 } 122 123 func readUser(d *schema.ResourceData, meta interface{}) error { 124 conn := meta.(*client.Client) 125 name := d.Get("name").(string) 126 127 // InfluxDB doesn't have a command to check the existence of a single 128 // User, so we instead must read the list of all Users and see 129 // if ours is present in it. 130 query := client.Query{ 131 Command: "SHOW USERS", 132 } 133 134 resp, err := conn.Query(query) 135 if err != nil { 136 return err 137 } 138 if resp.Err != nil { 139 return resp.Err 140 } 141 142 var found = false 143 for _, result := range resp.Results[0].Series[0].Values { 144 if result[0] == name { 145 found = true 146 d.Set("admin", result[1].(bool)) 147 break 148 } 149 } 150 151 if !found { 152 // If we fell out here then we didn't find our User in the list. 153 d.SetId("") 154 155 return nil 156 } 157 158 return readGrants(d, meta) 159 } 160 161 func readGrants(d *schema.ResourceData, meta interface{}) error { 162 conn := meta.(*client.Client) 163 name := d.Get("name").(string) 164 165 query := client.Query{ 166 Command: fmt.Sprintf("SHOW GRANTS FOR %s", name), 167 } 168 169 resp, err := conn.Query(query) 170 if err != nil { 171 return err 172 } 173 174 if resp.Err != nil { 175 return resp.Err 176 } 177 178 var grants = []map[string]string{} 179 for _, result := range resp.Results[0].Series[0].Values { 180 if result[1].(string) != "NO PRIVILEGES" { 181 var grant = map[string]string{ 182 "database": result[0].(string), 183 "privilege": strings.ToLower(result[1].(string)), 184 } 185 grants = append(grants, grant) 186 } 187 } 188 d.Set("grant", grants) 189 return nil 190 } 191 192 func updateUser(d *schema.ResourceData, meta interface{}) error { 193 conn := meta.(*client.Client) 194 name := d.Get("name").(string) 195 196 if d.HasChange("admin") { 197 if !d.Get("admin").(bool) { 198 revokeAllOn(conn, name) 199 } else { 200 grantAllOn(conn, name) 201 } 202 } 203 204 if d.HasChange("grant") { 205 oldGrantV, newGrantV := d.GetChange("grant") 206 oldGrant := oldGrantV.([]interface{}) 207 newGrant := newGrantV.([]interface{}) 208 209 for _, oGV := range oldGrant { 210 oldGrant := oGV.(map[string]interface{}) 211 212 exists := false 213 privilege := oldGrant["privilege"].(string) 214 for _, nGV := range newGrant { 215 newGrant := nGV.(map[string]interface{}) 216 217 if newGrant["database"].(string) == oldGrant["database"].(string) { 218 exists = true 219 privilege = newGrant["privilege"].(string) 220 } 221 } 222 223 if !exists { 224 revokePrivilegeOn(conn, oldGrant["privilege"].(string), oldGrant["database"].(string), name) 225 } else { 226 if privilege != oldGrant["privilege"].(string) { 227 grantPrivilegeOn(conn, privilege, oldGrant["database"].(string), name) 228 } 229 } 230 } 231 232 for _, nGV := range newGrant { 233 newGrant := nGV.(map[string]interface{}) 234 235 exists := false 236 for _, oGV := range oldGrant { 237 oldGrant := oGV.(map[string]interface{}) 238 239 exists = exists || (newGrant["database"].(string) == oldGrant["database"].(string) && newGrant["privilege"].(string) == oldGrant["privilege"].(string)) 240 } 241 242 if !exists { 243 grantPrivilegeOn(conn, newGrant["privilege"].(string), newGrant["database"].(string), name) 244 } 245 } 246 } 247 248 return readUser(d, meta) 249 } 250 251 func deleteUser(d *schema.ResourceData, meta interface{}) error { 252 conn := meta.(*client.Client) 253 name := d.Get("name").(string) 254 255 queryStr := fmt.Sprintf("DROP USER %s", name) 256 query := client.Query{ 257 Command: queryStr, 258 } 259 260 resp, err := conn.Query(query) 261 if err != nil { 262 return err 263 } 264 if resp.Err != nil { 265 return resp.Err 266 } 267 268 d.SetId("") 269 270 return nil 271 }