diff options
Diffstat (limited to 'pkg')
-rw-r--r-- | pkg/api/handlers/compat/images_build.go | 16 | ||||
-rw-r--r-- | pkg/bindings/images/build.go | 16 | ||||
-rw-r--r-- | pkg/domain/entities/types/auth.go | 3 | ||||
-rw-r--r-- | pkg/domain/entities/types/types.go | 3 | ||||
-rw-r--r-- | pkg/domain/infra/abi/containers_runlabel.go | 25 | ||||
-rw-r--r-- | pkg/domain/infra/abi/play.go | 1 | ||||
-rw-r--r-- | pkg/errorhandling/errorhandling.go | 3 | ||||
-rw-r--r-- | pkg/registrar/registrar.go | 127 | ||||
-rw-r--r-- | pkg/registrar/registrar_test.go | 213 | ||||
-rw-r--r-- | pkg/specgen/generate/kube/kube.go | 6 |
10 files changed, 50 insertions, 363 deletions
diff --git a/pkg/api/handlers/compat/images_build.go b/pkg/api/handlers/compat/images_build.go index 700881926..ec40fdd2d 100644 --- a/pkg/api/handlers/compat/images_build.go +++ b/pkg/api/handlers/compat/images_build.go @@ -462,12 +462,18 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { buildOptions.Timestamp = &ts } + var ( + imageID string + success bool + ) + runCtx, cancel := context.WithCancel(context.Background()) - var imageID string go func() { defer cancel() imageID, _, err = runtime.Build(r.Context(), buildOptions, query.Dockerfile) - if err != nil { + if err == nil { + success = true + } else { stderr.Write([]byte(err.Error() + "\n")) } }() @@ -483,8 +489,6 @@ func BuildImage(w http.ResponseWriter, r *http.Request) { w.Header().Add("Content-Type", "application/json") flush() - var failed bool - body := w.(io.Writer) if logrus.IsLevelEnabled(logrus.DebugLevel) { if v, found := os.LookupEnv("PODMAN_RETAIN_BUILD_ARTIFACT"); found { @@ -525,14 +529,14 @@ loop: } flush() case e := <-stderr.Chan(): - failed = true m.Error = string(e) if err := enc.Encode(m); err != nil { logrus.Warnf("Failed to json encode error %v", err) } flush() case <-runCtx.Done(): - if !failed { + flush() + if success { if !utils.IsLibpodRequest(r) { m.Stream = fmt.Sprintf("Successfully built %12.12s\n", imageID) if err := enc.Encode(m); err != nil { diff --git a/pkg/bindings/images/build.go b/pkg/bindings/images/build.go index 34d6cee05..c0e5706a5 100644 --- a/pkg/bindings/images/build.go +++ b/pkg/bindings/images/build.go @@ -340,6 +340,7 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO re := regexp.MustCompile(`[0-9a-f]{12}`) var id string + var mErr error for { var s struct { Stream string `json:"stream,omitempty"` @@ -347,11 +348,21 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO } if err := dec.Decode(&s); err != nil { if errors.Is(err, io.EOF) { - return &entities.BuildReport{ID: id}, nil + if mErr == nil && id == "" { + mErr = errors.New("stream dropped, unexpected failure") + } + break } s.Error = err.Error() + "\n" } + select { + case <-response.Request.Context().Done(): + return &entities.BuildReport{ID: id}, mErr + default: + // non-blocking select + } + switch { case s.Stream != "": stdout.Write([]byte(s.Stream)) @@ -359,11 +370,12 @@ func Build(ctx context.Context, containerFiles []string, options entities.BuildO id = strings.TrimSuffix(s.Stream, "\n") } case s.Error != "": - return nil, errors.New(s.Error) + mErr = errors.New(s.Error) default: return &entities.BuildReport{ID: id}, errors.New("failed to parse build results stream, unexpected input") } } + return &entities.BuildReport{ID: id}, mErr } func nTar(excludes []string, sources ...string) (io.ReadCloser, error) { diff --git a/pkg/domain/entities/types/auth.go b/pkg/domain/entities/types/auth.go index ddf15bb18..7f2480173 100644 --- a/pkg/domain/entities/types/auth.go +++ b/pkg/domain/entities/types/auth.go @@ -1,4 +1,5 @@ -package types // import "github.com/docker/docker/api/types" +// copied from github.com/docker/docker/api/types +package types // AuthConfig contains authorization information for connecting to a Registry type AuthConfig struct { diff --git a/pkg/domain/entities/types/types.go b/pkg/domain/entities/types/types.go index 77834c0cb..7dc785078 100644 --- a/pkg/domain/entities/types/types.go +++ b/pkg/domain/entities/types/types.go @@ -1,4 +1,5 @@ -package types // import "github.com/docker/docker/api/types" +// copied from github.com/docker/docker/api/types +package types // ComponentVersion describes the version information for a specific component. type ComponentVersion struct { diff --git a/pkg/domain/infra/abi/containers_runlabel.go b/pkg/domain/infra/abi/containers_runlabel.go index 8de383926..2cabab988 100644 --- a/pkg/domain/infra/abi/containers_runlabel.go +++ b/pkg/domain/infra/abi/containers_runlabel.go @@ -177,6 +177,16 @@ func generateRunlabelCommand(runlabel string, img *image.Image, args []string, o return cmd, env, nil } +func replaceName(arg, name string) string { + newarg := strings.ReplaceAll(arg, "$NAME", name) + return strings.ReplaceAll(newarg, "${NAME}", name) +} + +func replaceImage(arg, image string) string { + newarg := strings.ReplaceAll(arg, "$IMAGE", image) + return strings.ReplaceAll(newarg, "${IMAGE}", image) +} + // generateCommand takes a label (string) and converts it to an executable command func generateCommand(command, imageName, name, globalOpts string) ([]string, error) { if name == "" { @@ -196,26 +206,15 @@ func generateCommand(command, imageName, name, globalOpts string) ([]string, err for _, arg := range cmd[1:] { var newArg string switch arg { - case "IMAGE": - newArg = imageName - case "$IMAGE": - newArg = imageName case "IMAGE=IMAGE": newArg = fmt.Sprintf("IMAGE=%s", imageName) - case "IMAGE=$IMAGE": - newArg = fmt.Sprintf("IMAGE=%s", imageName) - case "NAME": - newArg = name case "NAME=NAME": newArg = fmt.Sprintf("NAME=%s", name) - case "NAME=$NAME": - newArg = fmt.Sprintf("NAME=%s", name) - case "$NAME": - newArg = name case "$GLOBAL_OPTS": newArg = globalOpts default: - newArg = arg + newArg = replaceName(arg, name) + newArg = replaceImage(newArg, imageName) } newCommand = append(newCommand, newArg) } diff --git a/pkg/domain/infra/abi/play.go b/pkg/domain/infra/abi/play.go index 52f759f13..6eecef2de 100644 --- a/pkg/domain/infra/abi/play.go +++ b/pkg/domain/infra/abi/play.go @@ -300,6 +300,7 @@ func (ic *ContainerEngine) playKubePod(ctx context.Context, podName string, podY RestartPolicy: ctrRestartPolicy, NetNSIsHost: p.NetNS.IsHost(), SecretsManager: secretsManager, + LogDriver: options.LogDriver, } specGen, err := kube.ToSpecGen(ctx, &specgenOpts) if err != nil { diff --git a/pkg/errorhandling/errorhandling.go b/pkg/errorhandling/errorhandling.go index b1923be98..9dc545ebb 100644 --- a/pkg/errorhandling/errorhandling.go +++ b/pkg/errorhandling/errorhandling.go @@ -24,6 +24,9 @@ func JoinErrors(errs []error) error { if finalErr == nil { return finalErr } + if len(multiE.WrappedErrors()) == 1 && logrus.IsLevelEnabled(logrus.TraceLevel) { + return multiE.WrappedErrors()[0] + } return errors.New(strings.TrimSpace(finalErr.Error())) } diff --git a/pkg/registrar/registrar.go b/pkg/registrar/registrar.go deleted file mode 100644 index 1e75ee995..000000000 --- a/pkg/registrar/registrar.go +++ /dev/null @@ -1,127 +0,0 @@ -// Package registrar provides name registration. It reserves a name to a given key. -package registrar - -import ( - "errors" - "sync" -) - -var ( - // ErrNameReserved is an error which is returned when a name is requested to be reserved that already is reserved - ErrNameReserved = errors.New("name is reserved") - // ErrNameNotReserved is an error which is returned when trying to find a name that is not reserved - ErrNameNotReserved = errors.New("name is not reserved") - // ErrNoSuchKey is returned when trying to find the names for a key which is not known - ErrNoSuchKey = errors.New("provided key does not exist") -) - -// Registrar stores indexes a list of keys and their registered names as well as indexes names and the key that they are registered to -// Names must be unique. -// Registrar is safe for concurrent access. -type Registrar struct { - idx map[string][]string - names map[string]string - mu sync.Mutex -} - -// NewRegistrar creates a new Registrar with the an empty index -func NewRegistrar() *Registrar { - return &Registrar{ - idx: make(map[string][]string), - names: make(map[string]string), - } -} - -// Reserve registers a key to a name -// Reserve is idempotent -// Attempting to reserve a key to a name that already exists results in an `ErrNameReserved` -// A name reservation is globally unique -func (r *Registrar) Reserve(name, key string) error { - r.mu.Lock() - defer r.mu.Unlock() - - if k, exists := r.names[name]; exists { - if k != key { - return ErrNameReserved - } - return nil - } - - r.idx[key] = append(r.idx[key], name) - r.names[name] = key - return nil -} - -// Release releases the reserved name -// Once released, a name can be reserved again -func (r *Registrar) Release(name string) { - r.mu.Lock() - defer r.mu.Unlock() - - key, exists := r.names[name] - if !exists { - return - } - - for i, n := range r.idx[key] { - if n != name { - continue - } - r.idx[key] = append(r.idx[key][:i], r.idx[key][i+1:]...) - break - } - - delete(r.names, name) - - if len(r.idx[key]) == 0 { - delete(r.idx, key) - } -} - -// Delete removes all reservations for the passed in key. -// All names reserved to this key are released. -func (r *Registrar) Delete(key string) { - r.mu.Lock() - for _, name := range r.idx[key] { - delete(r.names, name) - } - delete(r.idx, key) - r.mu.Unlock() -} - -// GetNames lists all the reserved names for the given key -func (r *Registrar) GetNames(key string) ([]string, error) { - r.mu.Lock() - defer r.mu.Unlock() - - names, exists := r.idx[key] - if !exists { - return nil, ErrNoSuchKey - } - return names, nil -} - -// Get returns the key that the passed in name is reserved to -func (r *Registrar) Get(name string) (string, error) { - r.mu.Lock() - key, exists := r.names[name] - r.mu.Unlock() - - if !exists { - return "", ErrNameNotReserved - } - return key, nil -} - -// GetAll returns all registered names -func (r *Registrar) GetAll() map[string][]string { - out := make(map[string][]string) - - r.mu.Lock() - // copy index into out - for id, names := range r.idx { - out[id] = names - } - r.mu.Unlock() - return out -} diff --git a/pkg/registrar/registrar_test.go b/pkg/registrar/registrar_test.go deleted file mode 100644 index dc9942e80..000000000 --- a/pkg/registrar/registrar_test.go +++ /dev/null @@ -1,213 +0,0 @@ -package registrar_test - -import ( - "testing" - - "github.com/containers/podman/v3/pkg/registrar" - . "github.com/containers/podman/v3/test/framework" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" -) - -// TestRegistrar runs the created specs -func TestRegistrar(t *testing.T) { - RegisterFailHandler(Fail) - RunSpecs(t, "Registrar") -} - -// nolint: gochecknoglobals -var t *TestFramework - -var _ = BeforeSuite(func() { - t = NewTestFramework(NilFunc, NilFunc) - t.Setup() -}) - -var _ = AfterSuite(func() { - t.Teardown() -}) - -// The actual test suite -var _ = t.Describe("Registrar", func() { - // Constant test data needed by some tests - const ( - testKey = "testKey" - testName = "testName" - anotherKey = "anotherKey" - ) - - // The system under test - var sut *registrar.Registrar - - // Prepare the system under test and register a test name and key before - // each test - BeforeEach(func() { - sut = registrar.NewRegistrar() - Expect(sut.Reserve(testName, testKey)).To(BeNil()) - }) - - t.Describe("Reserve", func() { - It("should succeed to reserve a new registrar", func() { - // Given - // When - err := sut.Reserve("name", "key") - - // Then - Expect(err).To(BeNil()) - }) - - It("should succeed to reserve a registrar twice", func() { - // Given - // When - err := sut.Reserve(testName, testKey) - - // Then - Expect(err).To(BeNil()) - }) - - It("should fail to reserve an already reserved registrar", func() { - // Given - // When - err := sut.Reserve(testName, anotherKey) - - // Then - Expect(err).NotTo(BeNil()) - Expect(err).To(Equal(registrar.ErrNameReserved)) - }) - }) - - t.Describe("Release", func() { - It("should succeed to release a registered registrar multiple times", func() { - // Given - // When - // Then - sut.Release(testName) - sut.Release(testName) - }) - - It("should succeed to release a unknown registrar multiple times", func() { - // Given - // When - // Then - sut.Release(anotherKey) - sut.Release(anotherKey) - }) - - It("should succeed to release and re-register a registrar", func() { - // Given - // When - sut.Release(testName) - err := sut.Reserve(testName, testKey) - - // Then - Expect(err).To(BeNil()) - }) - }) - - t.Describe("GetNames", func() { - It("should succeed to retrieve a single name for a registrar", func() { - // Given - // When - names, err := sut.GetNames(testKey) - - // Then - Expect(err).To(BeNil()) - Expect(len(names)).To(Equal(1)) - Expect(names[0]).To(Equal(testName)) - }) - - It("should succeed to retrieve all names for a registrar", func() { - // Given - testNames := []string{"test1", "test2"} - for _, name := range testNames { - Expect(sut.Reserve(name, anotherKey)).To(BeNil()) - } - - // When - names, err := sut.GetNames(anotherKey) - - // Then - Expect(err).To(BeNil()) - Expect(len(names)).To(Equal(2)) - Expect(names).To(Equal(testNames)) - }) - }) - - t.Describe("GetNames", func() { - It("should succeed to retrieve a single name for a registrar", func() { - // Given - // When - names, err := sut.GetNames(testKey) - - // Then - Expect(err).To(BeNil()) - Expect(len(names)).To(Equal(1)) - Expect(names[0]).To(Equal(testName)) - }) - - It("should succeed to retrieve all names for a registrar", func() { - // Given - anotherKey := "anotherKey" - testNames := []string{"test1", "test2"} - for _, name := range testNames { - Expect(sut.Reserve(name, anotherKey)).To(BeNil()) - } - - // When - names, err := sut.GetNames(anotherKey) - - // Then - Expect(err).To(BeNil()) - Expect(len(names)).To(Equal(2)) - Expect(names).To(Equal(testNames)) - }) - }) - - t.Describe("Delete", func() { - It("should succeed to delete a registrar", func() { - // Given - // When - sut.Delete(testKey) - - // Then - names, err := sut.GetNames(testKey) - Expect(len(names)).To(BeZero()) - Expect(err).To(Equal(registrar.ErrNoSuchKey)) - }) - }) - - t.Describe("Get", func() { - It("should succeed to get a key for a registrar", func() { - // Given - // When - key, err := sut.Get(testName) - - // Then - Expect(err).To(BeNil()) - Expect(key).To(Equal(testKey)) - }) - - It("should fail to get a key for a not existing registrar", func() { - // Given - // When - key, err := sut.Get("notExistingName") - - // Then - Expect(key).To(BeEmpty()) - Expect(err).To(Equal(registrar.ErrNameNotReserved)) - }) - }) - - t.Describe("GetAll", func() { - It("should succeed to get all names", func() { - // Given - // When - names := sut.GetAll() - - // Then - Expect(len(names)).To(Equal(1)) - Expect(len(names[testKey])).To(Equal(1)) - Expect(names[testKey][0]).To(Equal(testName)) - }) - }) -}) diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go index 31ed3fd7c..7aeec9d41 100644 --- a/pkg/specgen/generate/kube/kube.go +++ b/pkg/specgen/generate/kube/kube.go @@ -98,6 +98,8 @@ type CtrSpecGenOptions struct { NetNSIsHost bool // SecretManager to access the secrets SecretsManager *secrets.SecretsManager + // LogDriver which should be used for the container + LogDriver string } func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGenerator, error) { @@ -115,6 +117,10 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener s.Pod = opts.PodID + s.LogConfiguration = &specgen.LogConfig{ + Driver: opts.LogDriver, + } + setupSecurityContext(s, opts.Container) // Since we prefix the container name with pod name to work-around the uniqueness requirement, |