Skip to content

Commit

Permalink
Split out handlers, updated output
Browse files Browse the repository at this point in the history
Output aligned to docker structures

Signed-off-by: Jhon Honce <[email protected]>
  • Loading branch information
jwhonce committed Nov 2, 2019
1 parent 7d7a179 commit 918ff55
Show file tree
Hide file tree
Showing 7 changed files with 158 additions and 54 deletions.
2 changes: 2 additions & 0 deletions cmd/service/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
service: main.go
go build .
27 changes: 20 additions & 7 deletions cmd/service/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@ package main

import (
"context"
"fmt"
"os"
"time"

"github.com/containers/libpod/cmd/podman/cliconfig"
"github.com/containers/libpod/cmd/podman/libpodruntime"
"github.com/containers/libpod/pkg/serviceapi"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
)

Expand All @@ -18,8 +19,7 @@ func initConfig() {
func main() {
cobra.OnInitialize(initConfig)

var cancel context.CancelFunc
_, cancel = context.WithTimeout(context.Background(), time.Duration(50)*time.Millisecond)
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(50)*time.Millisecond)
defer cancel()

config := cliconfig.PodmanCommand{
Expand All @@ -31,11 +31,24 @@ func main() {
// Create a single runtime for http
runtime, err := libpodruntime.GetRuntimeDisableFDs(context.Background(), &config)
if err != nil {
log.Panicf("error creating libpod runtime: %s", err)
fmt.Printf("error creating libpod runtime: %s", err.Error())
os.Exit(1)
}
defer runtime.DeferredShutdown(false)

server, _ := serviceapi.NewServer(runtime)
_ = server.Serve()
defer server.Shutdown()
server, err := serviceapi.NewServer(runtime)
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
err = server.Serve()
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}
defer func() {
if e := server.Shutdown(ctx); e != nil {
fmt.Println(err.Error())
}
}()
}
13 changes: 13 additions & 0 deletions pkg/serviceapi/handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package serviceapi

import (
"net/http"

"github.com/containers/libpod/libpod"
)

type serviceHandler func(w http.ResponseWriter, r *http.Request, runtime *libpod.Runtime)

func (h serviceHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h(w, r, libpodRuntime)
}
11 changes: 11 additions & 0 deletions pkg/serviceapi/handler_containers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package serviceapi

import (
"net/http"

"github.com/containers/libpod/libpod"
)

func containers(w http.ResponseWriter, r *http.Request, runtime *libpod.Runtime) {
http.NotFound(w, r)
}
44 changes: 44 additions & 0 deletions pkg/serviceapi/handler_images.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package serviceapi

import (
"encoding/json"
"fmt"
"io"
"net/http"

"github.com/containers/libpod/libpod"
)

func images(w http.ResponseWriter, r *http.Request, runtime *libpod.Runtime) {
contentType := r.Header.Get("Content-Type")
if contentType != "" && contentType != "application/json" {
http.Error(w,
fmt.Sprintf("%s is not a supported Content-Type", r.Header.Get("Content-Type")),
http.StatusUnsupportedMediaType)
return
}

images, err := runtime.ImageRuntime().GetImages()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

var summaries []*ImageSummary
for _, img := range images {
i, err := ImageToImageSummary(img)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
summaries = append(summaries, i)
}

buffer, err := json.Marshal(summaries)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

w.Header().Set("Content-Type", "application/json")
io.WriteString(w, string(buffer))
}
57 changes: 10 additions & 47 deletions pkg/serviceapi/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ package serviceapi

import (
"context"
"encoding/json"
"fmt"
"io"
"net"
"net/http"
"os"
Expand All @@ -13,13 +10,14 @@ import (
"time"

"github.com/containers/libpod/libpod"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"

"github.com/coreos/go-systemd/activation"
)

type HttpServer struct {
*http.Server
http.Server
done chan struct{}
listener net.Listener
}
Expand All @@ -31,17 +29,17 @@ func NewServer(runtime *libpod.Runtime) (*HttpServer, error) {

listeners, err := activation.Listeners()
if err != nil {
log.Panicf("Cannot retrieve listeners: %s", err)
return nil, errors.Wrap(err, "Cannot retrieve listeners")
}
if len(listeners) != 1 {
log.Panicf("unexpected number of socket activation (%d != 1)", len(listeners))
return nil, errors.Wrapf(err, "unexpected number of socket activation (%d != 1)", len(listeners))
}

done := make(chan struct{})
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)

server := &http.Server{}
server := HttpServer{http.Server{}, done, listeners[0]}
go func() {
<-quit
log.Debugf("HttpServer is shutting down")
Expand All @@ -57,58 +55,23 @@ func NewServer(runtime *libpod.Runtime) (*HttpServer, error) {
// TODO: build this into a map...
http.Handle("/v1.24/images/json", serviceHandler(images))
http.Handle("/v1.24/containers/json", serviceHandler(containers))
return &HttpServer{server, done, listeners[0]}, nil
return &server, nil
}

func (s *HttpServer) Serve() error {
err := http.Serve(s.listener, nil)
if err != nil {
log.Panicf("Cannot start server: %s", err)
return errors.Wrap(err, "Failed to start HttpServer")
}
<-s.done
return nil
}

func (s *HttpServer) Shutdown() error {
func (s *HttpServer) Shutdown(ctx context.Context) error {
<-s.done
return nil
return s.Server.Shutdown(ctx)
}

func (s *HttpServer) Close() error {
return s.Close()
}

type serviceHandler func(w http.ResponseWriter, r *http.Request, runtime *libpod.Runtime)

func (h serviceHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
h(w, r, libpodRuntime)
}

func images(w http.ResponseWriter, r *http.Request, runtime *libpod.Runtime) {
contentType := r.Header.Get("Content-Type")
if contentType != "" && contentType != "application/json" {
http.Error(w,
fmt.Sprintf("%s is not a supported Content-Type", r.Header.Get("Content-Type")),
http.StatusUnsupportedMediaType)
return
}

images, err := runtime.ImageRuntime().GetImages()
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

buffer, err := json.Marshal(images)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}

w.Header().Set("Content-Type", "application/json")
io.WriteString(w, string(buffer))
}

func containers(w http.ResponseWriter, r *http.Request, runtime *libpod.Runtime) {
http.NotFound(w, r)
return s.Server.Close()
}
58 changes: 58 additions & 0 deletions pkg/serviceapi/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
package serviceapi

import (
"context"

podman "github.com/containers/libpod/libpod/image"
docker "github.com/docker/docker/api/types"
"github.com/pkg/errors"
)

type ImageSummary struct {
docker.ImageSummary
}

func ImageToImageSummary(p *podman.Image) (*ImageSummary, error) {
containers, err := p.Containers()
if err != nil {
return nil, errors.Wrapf(err, "Failed to obtain Containers for image %s", p.ID())
}
containerCount := len(containers)

var digests []string
for _, d := range p.Digests() {
digests = append(digests, string(d))
}

tags, err := p.RepoTags()
if err != nil {
return nil, errors.Wrapf(err, "Failed to obtain RepoTags for image %s", p.ID())
}

// parent, err := p.GetParent(context.TODO())
// if err != nil {
// return nil, errors.Wrapf(err, "Failed to obtain ParentID for image %s", p.ID())
// }

labels, err := p.Labels(context.TODO())
if err != nil {
return nil, errors.Wrapf(err, "Failed to obtain Labels for image %s", p.ID())
}

size, err := p.Size(context.TODO())
if err != nil {
return nil, errors.Wrapf(err, "Failed to obtain Size for image %s", p.ID())
}
return &ImageSummary{docker.ImageSummary{
Containers: int64(containerCount),
Created: p.Created().Unix(),
ID: p.ID(),
Labels: labels,
ParentID: "parent.ID()",
RepoDigests: digests,
RepoTags: tags,
SharedSize: 0,
Size: int64(*size),
VirtualSize: int64(*size),
}}, nil
}

0 comments on commit 918ff55

Please sign in to comment.