github.com/makyo/juju@v0.0.0-20160425123129-2608902037e9/resource/resourceadapters/apiserver.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package resourceadapters
     5  
     6  import (
     7  	"net/http"
     8  
     9  	"github.com/juju/errors"
    10  	"github.com/juju/names"
    11  
    12  	"github.com/juju/juju/apiserver/common"
    13  	"github.com/juju/juju/apiserver/common/apihttp"
    14  	"github.com/juju/juju/resource"
    15  	internalserver "github.com/juju/juju/resource/api/private/server"
    16  	"github.com/juju/juju/resource/api/server"
    17  	corestate "github.com/juju/juju/state"
    18  )
    19  
    20  // NewPublicFacade provides the public API facade for resources. It is
    21  // passed into common.RegisterStandardFacade.
    22  func NewPublicFacade(st *corestate.State, _ *common.Resources, authorizer common.Authorizer) (*server.Facade, error) {
    23  	if !authorizer.AuthClient() {
    24  		return nil, common.ErrPerm
    25  	}
    26  
    27  	rst, err := st.Resources()
    28  	if err != nil {
    29  		return nil, errors.Trace(err)
    30  	}
    31  	newClient := func() (server.CharmStore, error) {
    32  		return newCharmStoreClient(st)
    33  	}
    34  	facade, err := server.NewFacade(rst, newClient)
    35  	if err != nil {
    36  		return nil, errors.Trace(err)
    37  	}
    38  	return facade, nil
    39  }
    40  
    41  // NewUploadHandler returns a new HTTP handler for the given args.
    42  func NewUploadHandler(args apihttp.NewHandlerArgs) http.Handler {
    43  	return server.NewLegacyHTTPHandler(
    44  		func(req *http.Request) (server.DataStore, names.Tag, error) {
    45  			st, entity, err := args.Connect(req)
    46  			if err != nil {
    47  				return nil, nil, errors.Trace(err)
    48  			}
    49  			resources, err := st.Resources()
    50  			if err != nil {
    51  				return nil, nil, errors.Trace(err)
    52  			}
    53  
    54  			return resources, entity.Tag(), nil
    55  		},
    56  	)
    57  }
    58  
    59  // NewDownloadHandler returns a new HTTP handler for the given args.
    60  func NewDownloadHandler(args apihttp.NewHandlerArgs) http.Handler {
    61  	extractor := &httpDownloadRequestExtractor{
    62  		connect: args.Connect,
    63  	}
    64  	deps := internalserver.NewLegacyHTTPHandlerDeps(extractor)
    65  	return internalserver.NewLegacyHTTPHandler(deps)
    66  }
    67  
    68  // stateConnector exposes ways to connect to Juju's state.
    69  type stateConnector interface {
    70  	// Connect connects to state for a unit agent.
    71  }
    72  
    73  // httpDownloadRequestExtractor provides the functionality needed to
    74  // handle a resource download HTTP request.
    75  type httpDownloadRequestExtractor struct {
    76  	connect func(*http.Request) (*corestate.State, corestate.Entity, error)
    77  }
    78  
    79  // NewResourceOpener returns a new resource.Opener for the given
    80  // HTTP request.
    81  func (ex *httpDownloadRequestExtractor) NewResourceOpener(req *http.Request) (resource.Opener, error) {
    82  	st, ent, err := ex.connect(req)
    83  	if err != nil {
    84  		return nil, errors.Trace(err)
    85  	}
    86  	unit, ok := ent.(*corestate.Unit)
    87  	if !ok {
    88  		logger.Errorf("unexpected type: %T", ent)
    89  		return nil, errors.Errorf("unexpected type: %T", ent)
    90  	}
    91  
    92  	resources, err := st.Resources()
    93  	if err != nil {
    94  		return nil, errors.Trace(err)
    95  	}
    96  
    97  	opener := &resourceOpener{
    98  		st:     st,
    99  		res:    resources,
   100  		userID: unit.Tag(),
   101  		unit:   unit,
   102  	}
   103  	return opener, nil
   104  }