Weekday evening, how not to do writing articles, notes. In which I want to share my impressions of meeting Go . All that is written below is the subjective opinion of the author. This article will be useful to those who want to sit down to study Go and will be of little use to developers on it.
My main activity is solving business problems in the environment of a harsh enterprise in java , and I want to learn new and interesting things by my nature, to support my skills, learn new things and not stand still (sort of a linear-> businessman ). And for this reason the look at docker fell long ago.
And on the current project, in some places, I began to introduce docker practices in the environment of developers and testers. And where docker appears, containers appear and I want to know everything from these CPUs to Network I / O about these containers. For all this, I first used the standard bundle of docker ps
and docker stats
. There were some inconveniences due to the fact that these are two separate utilities, but on the whole it was sleepy until I came across a ctop . I think many people who use docker know it.
Running ctop on the machine I saw beautiful like-htop containers with statistics and the ability to view detailed information on the container, with search or sorting. In general, I was extremely pleased.
Until a certain point, the first thing I would like to see in ctop is the healthcheck container, but it was not there. Then docker swarm mode came up and for which I would also like to see statistics on services from ctop .
And here the corrosive reader may wonder, and where is Go , if everything is about docker and personal opinion of the author .
Having the experience of writing / finishing the Linux utilities for myself, I thought, well, since this is in the terminal and this is for the console, then there should be python and now we will quickly add everything that I want.
Going into the repository , I was surprised to see Go there (although it is logical that the docker is written on it). Remembering someone's words from the report about Go that he can learn it in the evening, he continued his efforts in finalizing the program. After reading the documentation and launching examples from this site I sat down at the project.
When I got acquainted with Go , the phrase had slipped somewhere that he was "laconic and easy to support" and I agree with these statements.
The first thing that looked unusual, but comfortable - it is GOPATH . About the setting and the concepts themselves are very well described here .
Also, an interesting approach to the organization and structuring of packages and access level. In particular, the declaration of public and private methods through upper and lower case letters and the implementation of interfaces. And I was incredibly pleased with the signs, as a person from the world of java .
Dependency management, at least on this project, did not cause any particular difficulties (even though Go was blamed for the lack of a package manager). All that is specified in the import
construct is collected in the GOPATH folder in the scr directory and dependencies can already be used. Separately, it should be noted that the dependency can be directly on a project with GitHub and it is not much different from the dependency on some own module (the import logic is minimized):
import ( "fmt" "strings" "sync" "github.com/bcicen/ctop/connector/collector" api "github.com/fsouza/go-dockerclient" "github.com/bcicen/ctop/config" "context" "github.com/bcicen/ctop/entity" "github.com/docker/docker/api/types/swarm" )
As for ctop , it turned out to be rather simple in its structure, for which a special thanks to its chief engineer.
The structure of the project is divided into three major parts:
connector - an interface for connecting to various services provided information about containers. For example, docker, opencontainer, kubernates and others.
In the connector directory, the main.go
class has been main.go
, which describes the interface of our connector:
package connector type Connector interface { All() container.Containers Get(string) (*container.Container, bool) }
And in order to import it, we need to create another file, for example, docker.go
and, for the NewDocker()
method, specify the return type of the interface and return the address for it.
And then implement all the methods listed. I liked that in the framework of one class it is possible to describe several implementations of the interface and this is a normal practice.
package docker type Docker struct { client *api.Client containers map[string]*container.Container needsRefresh chan string lock sync.RWMutex } func NewDocker() Connector { client, err := api.NewClientFromEnv() if err != nil { panic(err) } cm := &Docker{ client: client, containers: make(map[string]*container.Container), needsRefresh: make(chan string, 60), lock: sync.RWMutex{}, } return cm } func (cm *Docker) All() (containers container.Containers) { cm.lock.Lock() for _, c := range cm.containers { containers = append(containers, c) } containers.Sort() containers.Filter() cm.lock.Unlock() return containers } func (cm *Docker) Get(id string) (*container.Container, bool) { cm.lock.Lock() c, ok := cm.containers[id] cm.lock.Unlock() return c, ok }
In parentheses after func
indicated for which structure the method is implemented, it looks very convenient.
cwidgets - individual graphic elements from which the ready interface is assembled.
grid / cursor - a package that in itself gathers everything together for display on the screen and provides access and control methods.
Implementing the healthcheck mapping was pretty simple. In docker.go
, docker.go
added the health
attribute to the meta information, which we read through api, similar to the docker inspect <CONTAINER>
functional docker inspect <CONTAINER>
. And depending on the value, we change the text color in the NAME
column.
But the addition of swarm mode was more interesting.
In the swarm mode, the concepts of node
, service
and task
appear. And between them it is necessary to display the relationship of who is where. And this was not provided in ctop . And here really felt a good maintainability of the code. The container structure contained methods for accessing meta information and a graphical interface, which are easily put into a separate interface, which is necessary for new concepts introduced. The interface looks like this:
package entity import ( "github.com/bcicen/ctop/logging" "github.com/bcicen/ctop/connector/collector" "github.com/bcicen/ctop/models" ) var ( log = logging.Init() ) type Entity interface { SetState(s string) Logs() collector.LogCollector GetMetaEntity() Meta GetId() string GetMetrics() models.Metrics }
Here we declare the log
variable common to all classes implementing this interface and describe the interface contract: the method of changing the state of an element, access to the log of a specific element through the variable log
, access to the meta information of the element and access to its metrics.
After describing the interface, implementing it for all structs and replacing the old container
with a new entity
in the grid
methods, one interesting question surfaced. Docker currently does not provide the ability to get information about the use of resources from a remote node using api tools. Therefore, I stopped at the implementation of the output of the structure of the swarm cluster and the healthcheck of the running tasks.
In general, I was very pleased with the use of Go in the project, the language was really made practical and concise. He recalled with something a mixture of Python and C ++ , from which they tried to take the best. You can really learn it in the evening. But in order to start writing on it in the evening, one must have an adequate background, and I would not advise him to be the first language to learn. To understand his convenience, you must probably come. I also selected a niche for myself for the language in the form of writing services (it was probably designed for this purpose).
As for ctop , the mine request received a pull request with the healthcheck map, now I plan to finish the mapping of the swarm structure. I will be glad to suggestions how to implement the reading of container metrics from remote nodes.
Source: https://habr.com/ru/post/336572/
All Articles