Enhance logging driver and ctr tasks to support windows

Signed-off-by: Maksim An <maksiman@microsoft.com>
This commit is contained in:
Maksim An 2020-11-20 00:55:54 -08:00 committed by Maksim An
parent 83f8d6126b
commit ddb5e1651a
4 changed files with 170 additions and 43 deletions

View File

@ -18,6 +18,7 @@ package tasks
import (
gocontext "context"
"net/url"
"time"
"github.com/containerd/console"
@ -67,6 +68,12 @@ func NewTask(ctx gocontext.Context, client *containerd.Client, container contain
ioCreator = cio.NewCreator(append([]cio.Opt{cio.WithStreams(con, con, nil), cio.WithTerminal}, ioOpts...)...)
} else if nullIO {
ioCreator = cio.NullIO
} else if logURI != "" {
u, err := url.Parse(logURI)
if err != nil {
return nil, err
}
ioCreator = cio.LogURI(u)
} else {
ioCreator = cio.NewCreator(append([]cio.Opt{cio.WithStdio}, ioOpts...)...)
}

View File

@ -1,5 +1,3 @@
// +build !windows
/*
Copyright The containerd Authors.
@ -20,12 +18,7 @@ package logging
import (
"context"
"fmt"
"io"
"os"
"os/signal"
"golang.org/x/sys/unix"
)
// Config of the container logs
@ -38,39 +31,3 @@ type Config struct {
// LoggerFunc is implemented by custom v2 logging binaries
type LoggerFunc func(context.Context, *Config, func() error) error
// Run the logging driver
func Run(fn LoggerFunc) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
config := &Config{
ID: os.Getenv("CONTAINER_ID"),
Namespace: os.Getenv("CONTAINER_NAMESPACE"),
Stdout: os.NewFile(3, "CONTAINER_STDOUT"),
Stderr: os.NewFile(4, "CONTAINER_STDERR"),
}
var (
s = make(chan os.Signal, 32)
errCh = make(chan error, 1)
wait = os.NewFile(5, "CONTAINER_WAIT")
)
signal.Notify(s, unix.SIGTERM)
go func() {
errCh <- fn(ctx, config, wait.Close)
}()
for {
select {
case <-s:
cancel()
case err := <-errCh:
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
os.Exit(0)
}
}
}

View File

@ -0,0 +1,64 @@
// +build !windows
/*
Copyright The containerd Authors.
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 logging
import (
"context"
"fmt"
"os"
"os/signal"
"golang.org/x/sys/unix"
)
// Run the logging driver
func Run(fn LoggerFunc) {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
config := &Config{
ID: os.Getenv("CONTAINER_ID"),
Namespace: os.Getenv("CONTAINER_NAMESPACE"),
Stdout: os.NewFile(3, "CONTAINER_STDOUT"),
Stderr: os.NewFile(4, "CONTAINER_STDERR"),
}
var (
sigCh = make(chan os.Signal, 32)
errCh = make(chan error, 1)
wait = os.NewFile(5, "CONTAINER_WAIT")
)
signal.Notify(sigCh, unix.SIGTERM)
go func() {
errCh <- fn(ctx, config, wait.Close)
}()
for {
select {
case <-sigCh:
cancel()
case err := <-errCh:
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
os.Exit(0)
}
}
}

View File

@ -0,0 +1,99 @@
// +build windows
/*
Copyright The containerd Authors.
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 logging
import (
"context"
"fmt"
"net"
"os"
"os/signal"
"syscall"
"github.com/Microsoft/go-winio"
"github.com/pkg/errors"
)
// Run the logging driver
func Run(fn LoggerFunc) {
err := runInternal(fn)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
os.Exit(0)
}
func runInternal(fn LoggerFunc) error {
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
var (
soutPipe, serrPipe, waitPipe string
sout, serr, wait net.Conn
ok bool
err error
)
if soutPipe, ok = os.LookupEnv("CONTAINER_STDOUT"); !ok {
return errors.New("'CONTAINER_STDOUT' environment variable missing")
}
if sout, err = winio.DialPipeContext(ctx, soutPipe); err != nil {
return errors.Wrap(err, "unable to dial stdout pipe")
}
if serrPipe, ok = os.LookupEnv("CONTAINER_STDERR"); !ok {
return errors.New("'CONTAINER_STDERR' environment variable missing")
}
if serr, err = winio.DialPipeContext(ctx, serrPipe); err != nil {
return errors.Wrap(err, "unable to dial stderr pipe")
}
waitPipe = os.Getenv("CONTAINER_WAIT")
if wait, err = winio.DialPipeContext(ctx, waitPipe); err != nil {
return errors.Wrap(err, "unable to dial wait pipe")
}
config := &Config{
ID: os.Getenv("CONTAINER_ID"),
Namespace: os.Getenv("CONTAINER_NAMESPACE"),
Stdout: sout,
Stderr: serr,
}
var (
sigCh = make(chan os.Signal, 2)
errCh = make(chan error, 1)
)
signal.Notify(sigCh, os.Interrupt, syscall.SIGTERM)
go func() {
errCh <- fn(ctx, config, wait.Close)
}()
for {
select {
case <-sigCh:
cancel()
case err = <-errCh:
return err
}
}
}