From 60fd13d25a73fdf86a760dcb54448378f248d831 Mon Sep 17 00:00:00 2001 From: Jef Roosens Date: Thu, 23 Jun 2022 20:26:45 +0200 Subject: [PATCH] feat: added request builder; moved types to own module --- .gitignore | 1 + containers.v | 81 +++++++---------------------------------------- docker.v | 7 ++++ request.v | 51 +++++++++++++++++++++++++++++ types/container.v | 67 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 138 insertions(+), 69 deletions(-) create mode 100644 request.v create mode 100644 types/container.v diff --git a/.gitignore b/.gitignore index 936332c..c7c30d3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ *.so _docs/ +vls.log diff --git a/containers.v b/containers.v index 2d6d1a8..0e69c05 100644 --- a/containers.v +++ b/containers.v @@ -3,79 +3,22 @@ module docker import json import time import net.http { Method } +import types { ContainerListItem } -pub struct Port { - ip string [json: IP] - private_port u16 [json: PrivatePort] - public_port u16 [json: PublicPort] - type_ string [json: Type] +[params] +pub struct ContainerListConfig { + all bool + limit int + size bool + filters map[string][]string } -pub struct HostConfig { - network_mode string [json: NetworkMode] -} +pub fn (mut d DockerConn) container_list(c ContainerListConfig) ?[]ContainerListItem { + d.get('/containers/json') + d.params(c) + d.send()? -pub struct EndpointIpamConfig { - ipv4_address string [json: IPv4Address] - ipv6_address string [json: IPv6Address] - link_local_ips []string [json: LinkLocalIPs] -} - -pub struct EndpointSettings { - ipam_config EndpointIpamConfig [json: IPAMConfig] - links []string [json: Links] - aliases []string [json: Aliases] - network_id string [json: NetworkID] - endpoint_id string [json: EndpointID] - gateway string [json: Gateway] - ip_address string [json: IPAddress] - ip_prefix_len int [json: IPPrefixLen] - ipv6_gateway string [json: IPv6Gateway] - global_ipv6_address string [json: GlobalIPv6Address] - global_ipv6_prefix_len i64 [json: GlobalIPv6PrefixLen] - mac_address string [json: MacAddress] - driver_opts map[string]string [json: DriverOpts] -} - -pub struct NetworkSettings { - networks map[string]EndpointSettings [json: Networks] -} - -pub struct MountPoint { - type_ string [json: Type] - name string [json: Name] - source string [json: Source] - destination string [json: Destination] - driver string [json: Driver] - mode string [json: Mode] - rw bool [json: RW] - propagation string [json: Propagation] -} - -pub struct ContainerListItem { - id string [json: Id] - names []string [json: Names] - image string [json: Image] - image_id string [json: ImageID] - command string [json: Command] - created i64 [json: Created] - ports []Port [json: Ports] - size_rw i64 [json: SizeRw] - size_root_fs i64 [json: SizeRootFs] - labels map[string]string [json: Labels] - state string [json: State] - status string [json: Status] - host_config HostConfig [json: HostConfig] - network_settings NetworkSettings [json: NetworkSettings] - mounts []MountPoint [json: Mounts] -} - -pub fn (mut d DockerConn) container_list() ?[]ContainerListItem { - d.send_request(Method.get, '/containers/json')? - - data := d.read_json_response<[]ContainerListItem>()? - - return data + return d.read_json_response<[]ContainerListItem>() } pub struct NewContainer { diff --git a/docker.v b/docker.v index 2963f0d..3fe6171 100644 --- a/docker.v +++ b/docker.v @@ -17,10 +17,17 @@ const ( api_version = 'v1.41' ) +[heap] pub struct DockerConn { mut: socket &unix.StreamConn reader &io.BufferedReader + // Data for the request that's currently being constructed. + method http.Method + url string + params map[string]string + content_type string + body string } // new_conn creates a new connection to the Docker daemon. diff --git a/request.v b/request.v new file mode 100644 index 0000000..14dd468 --- /dev/null +++ b/request.v @@ -0,0 +1,51 @@ +module docker + +import net.http +import net.urllib +import io + +fn (mut d DockerConn) request(method http.Method, url_str string) { + d.method = method + d.url = url_str + d.params.clear() + d.content_type = '' + d.body = '' +} + +fn (mut d DockerConn) get(url_str string) { + d.request(http.Method.get, url_str) +} + +fn (mut d DockerConn) params(o T) { + $for field in T.fields { + v := o.$(field.name) + + if !isnil(v) { + d.params[field.name] = urllib.query_escape(v.str().replace("'", '"')) + } + } +} + +fn (mut d DockerConn) send() ? { + mut full_url := d.url + + if d.params.len > 0 { + params_str := d.params.keys().map('$it=${d.params[it]}').join('&') + full_url += '?$params_str' + } + + // This is to make sure we actually created a valid URL + parsed_url := urllib.parse(full_url)? + final_url := parsed_url.request_uri() + + req := if d.body == '' { + '$d.method $final_url HTTP/1.1\nHost: localhost\n\n' + } else { + '$d.method $final_url HTTP/1.1\nHost: localhost\nContent-Type: $d.content_type\nContent-Length: $d.body.len\n\n$d.body\n\n' + } + + d.socket.write_string(req)? + + // When starting a new request, the reader needs to be reset. + d.reader = io.new_buffered_reader(reader: d.socket) +} diff --git a/types/container.v b/types/container.v new file mode 100644 index 0000000..795c3d4 --- /dev/null +++ b/types/container.v @@ -0,0 +1,67 @@ +module types + +pub struct Port { + ip string [json: IP] + private_port u16 [json: PrivatePort] + public_port u16 [json: PublicPort] + type_ string [json: Type] +} + +pub struct HostConfig { + network_mode string [json: NetworkMode] +} + +pub struct EndpointIpamConfig { + ipv4_address string [json: IPv4Address] + ipv6_address string [json: IPv6Address] + link_local_ips []string [json: LinkLocalIPs] +} + +pub struct EndpointSettings { + ipam_config EndpointIpamConfig [json: IPAMConfig] + links []string [json: Links] + aliases []string [json: Aliases] + network_id string [json: NetworkID] + endpoint_id string [json: EndpointID] + gateway string [json: Gateway] + ip_address string [json: IPAddress] + ip_prefix_len int [json: IPPrefixLen] + ipv6_gateway string [json: IPv6Gateway] + global_ipv6_address string [json: GlobalIPv6Address] + global_ipv6_prefix_len i64 [json: GlobalIPv6PrefixLen] + mac_address string [json: MacAddress] + driver_opts map[string]string [json: DriverOpts] +} + +pub struct NetworkSettings { + networks map[string]EndpointSettings [json: Networks] +} + +pub struct MountPoint { + type_ string [json: Type] + name string [json: Name] + source string [json: Source] + destination string [json: Destination] + driver string [json: Driver] + mode string [json: Mode] + rw bool [json: RW] + propagation string [json: Propagation] +} + +pub struct ContainerListItem { + id string [json: Id] + names []string [json: Names] + image string [json: Image] + image_id string [json: ImageID] + command string [json: Command] + created i64 [json: Created] + ports []Port [json: Ports] + size_rw i64 [json: SizeRw] + size_root_fs i64 [json: SizeRootFs] + labels map[string]string [json: Labels] + state string [json: State] + status string [json: Status] + host_config HostConfig [json: HostConfig] + network_settings NetworkSettings [json: NetworkSettings] + mounts []MountPoint [json: Mounts] +}