|
| 1 | +/* |
| 2 | + * This Source Code Form is subject to the terms of the Mozilla Public |
| 3 | + * License, v. 2.0. If a copy of the MPL was not distributed with this |
| 4 | + * file, You can obtain one at https://mozilla.org/MPL/2.0/. |
| 5 | + */ |
| 6 | + |
| 7 | +package vms |
| 8 | + |
| 9 | +import ( |
| 10 | + "encoding/json" |
| 11 | + "fmt" |
| 12 | + "net/url" |
| 13 | + "strings" |
| 14 | + |
| 15 | + "github.com/bpg/terraform-provider-proxmox/proxmox/types" |
| 16 | +) |
| 17 | + |
| 18 | +// CustomVirtiofsShare handles Virtiofs directory shares. |
| 19 | +type CustomVirtiofsShare struct { |
| 20 | + DirId *string `json:"dirid" url:"dirid"` |
| 21 | + Cache *string `json:"cache,omitempty" url:"cache,omitempty"` |
| 22 | + DirectIo *types.CustomBool `json:"direct-io,omitempty" url:"direct-io,omitempty,int"` |
| 23 | + ExposeAcl *types.CustomBool `json:"expose-acl,omitempty" url:"expose-acl,omitempty,int"` |
| 24 | + ExposeXattr *types.CustomBool `json:"expose-xattr,omitempty" url:"expose-xattr,omitempty,int"` |
| 25 | +} |
| 26 | + |
| 27 | +// CustomVirtiofsShares handles Virtiofs directory shares. |
| 28 | +type CustomVirtiofsShares map[string]*CustomVirtiofsShare |
| 29 | + |
| 30 | +// EncodeValues converts a CustomVirtiofsShare struct to a URL value. |
| 31 | +func (r *CustomVirtiofsShare) EncodeValues(key string, v *url.Values) error { |
| 32 | + if r.DirId == nil { |
| 33 | + return fmt.Errorf("dir_id must be set") |
| 34 | + } |
| 35 | + |
| 36 | + if r.ExposeAcl != nil && *r.ExposeAcl && r.ExposeXattr != nil && !*r.ExposeXattr { |
| 37 | + // expose-xattr implies expose-acl |
| 38 | + return fmt.Errorf("expose_xattr must be omitted or true when expose_acl is enabled") |
| 39 | + } |
| 40 | + |
| 41 | + var values []string |
| 42 | + values = append(values, fmt.Sprintf("dirid=%s", *(r.DirId))) |
| 43 | + |
| 44 | + if r.Cache != nil { |
| 45 | + values = append(values, fmt.Sprintf("cache=%s", *r.Cache)) |
| 46 | + } |
| 47 | + |
| 48 | + if r.DirectIo != nil { |
| 49 | + if *r.DirectIo { |
| 50 | + values = append(values, "direct-io=1") |
| 51 | + } else { |
| 52 | + values = append(values, "direct-io=0") |
| 53 | + } |
| 54 | + } |
| 55 | + |
| 56 | + if r.ExposeAcl != nil { |
| 57 | + if *r.ExposeAcl { |
| 58 | + values = append(values, "expose-acl=1") |
| 59 | + } else { |
| 60 | + values = append(values, "expose-acl=0") |
| 61 | + } |
| 62 | + } |
| 63 | + |
| 64 | + if r.ExposeXattr != nil && (r.ExposeAcl == nil || !*r.ExposeAcl) { |
| 65 | + // expose-acl implies expose-xattr, omit it when unnecessary for consistency |
| 66 | + if *r.ExposeXattr { |
| 67 | + values = append(values, "expose-xattr=1") |
| 68 | + } else { |
| 69 | + values = append(values, "expose-xattr=0") |
| 70 | + } |
| 71 | + } |
| 72 | + |
| 73 | + v.Add(key, strings.Join(values, ",")) |
| 74 | + |
| 75 | + return nil |
| 76 | +} |
| 77 | + |
| 78 | +// EncodeValues converts a CustomVirtiofsShares dict to multiple URL values. |
| 79 | +func (r CustomVirtiofsShares) EncodeValues(key string, v *url.Values) error { |
| 80 | + for s, d := range r { |
| 81 | + if err := d.EncodeValues(s, v); err != nil { |
| 82 | + return fmt.Errorf("failed to encode virtiofs share %s: %w", s, err) |
| 83 | + } |
| 84 | + } |
| 85 | + |
| 86 | + return nil |
| 87 | +} |
| 88 | + |
| 89 | +// UnmarshalJSON converts a CustomVirtiofsShare string to an object. |
| 90 | +func (r *CustomVirtiofsShare) UnmarshalJSON(b []byte) error { |
| 91 | + var s string |
| 92 | + |
| 93 | + if err := json.Unmarshal(b, &s); err != nil { |
| 94 | + return fmt.Errorf("failed to unmarshal CustomVirtiofsShare: %w", err) |
| 95 | + } |
| 96 | + |
| 97 | + pairs := strings.Split(s, ",") |
| 98 | + |
| 99 | + for _, p := range pairs { |
| 100 | + v := strings.Split(strings.TrimSpace(p), "=") |
| 101 | + |
| 102 | + if len(v) == 1 { |
| 103 | + r.DirId = &v[0] |
| 104 | + } else if len(v) == 2 { |
| 105 | + switch v[0] { |
| 106 | + case "dirid": |
| 107 | + r.DirId = &v[1] |
| 108 | + case "cache": |
| 109 | + r.Cache = &v[1] |
| 110 | + case "direct-io": |
| 111 | + bv := types.CustomBool(v[1] == "1") |
| 112 | + r.DirectIo = &bv |
| 113 | + case "expose-acl": |
| 114 | + bv := types.CustomBool(v[1] == "1") |
| 115 | + r.ExposeAcl = &bv |
| 116 | + case "expose-xattr": |
| 117 | + bv := types.CustomBool(v[1] == "1") |
| 118 | + r.ExposeXattr = &bv |
| 119 | + } |
| 120 | + } |
| 121 | + } |
| 122 | + |
| 123 | + // expose-acl implies expose-xattr |
| 124 | + if r.ExposeAcl != nil && *r.ExposeAcl { |
| 125 | + if r.ExposeXattr == nil { |
| 126 | + bv := types.CustomBool(true) |
| 127 | + r.ExposeAcl = &bv |
| 128 | + } else if !*r.ExposeXattr { |
| 129 | + return fmt.Errorf("failed to unmarshal CustomVirtiofsShare: expose-xattr contradicts the value of expose-acl") |
| 130 | + } |
| 131 | + } |
| 132 | + |
| 133 | + return nil |
| 134 | +} |
0 commit comments