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