■ ■ ■ ■ ■ ■ ■
cmd/portforward/portforward.go
| skipped 4 lines |
5 | 5 | | "errors" |
6 | 6 | | "fmt" |
7 | 7 | | "io" |
| 8 | + | "net" |
| 9 | + | "os" |
| 10 | + | "os/signal" |
8 | 11 | | "strings" |
| 12 | + | "syscall" |
9 | 13 | | |
10 | 14 | | "github.com/docker/docker/api/types" |
11 | 15 | | "github.com/docker/docker/api/types/container" |
12 | 16 | | dockerclient "github.com/docker/docker/client" |
13 | 17 | | "github.com/docker/go-connections/nat" |
| 18 | + | "github.com/sirupsen/logrus" |
14 | 19 | | "github.com/spf13/cobra" |
15 | 20 | | |
16 | 21 | | "github.com/iximiuz/cdebug/pkg/cmd" |
| skipped 63 lines |
80 | 85 | | return err |
81 | 86 | | } |
82 | 87 | | |
83 | | - | forwardings, err := prepareForwardings(target, opts.forwardings) |
| 88 | + | forwardings, err := parseForwardings(target, opts.forwardings) |
84 | 89 | | if err != nil { |
85 | 90 | | return err |
86 | 91 | | } |
| skipped 3 lines |
90 | 95 | | return err |
91 | 96 | | } |
92 | 97 | | |
| 98 | + | fmt.Println("forwardings") |
| 99 | + | util.PrettyPrint(forwardings) |
| 100 | + | |
| 101 | + | fmt.Println("forwardings.toDockerPortSpecs()") |
| 102 | + | util.PrettyPrint(forwardings.toDockerPortSpecs()) |
| 103 | + | |
| 104 | + | fmt.Println("exposedPorts") |
| 105 | + | util.PrettyPrint(exposedPorts) |
| 106 | + | |
| 107 | + | fmt.Println("portBindings") |
| 108 | + | util.PrettyPrint(portBindings) |
| 109 | + | |
93 | 110 | | // TODO: Iterate over all forwardings. |
94 | 111 | | resp, err := client.ContainerCreate( |
95 | 112 | | ctx, |
| skipped 2 lines |
98 | 115 | | Entrypoint: []string{"socat"}, |
99 | 116 | | Cmd: []string{ |
100 | 117 | | fmt.Sprintf("TCP-LISTEN:%s,fork", forwardings[0].targetPort), |
101 | | - | fmt.Sprintf("TCP-CONNECT:%s:%d", forwardings[0].targetIP, forwardings[0].targetPort), |
| 118 | + | fmt.Sprintf("TCP-CONNECT:%s:%s", forwardings[0].targetIP, forwardings[0].targetPort), |
102 | 119 | | }, |
103 | 120 | | ExposedPorts: exposedPorts, |
104 | 121 | | }, |
| skipped 13 lines |
118 | 135 | | return fmt.Errorf("cannot start port-forwarder container: %w", err) |
119 | 136 | | } |
120 | 137 | | |
121 | | - | // TODO: Handle ctrl + C and other signals. |
| 138 | + | forwarder, err := client.ContainerInspect(ctx, resp.ID) |
| 139 | + | if err != nil { |
| 140 | + | return fmt.Errorf("cannot inspect forwarder container: %w", err) |
| 141 | + | } |
| 142 | + | // TODO: Multi-network support. |
| 143 | + | targetIP := target.NetworkSettings.Networks["bridge"].IPAddress |
| 144 | + | for from, frontends := range forwarder.NetworkSettings.Ports { |
| 145 | + | for _, frontend := range frontends { |
| 146 | + | fmt.Printf("Forwarding %s to %s's %s:%s\n", net.JoinHostPort(frontend.HostIP, frontend.HostPort), target.Name[1:], targetIP, from) |
| 147 | + | } |
| 148 | + | } |
| 149 | + | |
| 150 | + | sigCh := make(chan os.Signal, 128) |
| 151 | + | signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM) |
| 152 | + | defer close(sigCh) |
| 153 | + | |
| 154 | + | go func() { |
| 155 | + | for _ = range sigCh { |
| 156 | + | fmt.Println("Exiting...") |
| 157 | + | if err := client.ContainerKill(ctx, resp.ID, "KILL"); err != nil { |
| 158 | + | logrus.WithError(err).Warn("Cannot kill forwarder container") |
| 159 | + | } |
| 160 | + | break |
| 161 | + | } |
| 162 | + | }() |
| 163 | + | |
122 | 164 | | forwarderStatusCh, forwarderErrCh := client.ContainerWait(ctx, resp.ID, container.WaitConditionNotRunning) |
123 | 165 | | // targetStatusCh, targetErrCh := client.ContainerWait(ctx, target.ID, container.WaitConditionNotRunning) |
124 | 166 | | select { |
| skipped 41 lines |
166 | 208 | | return spec |
167 | 209 | | } |
168 | 210 | | |
169 | | - | func prepareForwardings( |
| 211 | + | func parseForwardings( |
170 | 212 | | target types.ContainerJSON, |
171 | 213 | | forwardings []string, |
172 | 214 | | ) (forwardingList, error) { |
| skipped 57 lines |