github.com/cs3org/reva/v2@v2.27.7/internal/http/services/mentix/mentix.go (about)

     1  // Copyright 2018-2021 CERN
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  // In applying this license, CERN does not waive the privileges and immunities
    16  // granted to it by virtue of its status as an Intergovernmental Organization
    17  // or submit itself to any jurisdiction.
    18  
    19  package mentix
    20  
    21  import (
    22  	"net/http"
    23  
    24  	"github.com/cs3org/reva/v2/pkg/mentix/meshdata"
    25  	"github.com/mitchellh/mapstructure"
    26  	"github.com/pkg/errors"
    27  	"github.com/rs/zerolog"
    28  
    29  	"github.com/cs3org/reva/v2/pkg/mentix"
    30  	"github.com/cs3org/reva/v2/pkg/mentix/config"
    31  	"github.com/cs3org/reva/v2/pkg/mentix/exchangers"
    32  	"github.com/cs3org/reva/v2/pkg/rhttp/global"
    33  )
    34  
    35  func init() {
    36  	global.Register(serviceName, New)
    37  }
    38  
    39  type svc struct {
    40  	conf *config.Configuration
    41  	mntx *mentix.Mentix
    42  	log  *zerolog.Logger
    43  
    44  	stopSignal chan struct{}
    45  }
    46  
    47  const (
    48  	serviceName = "mentix"
    49  )
    50  
    51  func (s *svc) Close() error {
    52  	// Trigger and close the stopSignal signal channel to stop Mentix
    53  	s.stopSignal <- struct{}{}
    54  	close(s.stopSignal)
    55  
    56  	return nil
    57  }
    58  
    59  func (s *svc) Prefix() string {
    60  	return s.conf.Prefix
    61  }
    62  
    63  func (s *svc) Unprotected() []string {
    64  	// Get all endpoints exposed by the RequestExchangers
    65  	importers := s.mntx.GetRequestImporters()
    66  	exporters := s.mntx.GetRequestExporters()
    67  
    68  	getEndpoints := func(exchangers []exchangers.RequestExchanger) []string {
    69  		endpoints := make([]string, 0, len(exchangers))
    70  		for _, exchanger := range exchangers {
    71  			if !exchanger.IsProtectedEndpoint() {
    72  				endpoints = append(endpoints, exchanger.Endpoint())
    73  			}
    74  		}
    75  		return endpoints
    76  	}
    77  
    78  	endpoints := make([]string, 0, len(importers)+len(exporters))
    79  	endpoints = append(endpoints, getEndpoints(importers)...)
    80  	endpoints = append(endpoints, getEndpoints(exporters)...)
    81  
    82  	return endpoints
    83  }
    84  
    85  func (s *svc) Handler() http.Handler {
    86  	// Forward requests to Mentix
    87  	return http.HandlerFunc(s.mntx.RequestHandler)
    88  }
    89  
    90  func (s *svc) startBackgroundService() {
    91  	// Just run Mentix in the background
    92  	go func() {
    93  		if err := s.mntx.Run(s.stopSignal); err != nil {
    94  			s.log.Err(err).Msg("error while running mentix")
    95  		}
    96  	}()
    97  }
    98  
    99  func parseConfig(m map[string]interface{}) (*config.Configuration, error) {
   100  	cfg := &config.Configuration{}
   101  	if err := mapstructure.Decode(m, &cfg); err != nil {
   102  		return nil, errors.Wrap(err, "mentix: error decoding configuration")
   103  	}
   104  	applyInternalConfig(m, cfg)
   105  	applyDefaultConfig(cfg)
   106  	return cfg, nil
   107  }
   108  
   109  func applyInternalConfig(m map[string]interface{}, conf *config.Configuration) {
   110  	getSubsections := func(section string) []string {
   111  		subsections := make([]string, 0, 5)
   112  		if list, ok := m[section].(map[string]interface{}); ok {
   113  			for name := range list {
   114  				subsections = append(subsections, name)
   115  			}
   116  		}
   117  		return subsections
   118  	}
   119  
   120  	conf.EnabledConnectors = getSubsections("connectors")
   121  	conf.EnabledImporters = getSubsections("importers")
   122  	conf.EnabledExporters = getSubsections("exporters")
   123  }
   124  
   125  func applyDefaultConfig(conf *config.Configuration) {
   126  	// General
   127  	if conf.Prefix == "" {
   128  		conf.Prefix = serviceName
   129  	}
   130  
   131  	if conf.UpdateInterval == "" {
   132  		conf.UpdateInterval = "1h" // Update once per hour
   133  	}
   134  
   135  	// Connectors
   136  	if conf.Connectors.GOCDB.Scope == "" {
   137  		conf.Connectors.GOCDB.Scope = "SM" // TODO(Daniel-WWU-IT): This might change in the future
   138  	}
   139  
   140  	// Exporters
   141  	addDefaultConnector := func(enabledList *[]string) {
   142  		if len(*enabledList) == 0 {
   143  			*enabledList = append(*enabledList, "*")
   144  		}
   145  	}
   146  
   147  	if conf.Exporters.WebAPI.Endpoint == "" {
   148  		conf.Exporters.WebAPI.Endpoint = "/sites"
   149  	}
   150  	addDefaultConnector(&conf.Exporters.WebAPI.EnabledConnectors)
   151  
   152  	if conf.Exporters.CS3API.Endpoint == "" {
   153  		conf.Exporters.CS3API.Endpoint = "/cs3"
   154  	}
   155  	addDefaultConnector(&conf.Exporters.CS3API.EnabledConnectors)
   156  	if len(conf.Exporters.CS3API.ElevatedServiceTypes) == 0 {
   157  		conf.Exporters.CS3API.ElevatedServiceTypes = append(conf.Exporters.CS3API.ElevatedServiceTypes, meshdata.EndpointGateway, meshdata.EndpointOCM, meshdata.EndpointWebdav)
   158  	}
   159  
   160  	if conf.Exporters.SiteLocations.Endpoint == "" {
   161  		conf.Exporters.SiteLocations.Endpoint = "/loc"
   162  	}
   163  	addDefaultConnector(&conf.Exporters.SiteLocations.EnabledConnectors)
   164  
   165  	addDefaultConnector(&conf.Exporters.PrometheusSD.EnabledConnectors)
   166  	addDefaultConnector(&conf.Exporters.Metrics.EnabledConnectors)
   167  }
   168  
   169  // New returns a new Mentix service.
   170  func New(m map[string]interface{}, log *zerolog.Logger) (global.Service, error) {
   171  	// Prepare the configuration
   172  	conf, err := parseConfig(m)
   173  	if err != nil {
   174  		return nil, err
   175  	}
   176  
   177  	conf.Init()
   178  
   179  	// Create the Mentix instance
   180  	mntx, err := mentix.New(conf, log)
   181  	if err != nil {
   182  		return nil, errors.Wrap(err, "mentix: error creating Mentix")
   183  	}
   184  
   185  	// Create the service and start its background activity
   186  	s := &svc{
   187  		conf:       conf,
   188  		mntx:       mntx,
   189  		log:        log,
   190  		stopSignal: make(chan struct{}),
   191  	}
   192  	s.startBackgroundService()
   193  	return s, nil
   194  }