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

verbose output #46

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
3 changes: 2 additions & 1 deletion cmd/oci-image-tool/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"strings"

"github.com/opencontainers/image-tools/image"
"github.com/opencontainers/image-tools/logger"
"github.com/urfave/cli"
)

Expand Down Expand Up @@ -74,7 +75,7 @@ func createHandle(context *cli.Context) error {
}

if err != nil {
fmt.Printf("creating failed: %v\n", err)
logger.G(globalCtx).WithError(err).Infof("creating failed")
}

return err
Expand Down
10 changes: 5 additions & 5 deletions cmd/oci-image-tool/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,13 @@ import (
"fmt"
"os"

"github.com/Sirupsen/logrus"
"github.com/opencontainers/image-tools/logger"
"github.com/opencontainers/image-tools/version"
"github.com/urfave/cli"
)

var globalCtx = logger.WithLogger(logger.Background(), logger.LogEntry)

// gitCommit will be the hash that the binary was built from
// and will be populated by the Makefile
var gitCommit = ""
Expand All @@ -43,9 +45,7 @@ func main() {
},
}
app.Before = func(c *cli.Context) error {
if c.GlobalBool("debug") {
logrus.SetLevel(logrus.DebugLevel)
}
logger.EnableDebugMode(c.GlobalBool("debug"))
return nil
}
app.Commands = []cli.Command{
Expand All @@ -55,6 +55,6 @@ func main() {
}

if err := app.Run(os.Args); err != nil {
logrus.Fatal(err)
os.Exit(1)
}
}
3 changes: 2 additions & 1 deletion cmd/oci-image-tool/unpack.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"strings"

"github.com/opencontainers/image-tools/image"
"github.com/opencontainers/image-tools/logger"
"github.com/urfave/cli"
)

Expand Down Expand Up @@ -67,7 +68,7 @@ func unpackHandle(context *cli.Context) error {
}

if err != nil {
fmt.Printf("unpacking failed: %v\n", err)
logger.G(globalCtx).WithError(err).Errorf("unpacking failed")
}
return err
}
Expand Down
23 changes: 13 additions & 10 deletions cmd/oci-image-tool/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ package main

import (
"fmt"
"log"
"os"
"strings"

"github.com/opencontainers/image-spec/schema"
"github.com/opencontainers/image-tools/image"
"github.com/opencontainers/image-tools/logger"
"github.com/pkg/errors"
"github.com/urfave/cli"
)
Expand All @@ -36,9 +36,8 @@ var validateTypes = []string{
}

type validateCmd struct {
stdout *log.Logger
typ string // the type to validate, can be empty string
refs []string
typ string // the type to validate, can be empty string
refs []string
}

var v validateCmd
Expand All @@ -58,10 +57,11 @@ func validateHandler(context *cli.Context) error {

var errs []string
for _, arg := range context.Args() {
var ctx = logger.WithLogger(globalCtx, logger.G(globalCtx).WithField("target", arg))
err := validatePath(arg)

if err == nil {
fmt.Printf("%s: OK\n", arg)
logger.G(ctx).Infof("OK")
continue
}

Expand All @@ -78,9 +78,12 @@ func validateHandler(context *cli.Context) error {
}

if len(errs) > 0 {
return fmt.Errorf("%d errors detected: \n%s", len(errs), strings.Join(errs, "\n"))
err := fmt.Errorf("%d errors detected: \n%s", len(errs), strings.Join(errs, "\n"))
logger.G(globalCtx).WithError(err).Infof("validation failed")
return err
}
fmt.Println("Validation succeeded")

logger.G(globalCtx).Infof("Validation succeeded")
return nil
}

Expand All @@ -98,13 +101,13 @@ func validatePath(name string) error {

switch typ {
case image.TypeImageLayout:
return image.ValidateLayout(name, v.refs, v.stdout)
return image.ValidateLayout(globalCtx, name, v.refs)
case image.TypeImage:
return image.ValidateFile(name, v.refs, v.stdout)
return image.ValidateFile(globalCtx, name, v.refs)
}

if len(v.refs) != 0 {
fmt.Printf("WARNING: type %q does not support refs, which are only appropriate if type is image or imageLayout.\n", typ)
logger.G(globalCtx).Warnf("type %q does not support refs, which are only appropriate if type is image or imageLayout.", typ)
}

f, err := os.Open(name)
Expand Down
25 changes: 10 additions & 15 deletions image/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,55 +18,52 @@ import (
"encoding/json"
"fmt"
"io"
"log"
"os"
"path/filepath"

"github.com/opencontainers/image-spec/specs-go/v1"
"github.com/opencontainers/image-tools/logger"
"github.com/pkg/errors"
)

// ValidateLayout walks through the given file tree and validates the manifest
// pointed to by the given refs or returns an error if the validation failed.
func ValidateLayout(src string, refs []string, out *log.Logger) error {
return validate(newPathWalker(src), refs, out)
func ValidateLayout(ctx logger.Context, src string, refs []string) error {
Copy link
Contributor

Choose a reason for hiding this comment

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

This doesn't make sense. This should just use a regular context. Don't define a new Context type.

Please follow the pattern in containerd. It is well-healed and does exactly what is needed here.

return validate(ctx, newPathWalker(src), refs)
}

// ValidateFile opens the tar file given by the filename, then calls ValidateReader
func ValidateFile(tarFile string, refs []string, out *log.Logger) error {
func ValidateFile(ctx logger.Context, tarFile string, refs []string) error {
f, err := os.Open(tarFile)
if err != nil {
return errors.Wrap(err, "unable to open file")
}
defer f.Close()

return Validate(f, refs, out)
return Validate(ctx, f, refs)
}

// Validate walks through a tar stream and validates the manifest.
// * Check that all refs point to extant blobs
// * Checks that all referred blobs are valid
// * Checks that mime-types are correct
// returns error on validation failure
func Validate(r io.ReadSeeker, refs []string, out *log.Logger) error {
return validate(newTarWalker(r), refs, out)
func Validate(ctx logger.Context, r io.ReadSeeker, refs []string) error {
return validate(ctx, newTarWalker(r), refs)
}

var validRefMediaTypes = []string{
v1.MediaTypeImageManifest,
v1.MediaTypeImageIndex,
}

func validate(w walker, refs []string, out *log.Logger) error {
func validate(ctx logger.Context, w walker, refs []string) error {
ds, err := listReferences(w)
if err != nil {
return err
}
if len(refs) == 0 && len(ds) == 0 {
// TODO(runcom): ugly, we'll need a better way and library
// to express log levels.
// see https://github.com/opencontainers/image-spec/issues/288
out.Print("WARNING: no descriptors found")
logger.G(ctx).Warnf("no descriptors found")
}

if len(refs) == 0 {
Expand Down Expand Up @@ -96,9 +93,7 @@ func validate(w walker, refs []string, out *log.Logger) error {
if err := m.validate(w); err != nil {
return err
}
if out != nil {
out.Printf("reference %q: OK", ref)
}
logger.G(ctx).WithField("reference", ref).Infof("validate OK")
}
return nil
}
Expand Down
3 changes: 2 additions & 1 deletion image/image_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (

"github.com/opencontainers/go-digest"
"github.com/opencontainers/image-spec/specs-go/v1"
"github.com/opencontainers/image-tools/logger"
)

const (
Expand Down Expand Up @@ -150,7 +151,7 @@ func TestValidateLayout(t *testing.T) {
t.Fatal(err)
}

err = ValidateLayout(root, []string{refTag}, nil)
err = ValidateLayout(logger.Background(), root, []string{refTag})
if err != nil {
t.Fatal(err)
}
Expand Down
31 changes: 31 additions & 0 deletions logger/context.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright 2016 The Linux Foundation
//
// 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 logger

import (
"context"
)

// Context is a copy of Context from the stdlib context package.
type Context interface {
Copy link
Contributor

Choose a reason for hiding this comment

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

Do not define a new context type.

context.Context
}

// Background returns a non-nil, empty Context. The background context
// provides a single key, "instance.id" that is globally unique to the
// process.
func Background() context.Context {
return context.Background()
}
69 changes: 69 additions & 0 deletions logger/logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright 2016 The Linux Foundation
//
// 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 logger
Copy link
Contributor

Choose a reason for hiding this comment

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

What is the purpose of this package?

Copy link
Contributor

Choose a reason for hiding this comment

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

Here is an example of a context-integrated logger that is threadsafe: https://github.com/docker/containerd/blob/master/log/context.go#L28.

However, please let me know what the intent of this package and we can get it into shape.


import (
// TODO(xiekeyang): The adaptation should be checked for openSUSE
// on non-x86_64 architectures. If encounting problem, the golang
// version should be updated accordingly.
"context"
"os"

"github.com/Sirupsen/logrus"
)

var (
// G is an alias for GetLogger.
//
// We may want to define this locally to a package to get package tagged log
// messages.
G = GetLogger

// LogEntry provides a public and standard logger instance.
LogEntry = logrus.NewEntry(logrus.StandardLogger())
)

type (
loggerKey struct{}
)

// WithLogger returns a new context with the provided logger. Use in
// combination with logger.WithField(s) for great effect.
func WithLogger(ctx context.Context, logger *logrus.Entry) context.Context {
return context.WithValue(ctx, loggerKey{}, logger)
}

// GetLogger retrieves the current logger from the context. If no logger is
// available, the default logger is returned.
func GetLogger(ctx context.Context) *logrus.Entry {
logger := ctx.Value(loggerKey{})

if logger == nil {
return LogEntry
}

return logger.(*logrus.Entry)
}

// EnableDebugMode enables a selectable debug mode.
func EnableDebugMode(debug bool) {
if debug {
LogEntry.Logger.Level = logrus.DebugLevel
}
}

func init() {
LogEntry.Logger.Out = os.Stderr
}
2 changes: 2 additions & 0 deletions man/oci-image-tool.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ oci-image-tool is a collection of tools for working with the [OCI image specific
Create an OCI runtime bundle
See **oci-image-tool-create**(1) for full documentation on the **create** command.

During command run, the output stream will be sent to `OS stderr`.

# SEE ALSO
**oci-image-tool-validate**(1), **oci-image-tool-unpack**(1), **oci-image-tool-create**(1)

Expand Down