Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

podman http api client #51

Merged
merged 34 commits into from
Nov 25, 2020
Merged
Show file tree
Hide file tree
Changes from 26 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
eeb5c43
podman http api client initial commit
towe75 Jul 20, 2020
8c7b915
Merge branch 'master' into f-http-api
towe75 Jul 31, 2020
951c53a
Implement ContainerStart http api call
towe75 Jul 31, 2020
e9d30e1
Implement ContailerDelete http api call
towe75 Aug 2, 2020
d0591f2
Switch podman repo to opensuse
towe75 Aug 2, 2020
de69df0
Implement ContainerInspect and SystemInfo http api calls
towe75 Aug 4, 2020
ab0bcba
Linter
towe75 Aug 5, 2020
5d363e6
License headers
towe75 Aug 6, 2020
4ac65cf
linter, fmt
towe75 Aug 28, 2020
6f05360
Remove separate go setup, rely on base image
towe75 Aug 28, 2020
b2c8e24
Makefile improvements
towe75 Aug 29, 2020
4ca9b04
implemented api v2 create container
towe75 Aug 31, 2020
819cd82
Merged SignalTask support and linter changes
towe75 Sep 1, 2020
84bb809
Improved tmpfs unittest
towe75 Sep 1, 2020
f06c899
Implement ContainerKill / SignalTask http api call
towe75 Sep 6, 2020
c9bb044
Fix SignalTask unittest
towe75 Sep 6, 2020
34807fd
Implement ContainerStats http api call
towe75 Oct 31, 2020
220228c
Code cleanup
towe75 Nov 1, 2020
745fa54
Removed varlink from tests
towe75 Nov 1, 2020
dac3c0d
Remove varlink code
towe75 Nov 1, 2020
c394552
Fix test, lint
towe75 Nov 1, 2020
d49b67f
Pull image before create container
towe75 Nov 2, 2020
4a5c6ee
Fix ContainerInstpect, adopt some loglevels
towe75 Nov 2, 2020
b2cb7a3
Fixed various bugs
towe75 Nov 3, 2020
d1eddc5
Comments
towe75 Nov 5, 2020
3241eb9
Merge branch 'master' into f-http-api
towe75 Nov 5, 2020
205f71e
Code review #51
towe75 Nov 6, 2020
48050ff
Code review #51
towe75 Nov 6, 2020
1e6ba5a
Change license headers to MPL-2
towe75 Nov 6, 2020
072b63b
Code review #51
towe75 Nov 6, 2020
7f6d2f2
Removed license headers completely
towe75 Nov 9, 2020
c952215
Code review #51
towe75 Nov 9, 2020
4e201ba
Added a ClientConfig struct with default values
towe75 Nov 15, 2020
f52f9ee
Review #51
towe75 Nov 16, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 20 additions & 20 deletions .github/machinesetup.sh
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#!/bin/bash -e

# add podman repository
echo "deb http://ppa.launchpad.net/projectatomic/ppa/ubuntu $(lsb_release -cs) main" > /etc/apt/sources.list.d/podman.list
apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 018BA5AD9DF57A4448F0E6CF8BECF1637AD8C79D
# add podman 2.x repository
echo "deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_18.04/ /" | tee /etc/apt/sources.list.d/devel:kubic:libcontainers:stable.list
curl -L https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/stable/xUbuntu_18.04/Release.key | apt-key add -

# Ignore apt-get update errors to avoid failing due to misbehaving repo;
# true errors would fail in the apt-get install phase
Expand All @@ -25,37 +25,37 @@ podman info
echo "====== Podman version:"
podman version

# enable varlink socket (not included in ubuntu package)
cat > /etc/systemd/system/io.podman.service << EOF
# enable http socket (not included in ubuntu package)
cat > /etc/systemd/system/podman.service << EOF
[Unit]
Description=Podman Remote API Service
Requires=io.podman.socket
After=io.podman.socket
Documentation=man:podman-varlink(1)
Description=Podman API Service
Requires=podman.socket
After=podman.socket
Documentation=man:podman-system-service(1)
StartLimitIntervalSec=0

[Service]
Type=simple
ExecStart=/usr/bin/podman varlink unix:%t/podman/io.podman --timeout=60000
TimeoutStopSec=30
KillMode=process
ExecStart=/usr/bin/podman system service

[Install]
WantedBy=multi-user.target
Also=io.podman.socket
Also=podman.socket
EOF

cat > /etc/systemd/system/io.podman.socket << EOF
cat > /etc/systemd/system/podman.socket << EOF
[Unit]
Description=Podman Remote API Socket
Documentation=man:podman-varlink(1)
Description=Podman API Socket
Documentation=man:podman-system-service(1)

[Socket]
ListenStream=%t/podman/io.podman
SocketMode=0600
ListenStream=%t/podman/podman.sock
SocketMode=0660

[Install]
WantedBy=sockets.targett
WantedBy=sockets.target
EOF

systemctl daemon-reload
systemctl start io.podman
# enable http api
systemctl start podman
2 changes: 2 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ linters-settings:
gofmt:
# simplify code: gofmt with `-s` option, true by default
simplify: true
maligned:
suggest-new: true


linters:
Expand Down
32 changes: 13 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,11 @@ cd nomad-driver-podman
- Linux host with `podman` installed
- For rootless containers you need a system supporting cgroup V2 and a few other things, follow [this tutorial](https://github.com/containers/libpod/blob/master/docs/tutorials/rootless_tutorial.md)

You need a varlink enabled podman binary and a system socket activation unit,
see https://podman.io/blogs/2019/01/16/podman-varlink.html.
You need a 2.x podman binary and a system socket activation unit,
see https://www.redhat.com/sysadmin/podmans-new-rest-api

nomad agent, nomad-driver-podman and podman will reside on the same host, so you
do not have to worry about the ssh aspects of podman varlink.
do not have to worry about the ssh aspects of the podman api.

Ensure that nomad can find the plugin, see [plugin_dir](https://www.nomadproject.io/docs/configuration/index.html#plugin_dir)

Expand Down Expand Up @@ -334,22 +334,16 @@ GRUB_CMDLINE_LINUX_DEFAULT="quiet cgroup_enable=memory swapaccount=1 systemd.uni

`sudo update-grub`

ensure that podman varlink is running
```
$ systemctl --user status io.podman
● io.podman.service - Podman Remote API Service
Loaded: loaded (/usr/lib/systemd/user/io.podman.service; disabled; vendor preset: enabled)
Active: active (running) since Wed 2020-07-01 16:01:41 EDT; 7s ago
TriggeredBy: ● io.podman.socket
Docs: man:podman-varlink(1)
Main PID: 25091 (podman)
Tasks: 29 (limit: 18808)
Memory: 17.5M
CPU: 184ms
CGroup: /user.slice/user-1000.slice/user@1000.service/io.podman.service
├─25091 /usr/bin/podman varlink unix:/run/user/1000/podman/io.podman --timeout=60000 --cgroup-manager=systemd
├─25121 /usr/bin/podman varlink unix:/run/user/1000/podman/io.podman --timeout=60000 --cgroup-manager=systemd
└─25125 /usr/bin/podman
ensure that podman socket is running
```
$ systemctl --user status podman.socket
* podman.socket - Podman API Socket
Loaded: loaded (/usr/lib/systemd/user/podman.socket; disabled; vendor preset: disabled)
Active: active (listening) since Sat 2020-10-31 19:21:29 CET; 22h ago
Triggers: * podman.service
Docs: man:podman-system-service(1)
Listen: /run/user/1000/podman/podman.sock (Stream)
CGroup: /user.slice/user-1000.slice/user@1000.service/podman.socket
```

ensure that you have a recent version of [crun](https://github.com/containers/crun/)
Expand Down
110 changes: 110 additions & 0 deletions apiclient/apiclient.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
/*
Copyright 2019 Thomas Weber

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package apiclient

import (
"context"
"fmt"
"io"
"net"
"net/http"
"os"
"strings"
"time"

"github.com/hashicorp/go-hclog"
)

const (
PODMAN_API_VERSION = "v1.0.0"
)

type APIClient struct {
towe75 marked this conversation as resolved.
Show resolved Hide resolved
baseUrl string
httpClient *http.Client
logger hclog.Logger
}

func NewClient(logger hclog.Logger) *APIClient {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GuessSocketPath sounds like we are guessing :) Thoughts on passing in a an Config struct, that contains a logger and socket path? when we initialize the config we can use a renamed version of GuessSocketPath as DefaultSocketPath is one isn't provided

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Method is now renamed to DefaultSocketPath().

Not sure how to approach the config struct. What about moving api initialization from NewPodmanDriver() to SetConfig()? This way we could simply share the drivers config with api or derive a separate struct from driverconfig.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO something like this would be nice, if SetConfig is the entry point it could be built up there, We can provide a DefaultConfig() method in the api package if we are initializing the client first, then calling setconfig but that seems like something to think about for future improvements to only call once

type ClientConfig struct{
         SocketPath string
}

func NewClient(cfg ClientConfig, logger hclog.Logger) *APIClient {

ac := &APIClient{
logger: logger,
}
ac.SetSocketPath(GuessSocketPath())
return ac
}

func (c *APIClient) SetSocketPath(baseUrl string) {
c.logger.Debug("http baseurl", "url", baseUrl)
c.httpClient = &http.Client{
Timeout: 60 * time.Second,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Timeout seems like another good candidate to make configurable

}
if strings.HasPrefix(baseUrl, "unix:") {
c.baseUrl = "http://u"
path := strings.TrimPrefix(baseUrl, "unix:")
c.httpClient.Transport = &http.Transport{
DialContext: func(_ context.Context, _, _ string) (net.Conn, error) {
return net.Dial("unix", path)
},
}
} else {
c.baseUrl = baseUrl
}
}

// GuessSocketPath returns the default unix domain socket path for root or non-root users
func GuessSocketPath() string {
uid := os.Getuid()
// are we root?
if uid == 0 {
return "unix:/run/podman/podman.sock"
}
// not? then let's try the default per-user socket location
return fmt.Sprintf("unix:/run/user/%d/podman/podman.sock", uid)
}

func (c *APIClient) Do(req *http.Request) (*http.Response, error) {
res, err := c.httpClient.Do(req)
return res, err
}

func (c *APIClient) Get(ctx context.Context, path string) (*http.Response, error) {
req, err := http.NewRequest("GET", c.baseUrl+path, nil)
towe75 marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, err
}
req = req.WithContext(ctx)
return c.Do(req)
}

func (c *APIClient) Post(ctx context.Context, path string, body io.Reader) (*http.Response, error) {
req, err := http.NewRequest("POST", c.baseUrl+path, body)
if err != nil {
return nil, err
}
req = req.WithContext(ctx)
req.Header.Set("Content-Type", "application/json")
return c.Do(req)
}

func (c *APIClient) Delete(ctx context.Context, path string) (*http.Response, error) {
req, err := http.NewRequest("DELETE", c.baseUrl+path, nil)
if err != nil {
return nil, err
}
req = req.WithContext(ctx)
return c.Do(req)
}
Loading