Documentation
¶
Index ¶
- Constants
- Variables
- func CreateTypeSet(ts map[string]px.Type) px.TypeSet
- func FederatedLoader(parentLoader px.Loader) px.Loader
- func NewSubService(def serviceapi.Definition) serviceapi.Service
- type Builder
- func (ds *Builder) BuildResource(goType interface{}, bld func(f ResourceTypeBuilder)) px.AnnotatedType
- func (ds *Builder) RegisterAPI(name string, callable interface{})
- func (ds *Builder) RegisterApiType(name string, callable interface{})
- func (ds *Builder) RegisterHandler(name string, callable interface{}, stateType px.Type)
- func (ds *Builder) RegisterState(name string, state wf.State)
- func (ds *Builder) RegisterStateConverter(sf wf.StateConverter)
- func (ds *Builder) RegisterStep(step wf.Step)
- func (ds *Builder) RegisterType(typ px.Type)
- func (ds *Builder) RegisterTypes(namespace string, values ...interface{}) []px.Type
- func (ds *Builder) Server() *Server
- type ResourceTypeBuilder
- type Server
- func (s *Server) AddApi(name string, callable interface{}) serviceapi.Definition
- func (s *Server) Identifier(px.Context) px.TypedName
- func (s *Server) Invoke(c px.Context, api, name string, arguments ...px.Value) (result px.Value)
- func (s *Server) Metadata(px.Context) (typeSet px.TypeSet, definitions []serviceapi.Definition)
- func (s *Server) State(c px.Context, name string, parameters px.OrderedMap) px.PuppetObject
Examples ¶
Constants ¶
const ( AlreadyRegistered = `WF_ALREADY_REGISTERED` ApiTypeNotRegistered = `WF_API_TYPE_NOT_REGISTERED` IllegalTypeName = `WF_ILLEGAL_TYPE_NAME` NoCommonNamespace = `WF_NO_COMMON_NAMESPACE` NoSuchApi = `WF_NO_SUCH_API` NoSuchMethod = `WF_NO_SUCH_METHOD` NoSuchState = `WF_NO_SUCH_STATE` NotFound = `WF_NOT_FOUND` NotFunc = `WF_NOT_FUNC` NotPuppetObject = `WF_NOT_PUPPET_OBJECT` NoStateConverter = `WF_NO_STATE_CONVERTER` TypeNameClash = `WF_TYPE_NAME_CLASH` )
Variables ¶
var ErrorMetaType px.ObjectType
var ParameterMetaType px.ObjectType
var ServerVersion = semver.MustParseVersion(`0.1.0`)
Functions ¶
func FederatedLoader ¶
New creates a new federated loader instance
func NewSubService ¶
func NewSubService(def serviceapi.Definition) serviceapi.Service
Types ¶
type Builder ¶
type Builder struct {
// contains filtered or unexported fields
}
func (*Builder) BuildResource ¶
func (ds *Builder) BuildResource(goType interface{}, bld func(f ResourceTypeBuilder)) px.AnnotatedType
func (*Builder) RegisterAPI ¶
RegisterAPI registers a struct as an invokable. The callable instance given as the argument becomes the actual receiver the calls.
func (*Builder) RegisterApiType ¶
RegisterAPIType registers a the type of a struct as an invokable type. The struct should be a zero value. This method must be used to ensure that all type info is present for callable instances added to an already created service
func (*Builder) RegisterHandler ¶
RegisterHandler registers a callable struct as an invokable capable of handling a state described using px.Type. The callable instance given as the argument becomes the actual receiver the calls.
func (*Builder) RegisterState ¶
RegisterState registers the unresolved state of a resource.
func (*Builder) RegisterStateConverter ¶
func (ds *Builder) RegisterStateConverter(sf wf.StateConverter)
func (*Builder) RegisterStep ¶
RegisterStep registers an step
func (*Builder) RegisterType ¶
func (*Builder) RegisterTypes ¶
RegisterTypes registers arbitrary Go types to the TypeSet exported by this service.
A value is typically a pointer to the zero value of a struct. The name of the generated type for that struct will be the struct name prefixed by the service ID.
Example (AnnotatedTypeSet) ¶
package main
import (
"bytes"
"fmt"
"os"
"github.com/lyraproj/pcore/pcore"
"github.com/lyraproj/pcore/px"
"github.com/lyraproj/pcore/serialization"
"github.com/lyraproj/pcore/types"
"github.com/lyraproj/servicesdk/annotation"
"github.com/lyraproj/servicesdk/service"
)
type OwnerRes struct {
Id *string
Phone string
}
type ContainedRes struct {
Id *string
OwnerId string
Stuff string
}
func main() {
pcore.Do(func(c px.Context) {
sb := service.NewServiceBuilder(c, `My::Service`)
sb.RegisterTypes("My",
sb.BuildResource(&OwnerRes{}, func(rtb service.ResourceTypeBuilder) {
rtb.ProvidedAttributes(`id`)
rtb.ImmutableAttributes(`telephoneNumber`)
rtb.Tags(map[string]string{`Phone`: `name=>telephoneNumber`})
rtb.AddRelationship(`mine`, `My::ContainedRes`, annotation.KindContained, annotation.CardinalityMany, ``,
[]string{`id`, `ownerId`})
}),
sb.BuildResource(&ContainedRes{}, func(rtb service.ResourceTypeBuilder) {
rtb.ProvidedAttributes(`id`)
rtb.AddRelationship(`owner`, `My::OwnerRes`, annotation.KindContainer, annotation.CardinalityOne, ``,
[]string{`ownerId`, `id`})
}),
)
s := sb.Server()
ts, md := s.Metadata(c)
bld := bytes.NewBufferString(``)
coll := serialization.NewJsonStreamer(bld)
sr := serialization.NewSerializer(pcore.RootContext(), px.EmptyMap)
sr.Convert(types.WrapValues([]px.Value{ts, px.Wrap(c, md)}), coll)
dr := serialization.NewDeserializer(c, px.EmptyMap)
serialization.JsonToData(`/tmp/tst`, bld, dr)
dt := dr.Value().(*types.Array)
dt.At(0).ToString(os.Stdout, px.PrettyExpanded, nil)
fmt.Println()
})
}
Output: TypeSet[{ pcore_uri => 'http://puppet.com/2016.1/pcore', pcore_version => '1.0.0', name_authority => 'http://puppet.com/2016.1/runtime', name => 'My', version => '0.1.0', types => { ContainedRes => { annotations => { Lyra::Resource => { 'providedAttributes' => ['id'], 'relationships' => { 'owner' => { 'type' => OwnerRes, 'kind' => 'container', 'cardinality' => 'one', 'keys' => ['ownerId', 'id'] } } } }, attributes => { 'id' => Optional[String], 'ownerId' => String, 'stuff' => String } }, OwnerRes => { annotations => { Lyra::Resource => { 'immutableAttributes' => ['telephoneNumber'], 'providedAttributes' => ['id'], 'relationships' => { 'mine' => { 'type' => ContainedRes, 'kind' => 'contained', 'cardinality' => 'many', 'keys' => ['id', 'ownerId'] } } } }, attributes => { 'id' => Optional[String], 'telephoneNumber' => String } } } }]
Example (NestedType) ¶
package main
import (
"fmt"
"os"
"github.com/lyraproj/pcore/pcore"
"github.com/lyraproj/pcore/px"
"github.com/lyraproj/servicesdk/service"
)
type MyRes struct {
Name string
Phone string
}
type MyOuterRes struct {
Who *MyRes
What string
}
func main() {
pcore.Do(func(c px.Context) {
sb := service.NewServiceBuilder(c, `My::Service`)
sb.RegisterTypes("My", &MyOuterRes{})
s := sb.Server()
ts, _ := s.Metadata(c)
ts.ToString(os.Stdout, px.PrettyExpanded, nil)
fmt.Println()
})
}
Output: TypeSet[{ pcore_uri => 'http://puppet.com/2016.1/pcore', pcore_version => '1.0.0', name_authority => 'http://puppet.com/2016.1/runtime', name => 'My', version => '0.1.0', types => { MyOuterRes => { attributes => { 'who' => Optional[MyRes], 'what' => String } }, MyRes => { attributes => { 'name' => String, 'phone' => String } } } }]
Example (RecursiveType) ¶
package main
import (
"fmt"
"os"
"time"
"github.com/lyraproj/pcore/pcore"
"github.com/lyraproj/pcore/px"
"github.com/lyraproj/servicesdk/service"
)
type MyRes struct {
Name string
Phone string
}
type Person struct {
Who *MyRes
Children []*Person
Born time.Time
}
func main() {
pcore.Do(func(c px.Context) {
sb := service.NewServiceBuilder(c, `My::Service`)
sb.RegisterTypes("My", &Person{})
s := sb.Server()
ts, _ := s.Metadata(c)
ts.ToString(os.Stdout, px.PrettyExpanded, nil)
fmt.Println()
})
}
Output: TypeSet[{ pcore_uri => 'http://puppet.com/2016.1/pcore', pcore_version => '1.0.0', name_authority => 'http://puppet.com/2016.1/runtime', name => 'My', version => '0.1.0', types => { MyRes => { attributes => { 'name' => String, 'phone' => String } }, Person => { attributes => { 'who' => Optional[MyRes], 'children' => Array[Optional[Person]], 'born' => Timestamp } } } }]
type ResourceTypeBuilder ¶
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
func (*Server) AddApi ¶
func (s *Server) AddApi(name string, callable interface{}) serviceapi.Definition
func (*Server) Invoke ¶
Example ¶
package main
import (
"fmt"
"github.com/lyraproj/pcore/pcore"
"github.com/lyraproj/pcore/px"
"github.com/lyraproj/servicesdk/service"
)
type testAPI struct{}
func (*testAPI) First() string {
return `first`
}
func (*testAPI) Second(suffix string) string {
return `second ` + suffix
}
func main() {
pcore.Do(func(c px.Context) {
api := `My::TheApi`
sb := service.NewServiceBuilder(c, `My::Service`)
sb.RegisterAPI(api, &testAPI{})
s := sb.Server()
fmt.Println(s.Invoke(c, api, `first`))
fmt.Println(s.Invoke(c, api, `second`, px.Wrap(c, `place`)))
})
}
Output: first second place
func (*Server) Metadata ¶
func (s *Server) Metadata(px.Context) (typeSet px.TypeSet, definitions []serviceapi.Definition)
Example (Api) ¶
package main
import (
"fmt"
"os"
"github.com/lyraproj/pcore/pcore"
"github.com/lyraproj/pcore/px"
"github.com/lyraproj/servicesdk/service"
"github.com/lyraproj/servicesdk/wf"
)
type MyIdentityService struct {
extToId map[string]px.URI
idToExt map[px.URI]string
}
func (is *MyIdentityService) GetExternal(id px.URI) (string, error) {
if ext, ok := is.idToExt[id]; ok {
return ext, nil
}
return ``, wf.NotFound
}
func (is *MyIdentityService) GetInternal(ext string) (px.URI, error) {
if id, ok := is.extToId[ext]; ok {
return id, nil
}
return px.URI(``), wf.NotFound
}
func main() {
pcore.Do(func(c px.Context) {
sb := service.NewServiceBuilder(c, `My::Service`)
sb.RegisterAPI(`My::Identity`, &MyIdentityService{map[string]px.URI{}, map[px.URI]string{}})
s := sb.Server()
ts, defs := s.Metadata(c)
ts.ToString(os.Stdout, px.PrettyExpanded, nil)
fmt.Println()
for _, def := range defs {
fmt.Println(px.ToPrettyString(def))
}
})
}
Output: TypeSet[{ pcore_uri => 'http://puppet.com/2016.1/pcore', pcore_version => '1.0.0', name_authority => 'http://puppet.com/2016.1/runtime', name => 'My', version => '0.1.0', types => { Identity => { functions => { 'getExternal' => Callable[ [String], String], 'getInternal' => Callable[ [String], String] } } } }] Service::Definition( 'identifier' => TypedName( 'namespace' => 'definition', 'name' => 'My::Identity' ), 'serviceId' => TypedName( 'namespace' => 'service', 'name' => 'My::Service' ), 'properties' => { 'interface' => My::Identity, 'style' => 'callable' } )
Example (Definitions) ¶
package main
import (
"fmt"
"github.com/lyraproj/issue/issue"
"github.com/lyraproj/servicesdk/lang/go/lyra"
"github.com/lyraproj/pcore/pcore"
"github.com/lyraproj/pcore/px"
"github.com/lyraproj/servicesdk/service"
)
type MyRes struct {
Name string
Phone string
}
func main() {
pcore.Do(func(c px.Context) {
sb := service.NewServiceBuilder(c, `My::Service`)
sb.RegisterTypes("My", &MyRes{})
sb.RegisterStep((&lyra.Workflow{
Steps: map[string]lyra.Step{
`X`: &lyra.Resource{
State: func(struct {
A string
B string `lookup:"foo"`
C int `puppet:"value=>23"`
D *string `puppet:"value=>undef"`
E *string
F *string `value:"77"`
}) *MyRes {
return &MyRes{Name: `Bob`, Phone: `12345`}
}},
`Y`: &lyra.Call{
Parameters: struct {
P string `lookup:"foo" alias:"B"`
}{},
StepName: `z`,
}}}).Resolve(c, `My::Test`, issue.ParseLocation(`(file: /test/x.go)`)))
s := sb.Server()
_, defs := s.Metadata(c)
for _, def := range defs {
fmt.Println(px.ToPrettyString(def))
}
})
}
Output: Service::Definition( 'identifier' => TypedName( 'namespace' => 'definition', 'name' => 'My::Test' ), 'serviceId' => TypedName( 'namespace' => 'service', 'name' => 'My::Service' ), 'properties' => { 'steps' => [ Service::Definition( 'identifier' => TypedName( 'namespace' => 'definition', 'name' => 'My::Test::X' ), 'serviceId' => TypedName( 'namespace' => 'service', 'name' => 'My::Service' ), 'properties' => { 'parameters' => [ Lyra::Parameter( 'name' => 'a', 'type' => String ), Lyra::Parameter( 'name' => 'b', 'type' => String, 'value' => Deferred( 'name' => 'lookup', 'arguments' => ['foo'] ) ), Lyra::Parameter( 'name' => 'c', 'type' => Integer, 'value' => 23 ), Lyra::Parameter( 'name' => 'd', 'type' => Optional[String] ), Lyra::Parameter( 'name' => 'e', 'type' => Optional[String] ), Lyra::Parameter( 'name' => 'f', 'type' => Optional[String], 'value' => '77' )], 'resourceType' => My::MyRes, 'style' => 'resource', 'origin' => '(file: /test/x.go)' } ), Service::Definition( 'identifier' => TypedName( 'namespace' => 'definition', 'name' => 'My::Test::Y' ), 'serviceId' => TypedName( 'namespace' => 'service', 'name' => 'My::Service' ), 'properties' => { 'parameters' => [ Lyra::Parameter( 'name' => 'p', 'type' => String, 'alias' => 'b', 'value' => Deferred( 'name' => 'lookup', 'arguments' => ['foo'] ) )], 'call' => 'z', 'style' => 'call', 'origin' => '(file: /test/x.go)' } )], 'style' => 'workflow', 'origin' => '(file: /test/x.go)' } )
Example (State) ¶
package main
import (
"fmt"
"github.com/lyraproj/issue/issue"
"github.com/lyraproj/servicesdk/lang/go/lyra"
"github.com/lyraproj/pcore/pcore"
"github.com/lyraproj/pcore/px"
"github.com/lyraproj/servicesdk/service"
)
type MyRes struct {
Name string
Phone string
}
func main() {
pcore.Do(func(c px.Context) {
sb := service.NewServiceBuilder(c, `My::Service`)
sb.RegisterTypes("My", &MyRes{})
sb.RegisterStateConverter(lyra.StateConverter)
sb.RegisterStep((&lyra.Workflow{
Steps: map[string]lyra.Step{
`X`: &lyra.Resource{
State: func(parameters struct {
A string
B string
}) *MyRes {
return &MyRes{Name: `Bob`, Phone: `12345`}
}}}}).Resolve(c, `My::Test`, issue.ParseLocation(`(file: /test/x.go)`)))
s := sb.Server()
fmt.Println(px.ToPrettyString(s.State(c, `My::Test::X`, px.EmptyMap)))
})
}
Output: My::MyRes( 'name' => 'Bob', 'phone' => '12345' )
Example (TypeSet) ¶
package main
import (
"fmt"
"os"
"github.com/lyraproj/pcore/pcore"
"github.com/lyraproj/pcore/px"
"github.com/lyraproj/servicesdk/service"
)
type testAPI struct{}
func (*testAPI) First() string {
return `first`
}
func (*testAPI) Second(suffix string) string {
return `second ` + suffix
}
type MyRes struct {
Name string
Phone string
}
func main() {
pcore.Do(func(c px.Context) {
sb := service.NewServiceBuilder(c, `My::Service`)
sb.RegisterAPI(`My::TheApi`, &testAPI{})
sb.RegisterTypes("My", &MyRes{})
s := sb.Server()
ts, _ := s.Metadata(c)
ts.ToString(os.Stdout, px.PrettyExpanded, nil)
fmt.Println()
})
}
Output: TypeSet[{ pcore_uri => 'http://puppet.com/2016.1/pcore', pcore_version => '1.0.0', name_authority => 'http://puppet.com/2016.1/runtime', name => 'My', version => '0.1.0', types => { MyRes => { attributes => { 'name' => String, 'phone' => String } }, TheApi => { functions => { 'first' => Callable[ [0, 0], String], 'second' => Callable[ [String], String] } } } }]
func (*Server) State ¶
func (s *Server) State(c px.Context, name string, parameters px.OrderedMap) px.PuppetObject