github.com/tickoalcantara12/micro/v3@v3.0.0-20221007104245-9d75b9bcbab9/profile/profile.go (about)

     1  // Package profile is for specific profiles
     2  // @todo this package is the definition of cruft and
     3  // should be rewritten in a more elegant way
     4  package profile
     5  
     6  import (
     7  	"fmt"
     8  	"os"
     9  	"path/filepath"
    10  
    11  	"github.com/tickoalcantara12/micro/v3/service/auth/jwt"
    12  	"github.com/tickoalcantara12/micro/v3/service/auth/noop"
    13  	"github.com/tickoalcantara12/micro/v3/service/broker"
    14  	memBroker "github.com/tickoalcantara12/micro/v3/service/broker/memory"
    15  	"github.com/tickoalcantara12/micro/v3/service/build/golang"
    16  	"github.com/tickoalcantara12/micro/v3/service/client"
    17  	grpcClient "github.com/tickoalcantara12/micro/v3/service/client/grpc"
    18  	"github.com/tickoalcantara12/micro/v3/service/config"
    19  	storeConfig "github.com/tickoalcantara12/micro/v3/service/config/store"
    20  	evStore "github.com/tickoalcantara12/micro/v3/service/events/store"
    21  	memStream "github.com/tickoalcantara12/micro/v3/service/events/stream/memory"
    22  	"github.com/tickoalcantara12/micro/v3/service/logger"
    23  	"github.com/tickoalcantara12/micro/v3/service/model"
    24  	"github.com/tickoalcantara12/micro/v3/service/registry"
    25  	"github.com/tickoalcantara12/micro/v3/service/registry/memory"
    26  	"github.com/tickoalcantara12/micro/v3/service/router"
    27  	k8sRouter "github.com/tickoalcantara12/micro/v3/service/router/kubernetes"
    28  	regRouter "github.com/tickoalcantara12/micro/v3/service/router/registry"
    29  	"github.com/tickoalcantara12/micro/v3/service/runtime/kubernetes"
    30  	"github.com/tickoalcantara12/micro/v3/service/runtime/local"
    31  	"github.com/tickoalcantara12/micro/v3/service/server"
    32  	grpcServer "github.com/tickoalcantara12/micro/v3/service/server/grpc"
    33  	"github.com/tickoalcantara12/micro/v3/service/store/file"
    34  	mem "github.com/tickoalcantara12/micro/v3/service/store/memory"
    35  	"github.com/tickoalcantara12/micro/v3/util/opentelemetry"
    36  	"github.com/tickoalcantara12/micro/v3/util/opentelemetry/jaeger"
    37  	"github.com/urfave/cli/v2"
    38  
    39  	microAuth "github.com/tickoalcantara12/micro/v3/service/auth"
    40  	microBuilder "github.com/tickoalcantara12/micro/v3/service/build"
    41  	microEvents "github.com/tickoalcantara12/micro/v3/service/events"
    42  	microRuntime "github.com/tickoalcantara12/micro/v3/service/runtime"
    43  	microStore "github.com/tickoalcantara12/micro/v3/service/store"
    44  	inAuth "github.com/tickoalcantara12/micro/v3/util/auth"
    45  	"github.com/tickoalcantara12/micro/v3/util/user"
    46  )
    47  
    48  // profiles which when called will configure micro to run in that environment
    49  var profiles = map[string]*Profile{
    50  	// built in profiles
    51  	"client":     Client,
    52  	"service":    Service,
    53  	"server":     Server,
    54  	"test":       Test,
    55  	"local":      Local,
    56  	"kubernetes": Kubernetes,
    57  }
    58  
    59  // Profile configures an environment
    60  type Profile struct {
    61  	// name of the profile
    62  	Name string
    63  	// function used for setup
    64  	Setup func(*cli.Context) error
    65  	// TODO: presetup dependencies
    66  	// e.g start resources
    67  }
    68  
    69  // Register a profile
    70  func Register(name string, p *Profile) error {
    71  	if _, ok := profiles[name]; ok {
    72  		return fmt.Errorf("profile %s already exists", name)
    73  	}
    74  	profiles[name] = p
    75  	return nil
    76  }
    77  
    78  // Load a profile
    79  func Load(name string) (*Profile, error) {
    80  	v, ok := profiles[name]
    81  	if !ok {
    82  		return nil, fmt.Errorf("profile %s does not exist", name)
    83  	}
    84  	return v, nil
    85  }
    86  
    87  // Client profile is for any entrypoint that behaves as a client
    88  var Client = &Profile{
    89  	Name:  "client",
    90  	Setup: func(ctx *cli.Context) error { return nil },
    91  }
    92  
    93  // Local profile to run as a single process
    94  var Local = &Profile{
    95  	Name: "local",
    96  	Setup: func(ctx *cli.Context) error {
    97  		// set client/server
    98  		client.DefaultClient = grpcClient.NewClient()
    99  		server.DefaultServer = grpcServer.NewServer()
   100  
   101  		microAuth.DefaultAuth = jwt.NewAuth()
   102  		microStore.DefaultStore = file.NewStore(file.WithDir(filepath.Join(user.Dir, "server", "store")))
   103  		SetupConfigSecretKey(ctx)
   104  		config.DefaultConfig, _ = storeConfig.NewConfig(microStore.DefaultStore, "")
   105  
   106  		SetupJWT(ctx)
   107  		SetupRegistry(memory.NewRegistry())
   108  		SetupBroker(memBroker.NewBroker())
   109  
   110  		// set the store in the model
   111  		model.DefaultModel = model.NewModel(
   112  			model.WithStore(microStore.DefaultStore),
   113  		)
   114  
   115  		microRuntime.DefaultRuntime = local.NewRuntime()
   116  
   117  		var err error
   118  		microEvents.DefaultStream, err = memStream.NewStream()
   119  		if err != nil {
   120  			logger.Fatalf("Error configuring stream: %v", err)
   121  		}
   122  		microEvents.DefaultStore = evStore.NewStore(
   123  			evStore.WithStore(microStore.DefaultStore),
   124  		)
   125  
   126  		microStore.DefaultBlobStore, err = file.NewBlobStore()
   127  		if err != nil {
   128  			logger.Fatalf("Error configuring file blob store: %v", err)
   129  		}
   130  
   131  		return nil
   132  	},
   133  }
   134  
   135  // Kubernetes profile to run on kubernetes with zero deps. Designed for use with the micro helm chart
   136  var Kubernetes = &Profile{
   137  	Name: "kubernetes",
   138  	Setup: func(ctx *cli.Context) (err error) {
   139  		microAuth.DefaultAuth = jwt.NewAuth()
   140  		SetupJWT(ctx)
   141  
   142  		microRuntime.DefaultRuntime = kubernetes.NewRuntime()
   143  		microBuilder.DefaultBuilder, err = golang.NewBuilder()
   144  		if err != nil {
   145  			logger.Fatalf("Error configuring golang builder: %v", err)
   146  		}
   147  
   148  		microEvents.DefaultStream, err = memStream.NewStream()
   149  		if err != nil {
   150  			logger.Fatalf("Error configuring stream: %v", err)
   151  		}
   152  
   153  		microStore.DefaultStore = file.NewStore(file.WithDir("/store"))
   154  		microStore.DefaultBlobStore, err = file.NewBlobStore(file.WithDir("/store/blob"))
   155  		if err != nil {
   156  			logger.Fatalf("Error configuring file blob store: %v", err)
   157  		}
   158  
   159  		// set the store in the model
   160  		model.DefaultModel = model.NewModel(
   161  			model.WithStore(microStore.DefaultStore),
   162  		)
   163  
   164  		// the registry service uses the memory registry, the other core services will use the default
   165  		// rpc client and call the registry service
   166  		if ctx.Args().Get(1) == "registry" {
   167  			SetupRegistry(memory.NewRegistry())
   168  		}
   169  
   170  		// the broker service uses the memory broker, the other core services will use the default
   171  		// rpc client and call the broker service
   172  		if ctx.Args().Get(1) == "broker" {
   173  			SetupBroker(memBroker.NewBroker())
   174  		}
   175  
   176  		config.DefaultConfig, err = storeConfig.NewConfig(microStore.DefaultStore, "")
   177  		if err != nil {
   178  			logger.Fatalf("Error configuring config: %v", err)
   179  		}
   180  		SetupConfigSecretKey(ctx)
   181  
   182  		// Use k8s routing which is DNS based
   183  		router.DefaultRouter = k8sRouter.NewRouter()
   184  		client.DefaultClient.Init(client.Router(router.DefaultRouter))
   185  
   186  		// Configure tracing with Jaeger:
   187  		tracingServiceName := ctx.Args().Get(1)
   188  		if len(tracingServiceName) == 0 {
   189  			tracingServiceName = "Micro"
   190  		}
   191  		openTracer, _, err := jaeger.New(
   192  			opentelemetry.WithServiceName(tracingServiceName),
   193  			opentelemetry.WithTraceReporterAddress("localhost:6831"),
   194  		)
   195  		if err != nil {
   196  			logger.Fatalf("Error configuring opentracing: %v", err)
   197  		}
   198  		opentelemetry.DefaultOpenTracer = openTracer
   199  
   200  		return nil
   201  	},
   202  }
   203  
   204  var Server = &Profile{
   205  	Name: "server",
   206  	Setup: func(ctx *cli.Context) error {
   207  		microAuth.DefaultAuth = jwt.NewAuth()
   208  		microStore.DefaultStore = file.NewStore(file.WithDir(filepath.Join(user.Dir, "server", "store")))
   209  		SetupConfigSecretKey(ctx)
   210  		config.DefaultConfig, _ = storeConfig.NewConfig(microStore.DefaultStore, "")
   211  		SetupJWT(ctx)
   212  
   213  		// the registry service uses the memory registry, the other core services will use the default
   214  		// rpc client and call the registry service
   215  		if ctx.Args().Get(1) == "registry" {
   216  			SetupRegistry(memory.NewRegistry())
   217  		} else {
   218  			// set the registry address
   219  			registry.DefaultRegistry.Init(
   220  				registry.Addrs("localhost:8000"),
   221  			)
   222  
   223  			SetupRegistry(registry.DefaultRegistry)
   224  		}
   225  
   226  		// the broker service uses the memory broker, the other core services will use the default
   227  		// rpc client and call the broker service
   228  		if ctx.Args().Get(1) == "broker" {
   229  			SetupBroker(memBroker.NewBroker())
   230  		} else {
   231  			broker.DefaultBroker.Init(
   232  				broker.Addrs("localhost:8003"),
   233  			)
   234  			SetupBroker(broker.DefaultBroker)
   235  		}
   236  
   237  		// set the store in the model
   238  		model.DefaultModel = model.NewModel(
   239  			model.WithStore(microStore.DefaultStore),
   240  		)
   241  
   242  		// use the local runtime, note: the local runtime is designed to run source code directly so
   243  		// the runtime builder should NOT be set when using this implementation
   244  		microRuntime.DefaultRuntime = local.NewRuntime()
   245  
   246  		var err error
   247  		microEvents.DefaultStream, err = memStream.NewStream()
   248  		if err != nil {
   249  			logger.Fatalf("Error configuring stream: %v", err)
   250  		}
   251  		microEvents.DefaultStore = evStore.NewStore(
   252  			evStore.WithStore(microStore.DefaultStore),
   253  		)
   254  
   255  		microStore.DefaultBlobStore, err = file.NewBlobStore()
   256  		if err != nil {
   257  			logger.Fatalf("Error configuring file blob store: %v", err)
   258  		}
   259  
   260  		// Configure tracing with Jaeger (forced tracing):
   261  		tracingServiceName := ctx.Args().Get(1)
   262  		if len(tracingServiceName) == 0 {
   263  			tracingServiceName = "Micro"
   264  		}
   265  		openTracer, _, err := jaeger.New(
   266  			opentelemetry.WithServiceName(tracingServiceName),
   267  			opentelemetry.WithSamplingRate(1),
   268  		)
   269  		if err != nil {
   270  			logger.Fatalf("Error configuring opentracing: %v", err)
   271  		}
   272  		opentelemetry.DefaultOpenTracer = openTracer
   273  
   274  		return nil
   275  	},
   276  }
   277  
   278  // Service is the default for any services run
   279  var Service = &Profile{
   280  	Name:  "service",
   281  	Setup: func(ctx *cli.Context) error { return nil },
   282  }
   283  
   284  // Test profile is used for the go test suite
   285  var Test = &Profile{
   286  	Name: "test",
   287  	Setup: func(ctx *cli.Context) error {
   288  		microAuth.DefaultAuth = noop.NewAuth()
   289  		microStore.DefaultStore = mem.NewStore()
   290  		microStore.DefaultBlobStore, _ = file.NewBlobStore()
   291  		config.DefaultConfig, _ = storeConfig.NewConfig(microStore.DefaultStore, "")
   292  		SetupRegistry(memory.NewRegistry())
   293  		// set the store in the model
   294  		model.DefaultModel = model.NewModel(
   295  			model.WithStore(microStore.DefaultStore),
   296  		)
   297  		return nil
   298  	},
   299  }
   300  
   301  // SetupRegistry configures the registry
   302  func SetupRegistry(reg registry.Registry) {
   303  	registry.DefaultRegistry = reg
   304  	router.DefaultRouter = regRouter.NewRouter(router.Registry(reg))
   305  	client.DefaultClient.Init(client.Registry(reg), client.Router(router.DefaultRouter))
   306  	server.DefaultServer.Init(server.Registry(reg))
   307  }
   308  
   309  // SetupBroker configures the broker
   310  func SetupBroker(b broker.Broker) {
   311  	broker.DefaultBroker = b
   312  	client.DefaultClient.Init(client.Broker(b))
   313  	server.DefaultServer.Init(server.Broker(b))
   314  }
   315  
   316  // SetupJWT configures the default internal system rules
   317  func SetupJWT(ctx *cli.Context) {
   318  	for _, rule := range inAuth.SystemRules {
   319  		if err := microAuth.DefaultAuth.Grant(rule); err != nil {
   320  			logger.Fatal("Error creating default rule: %v", err)
   321  		}
   322  	}
   323  }
   324  
   325  func SetupConfigSecretKey(ctx *cli.Context) {
   326  	key := ctx.String("config_secret_key")
   327  	if len(key) == 0 {
   328  		k, err := user.GetConfigSecretKey()
   329  		if err != nil {
   330  			logger.Fatal("Error getting config secret: %v", err)
   331  		}
   332  		os.Setenv("MICRO_CONFIG_SECRET_KEY", k)
   333  	}
   334  }