1package state 2 3import ( 4 "context" 5 "errors" 6 "io/ioutil" 7 "log" 8 "os" 9 "path/filepath" 10 11 "github.com/hetznercloud/cli/internal/hcapi" 12 "github.com/hetznercloud/hcloud-go/hcloud" 13) 14 15type State struct { 16 Token string 17 Endpoint string 18 Context context.Context 19 Config *Config 20 ConfigPath string 21 Debug bool 22 DebugFilePath string 23 24 client *hcloud.Client 25 isoClient *hcapi.ISOClient 26 imageClient *hcapi.ImageClient 27 locationClient *hcapi.LocationClient 28 dataCenterClient *hcapi.DataCenterClient 29 sshKeyClient *hcapi.SSHKeyClient 30 volumeClient *hcapi.VolumeClient 31 certificateClient *hcapi.CertificateClient 32 floatingIPClient *hcapi.FloatingIPClient 33 networkClient *hcapi.NetworkClient 34 loadBalancerClient *hcapi.LoadBalancerClient 35 serverClient *hcapi.ServerClient 36 firewallClient *hcapi.FirewallClient 37} 38 39func New() *State { 40 s := &State{ 41 Context: context.Background(), 42 Config: &Config{}, 43 ConfigPath: DefaultConfigPath, 44 } 45 if p := os.Getenv("HCLOUD_CONFIG"); p != "" { 46 s.ConfigPath = p 47 } 48 return s 49} 50 51var ErrConfigPathUnknown = errors.New("config file path unknown") 52 53func (c *State) ReadEnv() { 54 if s := os.Getenv("HCLOUD_TOKEN"); s != "" { 55 c.Token = s 56 } 57 if s := os.Getenv("HCLOUD_ENDPOINT"); s != "" { 58 c.Endpoint = s 59 } 60 if s := os.Getenv("HCLOUD_DEBUG"); s != "" { 61 c.Debug = true 62 } 63 if s := os.Getenv("HCLOUD_DEBUG_FILE"); s != "" { 64 c.DebugFilePath = s 65 } 66 if s := os.Getenv("HCLOUD_CONTEXT"); s != "" && c.Config != nil { 67 if cfgCtx := c.Config.ContextByName(s); cfgCtx != nil { 68 c.Config.ActiveContext = cfgCtx 69 c.Token = cfgCtx.Token 70 } else { 71 log.Printf("warning: context %q specified in HCLOUD_CONTEXT does not exist\n", s) 72 } 73 } 74} 75 76func (c *State) ReadConfig() error { 77 if c.ConfigPath == "" { 78 return ErrConfigPathUnknown 79 } 80 81 data, err := ioutil.ReadFile(c.ConfigPath) 82 if err != nil { 83 return err 84 } 85 86 if err = UnmarshalConfig(c.Config, data); err != nil { 87 return err 88 } 89 90 if c.Config.ActiveContext != nil { 91 c.Token = c.Config.ActiveContext.Token 92 } 93 if c.Config.Endpoint != "" { 94 c.Endpoint = c.Config.Endpoint 95 } 96 97 return nil 98} 99 100func (c *State) WriteConfig() error { 101 if c.ConfigPath == "" { 102 return ErrConfigPathUnknown 103 } 104 if c.Config == nil { 105 return nil 106 } 107 108 data, err := MarshalConfig(c.Config) 109 if err != nil { 110 return err 111 } 112 if err := os.MkdirAll(filepath.Dir(c.ConfigPath), 0777); err != nil { 113 return err 114 } 115 if err := ioutil.WriteFile(c.ConfigPath, data, 0600); err != nil { 116 return err 117 } 118 return nil 119} 120