Merge pull request #52 from spotify/ben/listing-components

Listing Templates Dynamically
This commit is contained in:
Ben Lambert
2020-02-06 04:00:01 +01:00
committed by GitHub
9 changed files with 158 additions and 72 deletions
+1
View File
@@ -0,0 +1 @@
main
-3
View File
@@ -8,8 +8,5 @@ require (
github.com/golang/protobuf v1.3.3
github.com/spotify/backstage/proto v0.0.0-00010101000000-000000000000
go.etcd.io/bbolt v1.3.3
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3 // indirect
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135 // indirect
google.golang.org/grpc v1.27.0
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc // indirect
)
+50 -41
View File
@@ -56,39 +56,39 @@ func (m *Empty) XXX_DiscardUnknown() {
var xxx_messageInfo_Empty proto.InternalMessageInfo
type GetAllTemplatesResponse struct {
type GetAllTemplatesReply struct {
Templates []*Template `protobuf:"bytes,1,rep,name=templates,proto3" json:"templates,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *GetAllTemplatesResponse) Reset() { *m = GetAllTemplatesResponse{} }
func (m *GetAllTemplatesResponse) String() string { return proto.CompactTextString(m) }
func (*GetAllTemplatesResponse) ProtoMessage() {}
func (*GetAllTemplatesResponse) Descriptor() ([]byte, []int) {
func (m *GetAllTemplatesReply) Reset() { *m = GetAllTemplatesReply{} }
func (m *GetAllTemplatesReply) String() string { return proto.CompactTextString(m) }
func (*GetAllTemplatesReply) ProtoMessage() {}
func (*GetAllTemplatesReply) Descriptor() ([]byte, []int) {
return fileDescriptor_6737326b433dc57d, []int{1}
}
func (m *GetAllTemplatesResponse) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetAllTemplatesResponse.Unmarshal(m, b)
func (m *GetAllTemplatesReply) XXX_Unmarshal(b []byte) error {
return xxx_messageInfo_GetAllTemplatesReply.Unmarshal(m, b)
}
func (m *GetAllTemplatesResponse) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetAllTemplatesResponse.Marshal(b, m, deterministic)
func (m *GetAllTemplatesReply) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
return xxx_messageInfo_GetAllTemplatesReply.Marshal(b, m, deterministic)
}
func (m *GetAllTemplatesResponse) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetAllTemplatesResponse.Merge(m, src)
func (m *GetAllTemplatesReply) XXX_Merge(src proto.Message) {
xxx_messageInfo_GetAllTemplatesReply.Merge(m, src)
}
func (m *GetAllTemplatesResponse) XXX_Size() int {
return xxx_messageInfo_GetAllTemplatesResponse.Size(m)
func (m *GetAllTemplatesReply) XXX_Size() int {
return xxx_messageInfo_GetAllTemplatesReply.Size(m)
}
func (m *GetAllTemplatesResponse) XXX_DiscardUnknown() {
xxx_messageInfo_GetAllTemplatesResponse.DiscardUnknown(m)
func (m *GetAllTemplatesReply) XXX_DiscardUnknown() {
xxx_messageInfo_GetAllTemplatesReply.DiscardUnknown(m)
}
var xxx_messageInfo_GetAllTemplatesResponse proto.InternalMessageInfo
var xxx_messageInfo_GetAllTemplatesReply proto.InternalMessageInfo
func (m *GetAllTemplatesResponse) GetTemplates() []*Template {
func (m *GetAllTemplatesReply) GetTemplates() []*Template {
if m != nil {
return m.Templates
}
@@ -98,7 +98,8 @@ func (m *GetAllTemplatesResponse) GetTemplates() []*Template {
type Template struct {
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"`
User *v1.User `protobuf:"bytes,3,opt,name=user,proto3" json:"user,omitempty"`
Description string `protobuf:"bytes,3,opt,name=description,proto3" json:"description,omitempty"`
User *v1.User `protobuf:"bytes,4,opt,name=user,proto3" json:"user,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@@ -143,6 +144,13 @@ func (m *Template) GetName() string {
return ""
}
func (m *Template) GetDescription() string {
if m != nil {
return m.Description
}
return ""
}
func (m *Template) GetUser() *v1.User {
if m != nil {
return m.User
@@ -152,30 +160,31 @@ func (m *Template) GetUser() *v1.User {
func init() {
proto.RegisterType((*Empty)(nil), "spotify.backstage.scaffolder.v1.Empty")
proto.RegisterType((*GetAllTemplatesResponse)(nil), "spotify.backstage.scaffolder.v1.GetAllTemplatesResponse")
proto.RegisterType((*GetAllTemplatesReply)(nil), "spotify.backstage.scaffolder.v1.GetAllTemplatesReply")
proto.RegisterType((*Template)(nil), "spotify.backstage.scaffolder.v1.Template")
}
func init() { proto.RegisterFile("scaffolder/v1/scaffolder.proto", fileDescriptor_6737326b433dc57d) }
var fileDescriptor_6737326b433dc57d = []byte{
// 254 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x90, 0x4f, 0x4b, 0xc4, 0x30,
0x10, 0xc5, 0x49, 0x77, 0xfd, 0xb3, 0xb3, 0xb2, 0x42, 0x2e, 0x96, 0x1e, 0xb4, 0x54, 0x90, 0x7a,
0xc9, 0xd2, 0x7a, 0xd0, 0xab, 0x82, 0xec, 0xbd, 0xea, 0xc5, 0x5b, 0xba, 0x9d, 0x2e, 0xc1, 0xb6,
0x09, 0xcd, 0x58, 0xe8, 0xd1, 0x6f, 0x2e, 0x46, 0xba, 0x15, 0x51, 0x7a, 0x9b, 0x3c, 0xde, 0x2f,
0x33, 0xef, 0xc1, 0xb9, 0xdd, 0xca, 0xb2, 0xd4, 0x55, 0x81, 0xed, 0xba, 0x4b, 0xd6, 0xe3, 0x4b,
0x98, 0x56, 0x93, 0xe6, 0x17, 0xd6, 0x68, 0x52, 0x65, 0x2f, 0x72, 0xb9, 0x7d, 0xb3, 0x24, 0x77,
0x28, 0x7e, 0x78, 0xba, 0x24, 0x08, 0x54, 0x81, 0x0d, 0x29, 0xea, 0xbf, 0xf0, 0x61, 0xfe, 0x86,
0xa3, 0x23, 0x38, 0x78, 0xac, 0x0d, 0xf5, 0x51, 0x0e, 0x67, 0x1b, 0xa4, 0xfb, 0xaa, 0x7a, 0xc6,
0xda, 0x54, 0x92, 0xd0, 0x66, 0x68, 0x8d, 0x6e, 0x2c, 0xf2, 0x0d, 0x2c, 0x68, 0x10, 0x7d, 0x16,
0xce, 0xe2, 0x65, 0x7a, 0x2d, 0x26, 0x96, 0x8a, 0xe1, 0x9b, 0x6c, 0x64, 0xa3, 0x1d, 0x1c, 0x0f,
0x32, 0x5f, 0x81, 0xa7, 0x0a, 0x9f, 0x85, 0x2c, 0x5e, 0x64, 0x9e, 0x2a, 0x38, 0x87, 0x79, 0x23,
0x6b, 0xf4, 0x3d, 0xa7, 0xb8, 0x99, 0xdf, 0xc2, 0xfc, 0xdd, 0x62, 0xeb, 0xcf, 0x42, 0x16, 0x2f,
0xd3, 0xcb, 0x3f, 0x76, 0xee, 0xd3, 0x74, 0x89, 0x78, 0xb1, 0xd8, 0x66, 0x0e, 0x48, 0x3f, 0x18,
0xc0, 0xd3, 0xfe, 0x1c, 0x6e, 0xe1, 0xf4, 0x57, 0x36, 0x7e, 0x35, 0x19, 0xc0, 0xd5, 0x12, 0xdc,
0x4d, 0xfa, 0xfe, 0x69, 0xed, 0x61, 0xf5, 0x7a, 0x32, 0x1a, 0xbb, 0x24, 0x3f, 0x74, 0x85, 0xdf,
0x7c, 0x06, 0x00, 0x00, 0xff, 0xff, 0x6c, 0x28, 0xe6, 0x58, 0xcf, 0x01, 0x00, 0x00,
// 270 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x84, 0x91, 0x4f, 0x4b, 0xc4, 0x30,
0x10, 0xc5, 0xe9, 0x6e, 0xfd, 0xb3, 0x53, 0x59, 0x21, 0x78, 0x28, 0x3d, 0x68, 0xa9, 0x20, 0xf5,
0x92, 0xa5, 0x15, 0xf1, 0xac, 0x20, 0x7b, 0xaf, 0x7a, 0xf1, 0x22, 0xdd, 0x76, 0x2a, 0xc1, 0xb6,
0x09, 0xc9, 0x58, 0xe8, 0xc5, 0xbb, 0xdf, 0x5a, 0x8c, 0x74, 0xbb, 0xc8, 0x42, 0x6f, 0x93, 0x97,
0xf7, 0x4b, 0xe6, 0xcd, 0xc0, 0xb9, 0x29, 0xf2, 0xaa, 0x92, 0x75, 0x89, 0x7a, 0xd5, 0x25, 0xab,
0xf1, 0xc4, 0x95, 0x96, 0x24, 0xd9, 0x85, 0x51, 0x92, 0x44, 0xd5, 0xf3, 0x4d, 0x5e, 0x7c, 0x18,
0xca, 0xdf, 0x91, 0xef, 0x78, 0xba, 0x24, 0x08, 0x44, 0x89, 0x2d, 0x09, 0xea, 0x7f, 0xf1, 0xa1,
0xfe, 0x83, 0xa3, 0x23, 0x38, 0x78, 0x6c, 0x14, 0xf5, 0xd1, 0x1b, 0x9c, 0xad, 0x91, 0xee, 0xeb,
0xfa, 0x19, 0x1b, 0x55, 0xe7, 0x84, 0x26, 0x43, 0x55, 0xf7, 0x6c, 0x0d, 0x0b, 0x1a, 0x14, 0xdf,
0x09, 0xe7, 0xb1, 0x97, 0x5e, 0xf3, 0x89, 0x1f, 0xf9, 0xf0, 0x46, 0x36, 0xb2, 0xd1, 0xb7, 0x03,
0xc7, 0x83, 0xce, 0x96, 0x30, 0x13, 0xa5, 0xef, 0x84, 0x4e, 0xbc, 0xc8, 0x66, 0xa2, 0x64, 0x0c,
0xdc, 0x36, 0x6f, 0xd0, 0x9f, 0x59, 0xc5, 0xd6, 0x2c, 0x04, 0xaf, 0x44, 0x53, 0x68, 0xa1, 0x48,
0xc8, 0xd6, 0x9f, 0xdb, 0xab, 0x5d, 0x89, 0xdd, 0x81, 0xfb, 0x69, 0x50, 0xfb, 0x6e, 0xe8, 0xc4,
0x5e, 0x7a, 0xb9, 0xa7, 0xad, 0x6d, 0xda, 0x2e, 0xe1, 0x2f, 0x06, 0x75, 0x66, 0x81, 0xf4, 0x0b,
0xe0, 0x69, 0xdb, 0x30, 0x53, 0x70, 0xfa, 0x2f, 0x3a, 0xbb, 0x9a, 0x8c, 0x68, 0xa7, 0x16, 0xdc,
0x4e, 0xfa, 0xf6, 0x0d, 0xf5, 0x61, 0xf9, 0x7a, 0x32, 0xba, 0xba, 0x64, 0x73, 0x68, 0x97, 0x71,
0xf3, 0x13, 0x00, 0x00, 0xff, 0xff, 0x5b, 0x4d, 0x79, 0x5e, 0xeb, 0x01, 0x00, 0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@@ -190,7 +199,7 @@ const _ = grpc.SupportPackageIsVersion6
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://godoc.org/google.golang.org/grpc#ClientConn.NewStream.
type ScaffolderClient interface {
GetAllTemplates(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*GetAllTemplatesResponse, error)
GetAllTemplates(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*GetAllTemplatesReply, error)
}
type scaffolderClient struct {
@@ -201,8 +210,8 @@ func NewScaffolderClient(cc grpc.ClientConnInterface) ScaffolderClient {
return &scaffolderClient{cc}
}
func (c *scaffolderClient) GetAllTemplates(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*GetAllTemplatesResponse, error) {
out := new(GetAllTemplatesResponse)
func (c *scaffolderClient) GetAllTemplates(ctx context.Context, in *Empty, opts ...grpc.CallOption) (*GetAllTemplatesReply, error) {
out := new(GetAllTemplatesReply)
err := c.cc.Invoke(ctx, "/spotify.backstage.scaffolder.v1.Scaffolder/GetAllTemplates", in, out, opts...)
if err != nil {
return nil, err
@@ -212,14 +221,14 @@ func (c *scaffolderClient) GetAllTemplates(ctx context.Context, in *Empty, opts
// ScaffolderServer is the server API for Scaffolder service.
type ScaffolderServer interface {
GetAllTemplates(context.Context, *Empty) (*GetAllTemplatesResponse, error)
GetAllTemplates(context.Context, *Empty) (*GetAllTemplatesReply, error)
}
// UnimplementedScaffolderServer can be embedded to have forward compatible implementations.
type UnimplementedScaffolderServer struct {
}
func (*UnimplementedScaffolderServer) GetAllTemplates(ctx context.Context, req *Empty) (*GetAllTemplatesResponse, error) {
func (*UnimplementedScaffolderServer) GetAllTemplates(ctx context.Context, req *Empty) (*GetAllTemplatesReply, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetAllTemplates not implemented")
}
+40
View File
@@ -0,0 +1,40 @@
package app
import (
"context"
identity "github.com/spotify/backstage/backend/proto/identity/v1"
pb "github.com/spotify/backstage/proto/scaffolder/v1"
"github.com/spotify/backstage/scaffolder/repository"
)
// Server is the inventory Grpc server
type Server struct {
Repository *repository.Repository
}
// GetAllTemplates returns the local templatess
func (s *Server) GetAllTemplates(ctx context.Context, req *pb.Empty) (*pb.GetAllTemplatesReply, error) {
// todo (blam): yes we currently read the disk on every load. but it's fine for now 🤷‍♂️
definitions, err := s.Repository.Load()
var templates []*pb.Template
for _, definition := range definitions {
template := &pb.Template{
Id: definition.ID,
Name: definition.Name,
Description: definition.Description,
// need to actually call the idenity service here to get the
// actual user and propgate back when needed.
User: &identity.User{
Id: "spotify",
Name: "Spotify",
},
}
templates = append(templates, template)
}
return &pb.GetAllTemplatesReply{
Templates: templates,
}, err
}
+4
View File
@@ -2,9 +2,13 @@ module github.com/spotify/backstage/scaffolder
go 1.13
replace github.com/spotify/backstage/proto => ../proto
replace github.com/spotify/backstage/backend/proto => ../proto
require (
github.com/golang/protobuf v1.3.3
github.com/spotify/backstage/backend/proto v0.0.0-00010101000000-000000000000
github.com/spotify/backstage/proto v0.0.0-00010101000000-000000000000
google.golang.org/grpc v1.27.0
)
+4 -25
View File
@@ -1,12 +1,12 @@
package main
import (
"context"
"log"
"net"
pb "github.com/spotify/backstage/backend/proto/scaffolder/v1"
identity "github.com/spotify/backstage/backend/proto/identity/v1"
pb "github.com/spotify/backstage/proto/scaffolder/v1"
"github.com/spotify/backstage/scaffolder/app"
"google.golang.org/grpc"
)
@@ -21,28 +21,7 @@ func main() {
}
grpcServer := grpc.NewServer()
pb.RegisterScaffolderServer(grpcServer, &server{})
pb.RegisterScaffolderServer(grpcServer, &app.Server{})
log.Println("Serving Scaffolder Service")
grpcServer.Serve(lis)
}
type server struct {
}
func (s *server) GetAllTemplates(ctx context.Context, req *pb.Empty) (*pb.GetAllTemplatesResponse, error) {
template := &pb.Template {
Id: "react-ssr-template",
Name: "React SSR Template",
User: &identity.User {
Id: "spotify",
Name: "Spotify",
},
}
templates := []*pb.Template{ template }
return &pb.GetAllTemplatesResponse{
Templates: templates,
}, nil
}
@@ -0,0 +1,49 @@
package repository
import (
"encoding/json"
"fmt"
"io/ioutil"
"path/filepath"
)
// Repository Repository
type Repository struct{}
// TemplateDefinition maps to whats stored in the repo
type TemplateDefinition struct {
ID string
Name string
Description string
OwnerID string
}
// Load will return all the Repository templates
func (s *Repository) Load() ([]*TemplateDefinition, error) {
templateInfoFilePaths, err := filepath.Glob("templates/**/template-info.json")
var templateDefinitions []*TemplateDefinition
if err != nil {
fmt.Errorf("failed to load template-info files")
return nil, err
}
for _, templatePath := range templateInfoFilePaths {
content, err := ioutil.ReadFile(templatePath)
if err != nil {
fmt.Errorf("failed to load path for %s", templatePath)
continue
}
definition := TemplateDefinition{}
err = json.Unmarshal([]byte(content), &definition)
if err != nil {
fmt.Errorf("failed to unmarshal %s", templatePath)
continue
}
templateDefinitions = append(templateDefinitions, &definition)
}
return templateDefinitions, err
}
@@ -0,0 +1,6 @@
{
"id": "react-ssr-template",
"name": "React SSR",
"description": "Next.js application skeleton for creating isomorphic web applications.",
"ownerId": "ownerId"
}
+4 -3
View File
@@ -7,17 +7,18 @@ import "identity/v1/identity.proto";
option go_package = "scaffolderv1";
service Scaffolder {
rpc GetAllTemplates(Empty) returns (GetAllTemplatesResponse);
rpc GetAllTemplates(Empty) returns (GetAllTemplatesReply);
}
message Empty {}
message GetAllTemplatesResponse {
message GetAllTemplatesReply {
repeated Template templates = 1;
}
message Template {
string id = 1;
string name = 2;
spotify.backstage.identity.v1.User user = 3;
string description = 3;
spotify.backstage.identity.v1.User user = 4;
}