github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/docs/blog/_posts/2018-07-04-go-config.md (about) 1 --- 2 layout: post 3 title: Go Config - A pluggable config framework 4 date: 2018-07-04 09:00:00 5 --- 6 <br> 7 Application configuration has remained largely static for most of our lifetime, using flags, environment variables and files. 8 Any change has usually required restarting the application or significant complexity in code to signal and reload the config. 9 10 Today though, we need more. Restarting an application for a minor configuration seems like overkill. If only one property 11 needs to change, should there not be a better way? Dynamic configuration provides us this option. 12 13 ### Dynamic Config 14 15 Dynamic configuration is the concept by which a system can be modified or extended while it's running. Or in simpler terms 16 the values you require for configuration are automatically updated as they change. 17 18 There's an emergence of tooling for dynamic config mostly driven by key-value stores as the source of truth. Yet when we then 19 need to extract out these values it requires reading individual keys, extracting bytes and handling decoding manually. 20 21 In an ideal world, the configuration system should handle all of these concerns leaving you to focus on what's most important. 22 Your code. 23 24 [**Go Config**](https://github.com/micro/go-config) is a pluggable config framework which looks to solve these problems. 25 26 ### Go Config 27 28 Go Config was born out of a need to simplify configuration for users of micro. Once companies had started building real 29 products that were going to production they echoed the need for the ability to provide configuration for business logic 30 related code or higher level config that shouldn't really necessitate the need for a restart. 31 32 In some cases they had opted for the kubernetes config map or a key-value store such as consul or etcd but handling 33 this configuration in code was not pleasant. They were looking for abstractions similar to Go Micro for their config. 34 35 And so Go Config was created to help with this and much more. 36 37 Go Config is: 38 39 - **Dynamic** - Config is updated transparently in the background 40 - **Pluggable** - Backend sources can be swapped out 41 - **Mergeable** - Multiple sources are merged into a single source of truth 42 - **Observable** - Actively watch the config for changes if you need 43 - **Safe** - Default fallback values can be specified in case they don't exist 44 45 46 It also has the benefit of supporting multiple backend sources and config encoding formats out of the box. See the project 47 [readme](https://github.com/micro/go-config) for details. 48 49 Here's the top level interface which encapsulates all the features mentioned. 50 51 <script src="https://gist.github.com/asim/9365ffa1115d2215a39d9073a2fa0ffc.js"></script> 52 53 Ok so let's break it down and discuss the various concerns in the framework starting with the backend sources. 54 55 ### Source 56 57 A source is a backend from which config is loaded. This could be command line flags, environment variables, a key-value store 58 or any other number of places. 59 60 Go Config provides a simple abstraction over all these sources as a simple interface from which we read data or what we call a ChangeSet. 61 62 <script src="https://gist.github.com/asim/45a0c1f0a40c29c034b1aea796a24c96.js"></script> 63 64 The ChangeSet includes the raw data, it's format, timestamp of creation or last update and the source from which it was loaded. 65 There's also an optional md5 checksum which can be recalculated using the `Sum()` method. 66 67 The simplicity of this interface allows us to easily create a source for any backend, read it's values at any given time or 68 watch for changes where possible. 69 70 ### Encoding 71 72 Config is rarely available in just a single format and people usually have varying preferences on whether it should be stored 73 in json, yaml, toml or something else. We make sure to deal with this in the framework so almost any encoding format can be 74 dealt with. 75 76 The encoder is a very simply interface for handling encoding and decoding different formats. Why wouldn't we reuse existing libraries for 77 this? We do beneath the covers but to ensure we could deal with encoding in an abstract way it made sense to define an interface for it. 78 79 <script src="https://gist.github.com/asim/131349521cbb974c680cd3a245bf13c7.js"></script> 80 81 The current supported formats are json, yaml, toml, xml and hcl. 82 83 ### Reader 84 85 Once we've loaded backend sources and developed a way to decode the variety of config formats we need some way of actually internally 86 representing and reading it. For this we've created a reader. 87 88 The reader manages decoding and merging multiple changesets into a single source of truth. It then provides a value interface which 89 allows you to retrieve native Go types or scan the config into a type of your choosing. 90 91 <script src="https://gist.github.com/asim/e19799834382975b85e1c1813c4e2f89.js"></script> 92 93 Our default internal representation for the merged source is json. 94 95 ### Example 96 97 Let's look at how Go Config actually works in code. Starting with a simple example, let's read config from a file. 98 99 #### Read Config 100 101 Step 1. Define a config.json file 102 103 <script src="https://gist.github.com/asim/f6ddc55133f54f32fe0e9e6813e286dc.js"></script> 104 105 Step 2. Load the file into config 106 107 <script src="https://gist.github.com/asim/716a352d1f2d071fbf14a4fae39fc692.js"></script> 108 109 110 Step 3. Read the values from config 111 112 <script src="https://gist.github.com/asim/d97fe7bd2d16b125c721808e693ba88b.js"></script> 113 114 And that's it! It's really that simple. 115 116 #### Watch Config 117 118 If the config file changes, the next time you read the value it will be different. But what if you want to 119 track that change? You can watch for changes. Let's test it out. 120 121 <script src="https://gist.github.com/asim/d7b98889aaf0342f99c0360641907bc0.js"></script> 122 123 In this example rather than getting a value, we watch it. The next time the value changes we'll receive it and 124 can update our Host struct. 125 126 #### Merge Config 127 128 Another useful feature is the ability to load config from multiple sources which are ordered, merged and overridden. 129 A good example of this would be loading config from a file but overriding via environment variables or flags. 130 131 <script src="https://gist.github.com/asim/e91071c4eaff6e0a081ea43a9cdcf7da.js"></script> 132 133 #### Fallback Values 134 135 In the event some values may not exist or config does not load due to an error, you can set fallback values at 136 time of getting them. 137 138 <script src="https://gist.github.com/asim/fbfef8fcfe16cb252377fae821c03a2e.js"></script> 139 140 ### Summary 141 142 The way in which config is managed and consumed needs to evolve. Go Config looks to do this by drastically simplifying 143 use of dynamic configuration with a pluggable framework. 144 145 Go Config currently supports a number of configuration formats and backend sources but we're always looking for 146 more contributions. If you're interested in contribution please feel free to do so by with a pull request. 147 148 Let Go Config managed the complexity of configuration for you so you can focus on what's really important. Your code. 149 150 To learn more about micro check out the [website](https://m3o.com), follow us on [twitter](https://twitter.com/m3ocloud) or 151 join the [slack](https://slack.m3o.com) community. 152 153 <h6><a href="https://github.com/micro/go-config"><i class="fab fa-github fa-2x"></i> Go Config</a></h6>