NONRTRIC-946: Add support for Kong routes 63/11963/14
authorDenisGNoonan <denis.noonan@est.tech>
Tue, 24 Oct 2023 08:43:52 +0000 (09:43 +0100)
committerDenisGNoonan <denis.noonan@est.tech>
Thu, 7 Mar 2024 12:48:12 +0000 (12:48 +0000)
Issue-ID: NONRTRIC-946
Signed-off-by: DenisGNoonan <denis.noonan@est.tech>
Change-Id: Iadf368d9dcfc53d118a636ac33652f7bf524d043

64 files changed:
.gitignore
r1-sme-manager/.gitignore [deleted file]
r1-sme-manager/go.mod [deleted file]
r1-sme-manager/go.sum [deleted file]
servicemanager/.env.example [new file with mode: 0644]
servicemanager/Dockerfile [new file with mode: 0644]
servicemanager/README.md [new file with mode: 0644]
servicemanager/build-servicemanager-ubuntu.sh [new file with mode: 0755]
servicemanager/container-tag.yaml [new file with mode: 0644]
servicemanager/deploy/manifests/capifcore.yaml [new file with mode: 0644]
servicemanager/deploy/manifests/kong-postgres-pv.yaml [new file with mode: 0644]
servicemanager/deploy/manifests/kong-postgres-pvc.yaml [new file with mode: 0644]
servicemanager/deploy/manifests/servicemanager.yaml [new file with mode: 0644]
servicemanager/deploy/manifests/values.yaml [new file with mode: 0644]
servicemanager/deploy/src/delete-from-k8s.sh [new file with mode: 0755]
servicemanager/deploy/src/deploy-to-k8s.sh [new file with mode: 0755]
servicemanager/docker-compose.yaml [new file with mode: 0644]
servicemanager/generate.sh [moved from r1-sme-manager/generate-service-publish-and-discovery.sh with 51% similarity]
servicemanager/go.mod [new file with mode: 0644]
servicemanager/go.sum [new file with mode: 0644]
servicemanager/gogeneratorspecs/common/generator_settings.yaml [new file with mode: 0644]
servicemanager/gogeneratorspecs/common29122/generator_settings.yaml [new file with mode: 0644]
servicemanager/gogeneratorspecs/common29571/generator_settings.yaml [new file with mode: 0644]
servicemanager/gogeneratorspecs/discoverserviceapi/generator_settings_client.yaml [new file with mode: 0644]
servicemanager/gogeneratorspecs/discoverserviceapi/generator_settings_server.yaml [new file with mode: 0644]
servicemanager/gogeneratorspecs/discoverserviceapi/generator_settings_types.yaml [new file with mode: 0644]
servicemanager/gogeneratorspecs/invokermanagementapi/generator_settings_client.yaml [new file with mode: 0644]
servicemanager/gogeneratorspecs/invokermanagementapi/generator_settings_server.yaml [new file with mode: 0644]
servicemanager/gogeneratorspecs/invokermanagementapi/generator_settings_types.yaml [new file with mode: 0644]
servicemanager/gogeneratorspecs/providermanagementapi/generator_settings_client.yaml [new file with mode: 0644]
servicemanager/gogeneratorspecs/providermanagementapi/generator_settings_server.yaml [new file with mode: 0644]
servicemanager/gogeneratorspecs/providermanagementapi/generator_settings_types.yaml [new file with mode: 0644]
servicemanager/gogeneratorspecs/publishserviceapi/generator_settings_client.yaml [new file with mode: 0644]
servicemanager/gogeneratorspecs/publishserviceapi/generator_settings_server.yaml [new file with mode: 0644]
servicemanager/gogeneratorspecs/publishserviceapi/generator_settings_types.yaml [new file with mode: 0644]
servicemanager/internal/common/common.gen.go [new file with mode: 0644]
servicemanager/internal/common29122/common29122.gen.go [new file with mode: 0644]
servicemanager/internal/common29571/common29571.gen.go [new file with mode: 0644]
servicemanager/internal/discoverservice/discoverservice.go [new file with mode: 0644]
servicemanager/internal/discoverservice/discoverservice_test.go [new file with mode: 0644]
servicemanager/internal/discoverserviceapi/discoverserviceapi-client.gen.go [new file with mode: 0644]
servicemanager/internal/discoverserviceapi/discoverserviceapi-server.gen.go [new file with mode: 0644]
servicemanager/internal/discoverserviceapi/discoverserviceapi-types.gen.go [new file with mode: 0644]
servicemanager/internal/envreader/envreader.go [new file with mode: 0644]
servicemanager/internal/invokermanagement/invokermanagement.go [new file with mode: 0644]
servicemanager/internal/invokermanagement/invokermanagement_test.go [new file with mode: 0644]
servicemanager/internal/invokermanagementapi/invokermanagementapi-client.gen.go [new file with mode: 0644]
servicemanager/internal/invokermanagementapi/invokermanagementapi-server.gen.go [new file with mode: 0644]
servicemanager/internal/invokermanagementapi/invokermanagementapi-types.gen.go [new file with mode: 0644]
servicemanager/internal/kongclear/kongclear.go [new file with mode: 0644]
servicemanager/internal/kongclearup.go [new file with mode: 0644]
servicemanager/internal/providermanagement/providermanagement.go [new file with mode: 0644]
servicemanager/internal/providermanagement/providermanagement_test.go [new file with mode: 0644]
servicemanager/internal/providermanagementapi/providermanagementapi-client.gen.go [new file with mode: 0644]
servicemanager/internal/providermanagementapi/providermanagementapi-server.gen.go [new file with mode: 0644]
servicemanager/internal/providermanagementapi/providermanagementapi-types.gen.go [new file with mode: 0644]
servicemanager/internal/publishservice/publishservice.go [new file with mode: 0644]
servicemanager/internal/publishservice/publishservice_test.go [new file with mode: 0644]
servicemanager/internal/publishserviceapi/publishserviceapi-client.gen.go [new file with mode: 0644]
servicemanager/internal/publishserviceapi/publishserviceapi-server.gen.go [new file with mode: 0644]
servicemanager/internal/publishserviceapi/publishserviceapi-types.gen.go [new file with mode: 0644]
servicemanager/internal/publishserviceapi/typeupdate.go [new file with mode: 0644]
servicemanager/main.go [new file with mode: 0644]
servicemanager/main_test.go [new file with mode: 0644]

index 9e770b5..0dc4f08 100644 (file)
@@ -4,4 +4,16 @@
 docs/_build/
 .project
 .settings
-.pydevproject
\ No newline at end of file
+.pydevproject
+go.work*
+servicemanager.tar.gz
+servicemanager/servicemanager
+servicemanager/specs
+coverage.txt
+# Ignore all .env files
+.env*
+# Except for .env.example
+!.env.example
+# Ignore all files in folders named "mocks"
+**/mocks/*
+servicemanager/specs/
diff --git a/r1-sme-manager/.gitignore b/r1-sme-manager/.gitignore
deleted file mode 100644 (file)
index 3721741..0000000
+++ /dev/null
@@ -1 +0,0 @@
-internal/
\ No newline at end of file
diff --git a/r1-sme-manager/go.mod b/r1-sme-manager/go.mod
deleted file mode 100644 (file)
index a0eacc9..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-module oransc.org/nonrtric/r1-sme-manager
-
-go 1.19
-
-require (
-       github.com/deepmap/oapi-codegen v1.11.0
-       github.com/getkin/kin-openapi v0.106.0
-       github.com/labstack/echo/v4 v4.10.2
-       github.com/sirupsen/logrus v1.9.0
-       github.com/stretchr/testify v1.8.1
-       github.com/swaggo/swag v1.8.12
-       gopkg.in/yaml.v2 v2.4.0
-       helm.sh/helm/v3 v3.9.0
-       k8s.io/cli-runtime v0.25.3-rc.0
-       k8s.io/client-go v0.25.3-rc.0
-)
-
-require (
-       github.com/KyleBanks/depth v1.2.1 // indirect
-       github.com/go-openapi/spec v0.20.8 // indirect
-       github.com/pkg/errors v0.9.1 // indirect
-       github.com/swaggo/files/v2 v2.0.0 // indirect
-       golang.org/x/tools v0.8.0 // indirect
-)
-
-require (
-       github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
-       github.com/BurntSushi/toml v1.1.0 // indirect
-       github.com/MakeNowJust/heredoc v1.0.0 // indirect
-       github.com/Masterminds/goutils v1.1.1 // indirect
-       github.com/Masterminds/semver/v3 v3.1.1 // indirect
-       github.com/Masterminds/sprig/v3 v3.2.2 // indirect
-       github.com/Masterminds/squirrel v1.5.3 // indirect
-       github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect
-       github.com/beorn7/perks v1.0.1 // indirect
-       github.com/cespare/xxhash/v2 v2.1.2 // indirect
-       github.com/chai2010/gettext-go v1.0.2 // indirect
-       github.com/containerd/containerd v1.6.6 // indirect
-       github.com/cyphar/filepath-securejoin v0.2.3 // indirect
-       github.com/davecgh/go-spew v1.1.1 // indirect
-       github.com/docker/cli v20.10.17+incompatible // indirect
-       github.com/docker/distribution v2.8.1+incompatible // indirect
-       github.com/docker/docker v20.10.17+incompatible // indirect
-       github.com/docker/docker-credential-helpers v0.6.4 // indirect
-       github.com/docker/go-connections v0.4.0 // indirect
-       github.com/docker/go-metrics v0.0.1 // indirect
-       github.com/docker/go-units v0.4.0 // indirect
-       github.com/emicklei/go-restful/v3 v3.8.0 // indirect
-       github.com/evanphx/json-patch v5.6.0+incompatible // indirect
-       github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d // indirect
-       github.com/fatih/color v1.13.0 // indirect
-       github.com/go-errors/errors v1.0.1 // indirect
-       github.com/go-gorp/gorp/v3 v3.0.2 // indirect
-       github.com/go-logr/logr v1.2.3 // indirect
-       github.com/go-openapi/jsonpointer v0.19.6 // indirect
-       github.com/go-openapi/jsonreference v0.20.2 // indirect
-       github.com/go-openapi/swag v0.22.3 // indirect
-       github.com/gobwas/glob v0.2.3 // indirect
-       github.com/gogo/protobuf v1.3.2 // indirect
-       github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
-       github.com/golang/protobuf v1.5.2 // indirect
-       github.com/google/btree v1.0.1 // indirect
-       github.com/google/gnostic v0.5.7-v3refs // indirect
-       github.com/google/go-cmp v0.5.8 // indirect
-       github.com/google/gofuzz v1.2.0 // indirect
-       github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect
-       github.com/google/uuid v1.3.0
-       github.com/gorilla/mux v1.8.0 // indirect
-       github.com/gosuri/uitable v0.0.4 // indirect
-       github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect
-       github.com/huandu/xstrings v1.3.2 // indirect
-       github.com/imdario/mergo v0.3.12 // indirect
-       github.com/inconshreveable/mousetrap v1.0.0 // indirect
-       github.com/invopop/yaml v0.1.0 // indirect
-       github.com/jmoiron/sqlx v1.3.5 // indirect
-       github.com/josharian/intern v1.0.0 // indirect
-       github.com/json-iterator/go v1.1.12 // indirect
-       github.com/klauspost/compress v1.13.6 // indirect
-       github.com/labstack/gommon v0.4.0 // indirect
-       github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 // indirect
-       github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 // indirect
-       github.com/lib/pq v1.10.6 // indirect
-       github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de // indirect
-       github.com/mailru/easyjson v0.7.7 // indirect
-       github.com/mattn/go-colorable v0.1.13 // indirect
-       github.com/mattn/go-isatty v0.0.18 // indirect
-       github.com/mattn/go-runewidth v0.0.9 // indirect
-       github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
-       github.com/mitchellh/copystructure v1.2.0
-       github.com/mitchellh/go-wordwrap v1.0.0 // indirect
-       github.com/mitchellh/reflectwalk v1.0.2 // indirect
-       github.com/moby/locker v1.0.1 // indirect
-       github.com/moby/spdystream v0.2.0 // indirect
-       github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
-       github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
-       github.com/modern-go/reflect2 v1.0.2 // indirect
-       github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
-       github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
-       github.com/morikuni/aec v1.0.0 // indirect
-       github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
-       github.com/opencontainers/go-digest v1.0.0 // indirect
-       github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 // indirect
-       github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
-       github.com/pmezard/go-difflib v1.0.0 // indirect
-       github.com/prometheus/client_golang v1.12.1 // indirect
-       github.com/prometheus/client_model v0.2.0 // indirect
-       github.com/prometheus/common v0.32.1 // indirect
-       github.com/prometheus/procfs v0.7.3 // indirect
-       github.com/rubenv/sql-migrate v1.1.2 // indirect
-       github.com/russross/blackfriday v1.5.2 // indirect
-       github.com/shopspring/decimal v1.2.0 // indirect
-       github.com/spf13/cast v1.4.1 // indirect
-       github.com/spf13/cobra v1.5.0 // indirect
-       github.com/spf13/pflag v1.0.5 // indirect
-       github.com/stretchr/objx v0.5.0 // indirect
-       github.com/swaggo/echo-swagger v1.4.0
-       github.com/valyala/bytebufferpool v1.0.0 // indirect
-       github.com/valyala/fasttemplate v1.2.2 // indirect
-       github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
-       github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
-       github.com/xeipuuv/gojsonschema v1.2.0 // indirect
-       github.com/xlab/treeprint v1.1.0 // indirect
-       go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 // indirect
-       golang.org/x/crypto v0.8.0 // indirect
-       golang.org/x/net v0.9.0 // indirect
-       golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect
-       golang.org/x/sync v0.1.0 // indirect
-       golang.org/x/sys v0.7.0 // indirect
-       golang.org/x/term v0.7.0 // indirect
-       golang.org/x/text v0.9.0 // indirect
-       golang.org/x/time v0.3.0 // indirect
-       google.golang.org/appengine v1.6.7 // indirect
-       google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 // indirect
-       google.golang.org/grpc v1.47.0 // indirect
-       google.golang.org/protobuf v1.28.0 // indirect
-       gopkg.in/inf.v0 v0.9.1 // indirect
-       gopkg.in/yaml.v3 v3.0.1 // indirect
-       k8s.io/api v0.25.3-rc.0 // indirect
-       k8s.io/apiextensions-apiserver v0.25.2 // indirect
-       k8s.io/apimachinery v0.25.3-rc.0 // indirect
-       k8s.io/apiserver v0.25.2 // indirect
-       k8s.io/component-base v0.25.2 // indirect
-       k8s.io/klog/v2 v2.70.1 // indirect
-       k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect
-       k8s.io/kubectl v0.25.2 // indirect
-       k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed
-       oras.land/oras-go v1.1.1 // indirect
-       sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
-       sigs.k8s.io/kustomize/api v0.12.1 // indirect
-       sigs.k8s.io/kustomize/kyaml v0.13.9 // indirect
-       sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
-       sigs.k8s.io/yaml v1.3.0 // indirect
-)
diff --git a/r1-sme-manager/go.sum b/r1-sme-manager/go.sum
deleted file mode 100644 (file)
index c8d757d..0000000
+++ /dev/null
@@ -1,1116 +0,0 @@
-cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
-cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
-cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
-cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
-cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
-cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0=
-cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To=
-cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4=
-cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M=
-cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc=
-cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk=
-cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
-cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
-cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
-cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
-cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
-cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
-cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
-cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
-cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
-cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
-cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
-cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
-cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
-cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
-cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
-cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
-cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
-cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
-cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
-cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
-cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
-cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
-cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
-cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
-cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
-cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
-dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
-github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
-github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
-github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
-github.com/BurntSushi/toml v1.1.0 h1:ksErzDEI1khOiGPgpwuI7x2ebx/uXQNw7xJpn9Eq1+I=
-github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
-github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
-github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60=
-github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
-github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
-github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ=
-github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE=
-github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
-github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI=
-github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
-github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y=
-github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc=
-github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
-github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
-github.com/Masterminds/sprig/v3 v3.2.2 h1:17jRggJu518dr3QaafizSXOjKYp94wKfABxUmyxvxX8=
-github.com/Masterminds/sprig/v3 v3.2.2/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk=
-github.com/Masterminds/squirrel v1.5.3 h1:YPpoceAcxuzIljlr5iWpNKaql7hLeG1KLSrhvdHpkZc=
-github.com/Masterminds/squirrel v1.5.3/go.mod h1:NNaOrjSoIDfDA40n7sr2tPNZRfjzjA400rg+riTZj10=
-github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY=
-github.com/Microsoft/hcsshim v0.9.3 h1:k371PzBuRrz2b+ebGuI2nVgVhgsVX60jMfSw80NECxo=
-github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d h1:UrqY+r/OJnIp5u0s1SbQ8dVfLCZJsnvazdBP5hS4iRs=
-github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
-github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
-github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
-github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
-github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
-github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
-github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
-github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
-github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
-github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
-github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY=
-github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
-github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
-github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
-github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
-github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
-github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
-github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
-github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70=
-github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd h1:rFt+Y/IK1aEZkEHchZRSq9OQbsSzIT/OrI8YFFmRIng=
-github.com/bugsnag/osext v0.0.0-20130617224835-0dd3f918b21b h1:otBG+dV+YK+Soembjv71DPz3uX/V/6MMlSyD9JBQ6kQ=
-github.com/bugsnag/panicwrap v0.0.0-20151223152923-e2c28503fcd0 h1:nvj0OLI3YqYXer/kZD8Ri1aaunCxIEsOst1BVJswV0o=
-github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
-github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
-github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-github.com/chai2010/gettext-go v1.0.2 h1:1Lwwip6Q2QGsAdl/ZKPCwTe9fe0CjlUbqj5bFNSjIRk=
-github.com/chai2010/gettext-go v1.0.2/go.mod h1:y+wnP2cHYaVj19NZhYKAwEMH2CI1gNHeQQ+5AjwawxA=
-github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
-github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
-github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
-github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
-github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
-github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
-github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
-github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
-github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
-github.com/containerd/cgroups v1.0.3 h1:ADZftAkglvCiD44c77s5YmMqaP2pzVCFZvBmAlBdAP4=
-github.com/containerd/containerd v1.6.6 h1:xJNPhbrmz8xAMDNoVjHy9YHtWwEQNS+CDkcIRh7t8Y0=
-github.com/containerd/containerd v1.6.6/go.mod h1:ZoP1geJldzCVY3Tonoz7b1IXk8rIX0Nltt5QE4OMNk0=
-github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
-github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
-github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
-github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
-github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
-github.com/creack/pty v1.1.11 h1:07n33Z8lZxZ2qwegKbObQohDhXDQxiMMz1NOUGYlesw=
-github.com/creack/pty v1.1.11/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
-github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
-github.com/cyphar/filepath-securejoin v0.2.3 h1:YX6ebbZCZP7VkM3scTTokDgBL2TY741X51MTk3ycuNI=
-github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4=
-github.com/danieljoos/wincred v1.1.0/go.mod h1:XYlo+eRTsVA9aHGp7NGjFkPla4m+DCL7hqDjlFjiygg=
-github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
-github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
-github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
-github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE=
-github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
-github.com/deepmap/oapi-codegen v1.11.0 h1:f/X2NdIkaBKsSdpeuwLnY/vDI0AtPUrmB5LMgc7YD+A=
-github.com/deepmap/oapi-codegen v1.11.0/go.mod h1:k+ujhoQGxmQYBZBbxhOZNZf4j08qv5mC+OH+fFTnKxM=
-github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
-github.com/distribution/distribution/v3 v3.0.0-20211118083504-a29a3c99a684 h1:DBZ2sN7CK6dgvHVpQsQj4sRMCbWTmd17l+5SUCjnQSY=
-github.com/docker/cli v20.10.17+incompatible h1:eO2KS7ZFeov5UJeaDmIs1NFEDRf32PaqRpvoEkKBy5M=
-github.com/docker/cli v20.10.17+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
-github.com/docker/distribution v2.8.1+incompatible h1:Q50tZOPR6T/hjNsyc9g8/syEs6bk8XXApsHjKukMl68=
-github.com/docker/distribution v2.8.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
-github.com/docker/docker v20.10.17+incompatible h1:JYCuMrWaVNophQTOrMMoSwudOVEfcegoZZrleKc1xwE=
-github.com/docker/docker v20.10.17+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
-github.com/docker/docker-credential-helpers v0.6.4 h1:axCks+yV+2MR3/kZhAmy07yC56WZ2Pwu/fKWtKuZB0o=
-github.com/docker/docker-credential-helpers v0.6.4/go.mod h1:ofX3UI0Gz1TteYBjtgs07O36Pyasyp66D2uKT7H8W1c=
-github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ=
-github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec=
-github.com/docker/go-events v0.0.0-20190806004212-e31b211e4f1c h1:+pKlWGMw7gf6bQ+oDZB4KHQFypsfjYlq/C4rfL7D3g8=
-github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8=
-github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw=
-github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw=
-github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
-github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1 h1:ZClxb8laGDf5arXfYcAtECDFgAgHklGI8CxgjHnXKJ4=
-github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
-github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153 h1:yUdfgN0XgIJw7foRItutHYUIhlcKzcSf5vDpdhQAKTc=
-github.com/emicklei/go-restful/v3 v3.8.0 h1:eCZ8ulSerjdAiaNpF7GxXIE7ZCMo1moN1qX+S609eVw=
-github.com/emicklei/go-restful/v3 v3.8.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
-github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
-github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
-github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
-github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po=
-github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
-github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
-github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
-github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
-github.com/evanphx/json-patch v5.6.0+incompatible h1:jBYDEEiFBPxA0v50tFdvOzQQTCvpL6mnFh5mB2/l16U=
-github.com/evanphx/json-patch v5.6.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
-github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d h1:105gxyaGwCFad8crR9dcMQWvV9Hvulu6hwUh4tWPJnM=
-github.com/exponent-io/jsonpath v0.0.0-20151013193312-d6023ce2651d/go.mod h1:ZZMPRZwes7CROmyNKgQzC3XPs6L/G2EJLHddWejkmf4=
-github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
-github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
-github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
-github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
-github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
-github.com/getkin/kin-openapi v0.94.0/go.mod h1:LWZfzOd7PRy8GJ1dJ6mCU6tNdSfOwRac1BUPam4aw6Q=
-github.com/getkin/kin-openapi v0.106.0 h1:hrqfqJPAvWvuO/V0lCr/xyQOq4Gy21mcr28JJOSRcEI=
-github.com/getkin/kin-openapi v0.106.0/go.mod h1:9Dhr+FasATJZjS4iOLvB0hkaxgYdulrNYm2e9epLWOo=
-github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
-github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
-github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
-github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
-github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6w=
-github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
-github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
-github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
-github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
-github.com/go-gorp/gorp/v3 v3.0.2 h1:ULqJXIekoqMx29FI5ekXXFoH1dT2Vc8UhnRzBg+Emz4=
-github.com/go-gorp/gorp/v3 v3.0.2/go.mod h1:BJ3q1ejpV8cVALtcXvXaXyTOlMmJhWDxTmncaR6rwBY=
-github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
-github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
-github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
-github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
-github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
-github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
-github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
-github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
-github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
-github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
-github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
-github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
-github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
-github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo=
-github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE=
-github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k=
-github.com/go-openapi/spec v0.20.8 h1:ubHmXNY3FCIOinT8RNrrPfGc9t7I1qhPtdOGoG2AxRU=
-github.com/go-openapi/spec v0.20.8/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA=
-github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
-github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
-github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
-github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
-github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
-github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
-github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
-github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
-github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
-github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
-github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
-github.com/go-playground/validator/v10 v10.11.0/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
-github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
-github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
-github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
-github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
-github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
-github.com/gobuffalo/logger v1.0.6 h1:nnZNpxYo0zx+Aj9RfMPBm+x9zAU2OayFh/xrAWi34HU=
-github.com/gobuffalo/logger v1.0.6/go.mod h1:J31TBEHR1QLV2683OXTAItYIg8pv2JMHnF/quuAbMjs=
-github.com/gobuffalo/packd v1.0.1 h1:U2wXfRr4E9DH8IdsDLlRFwTZTK7hLfq9qT/QHXGVe/0=
-github.com/gobuffalo/packd v1.0.1/go.mod h1:PP2POP3p3RXGz7Jh6eYEf93S7vA2za6xM7QT85L4+VY=
-github.com/gobuffalo/packr/v2 v2.8.3 h1:xE1yzvnO56cUC0sTpKR3DIbxZgB54AftTFMhB2XEWlY=
-github.com/gobuffalo/packr/v2 v2.8.3/go.mod h1:0SahksCVcx4IMnigTjiFuyldmTrdTctXsOdiU5KwbKc=
-github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y=
-github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
-github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
-github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
-github.com/godror/godror v0.24.2/go.mod h1:wZv/9vPiUib6tkoDl+AZ/QLf5YZgMravZ7jxH2eQWAE=
-github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
-github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
-github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
-github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
-github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
-github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
-github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
-github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
-github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
-github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
-github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
-github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
-github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
-github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
-github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
-github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
-github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
-github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
-github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
-github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
-github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
-github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
-github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
-github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
-github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
-github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
-github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
-github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
-github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
-github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
-github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
-github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
-github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k=
-github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
-github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
-github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4=
-github.com/google/btree v1.0.1/go.mod h1:xXMiIv4Fb/0kKde4SpL7qlzvu5cMJDRkFDxJfI9uaxA=
-github.com/google/gnostic v0.5.7-v3refs h1:FhTMOKj2VhjpouxvWJAV1TL304uMlb9zcDqkl6cEI54=
-github.com/google/gnostic v0.5.7-v3refs/go.mod h1:73MKFl6jIHelAJNaBGFzt3SPtZULs9dYrGFt8OiIsHQ=
-github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
-github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
-github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
-github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
-github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
-github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
-github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
-github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
-github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
-github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
-github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
-github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
-github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
-github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
-github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
-github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
-github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
-github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
-github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
-github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
-github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4=
-github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
-github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
-github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
-github.com/gosuri/uitable v0.0.4 h1:IG2xLKRvErL3uhY6e1BylFzG+aJiwQviDDTfOKeKTpY=
-github.com/gosuri/uitable v0.0.4/go.mod h1:tKR86bXuXPZazfOTG1FIzvjIdXzd0mo4Vtn16vt0PJo=
-github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWetyv/0+wjACpqVH+eVULgEjkurDLq3goeM=
-github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
-github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
-github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
-github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
-github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
-github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
-github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
-github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
-github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
-github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
-github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
-github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
-github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
-github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
-github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
-github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
-github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
-github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
-github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
-github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
-github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
-github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
-github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
-github.com/huandu/xstrings v1.3.2 h1:L18LIDzqlW6xN2rEkpdV8+oL/IXWJ1APd+vsdYy4Wdw=
-github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
-github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
-github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
-github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
-github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU=
-github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA=
-github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
-github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
-github.com/invopop/yaml v0.1.0 h1:YW3WGUoJEXYfzWBjn00zIlrw7brGVD0fUKRYDPAPhrc=
-github.com/invopop/yaml v0.1.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
-github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
-github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
-github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
-github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
-github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
-github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
-github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
-github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
-github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
-github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
-github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
-github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
-github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
-github.com/karrick/godirwalk v1.16.1 h1:DynhcF+bztK8gooS0+NDJFrdNZjJ3gzVzC545UNA9iw=
-github.com/karrick/godirwalk v1.16.1/go.mod h1:j4mkqPuvaLI8mp1DroR3P6ad7cyYd4c1qeJ3RV7ULlk=
-github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
-github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
-github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
-github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
-github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
-github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
-github.com/kortschak/utter v1.0.1/go.mod h1:vSmSjbyrlKjjsL71193LmzBOKgwePk9DH6uFaWHIInc=
-github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
-github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
-github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
-github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
-github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
-github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
-github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
-github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
-github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
-github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
-github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
-github.com/labstack/echo/v4 v4.7.2/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks=
-github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M=
-github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k=
-github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
-github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
-github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
-github.com/lann/builder v0.0.0-20180802200727-47ae307949d0 h1:SOEGU9fKiNWd/HOJuq6+3iTQz8KNCLtVX6idSoTLdUw=
-github.com/lann/builder v0.0.0-20180802200727-47ae307949d0/go.mod h1:dXGbAdH5GtBTC4WfIxhKZfyBF/HBFgRZSWwZ9g/He9o=
-github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0 h1:P6pPBnrTSX3DEVR4fDembhRWSsG5rVo6hYhAB/ADZrk=
-github.com/lann/ps v0.0.0-20150810152359-62de8c46ede0/go.mod h1:vmVJ0l/dxyfGW6FmdpVm2joNMFikkuWg0EoCKLGUMNw=
-github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
-github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
-github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y=
-github.com/lestrrat-go/blackmagic v1.0.0/go.mod h1:TNgH//0vYSs8VXDCfkZLgIrVTTXQELZffUV0tz3MtdQ=
-github.com/lestrrat-go/blackmagic v1.0.1/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
-github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
-github.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc=
-github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
-github.com/lestrrat-go/jwx v1.2.24/go.mod h1:zoNuZymNl5lgdcu6P7K6ie2QRll5HVfF4xwxBBK1NxY=
-github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
-github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
-github.com/lib/pq v1.10.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
-github.com/lib/pq v1.10.6 h1:jbk+ZieJ0D7EVGJYpL9QTz7/YW6UHbmdnZWYyK5cdBs=
-github.com/lib/pq v1.10.6/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
-github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0=
-github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de/go.mod h1:zAbeS9B/r2mtpb6U+EI2rYA5OAXxsYw6wTamcNW+zcE=
-github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
-github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
-github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
-github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
-github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
-github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
-github.com/markbates/errx v1.1.0 h1:QDFeR+UP95dO12JgW+tgi2UVfo0V8YBHiUIOaeBPiEI=
-github.com/markbates/errx v1.1.0/go.mod h1:PLa46Oex9KNbVDZhKel8v1OT7hD5JZ2eI7AHhA0wswc=
-github.com/markbates/oncer v1.0.0 h1:E83IaVAHygyndzPimgUYJjbshhDTALZyXxvk9FOlQRY=
-github.com/markbates/oncer v1.0.0/go.mod h1:Z59JA581E9GP6w96jai+TGqafHPW+cPfRxz2aSZ0mcI=
-github.com/markbates/safe v1.0.1 h1:yjZkbvRM6IzKj9tlu/zMJLS0n/V351OZWRnF3QfaUxI=
-github.com/markbates/safe v1.0.1/go.mod h1:nAqgmRi7cY2nqMc92/bSEeQA+R4OheNU2T1kNSCBdG0=
-github.com/matryer/moq v0.2.7/go.mod h1:kITsx543GOENm48TUAQyJ9+SAvFSr7iGQXPoth/VUBk=
-github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
-github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
-github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
-github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
-github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
-github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
-github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
-github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
-github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
-github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
-github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
-github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
-github.com/mattn/go-oci8 v0.1.1/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI=
-github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
-github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
-github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
-github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
-github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
-github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
-github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI=
-github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
-github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
-github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
-github.com/mitchellh/cli v1.1.2/go.mod h1:6iaV0fGdElS6dPBx0EApTxHrcWvmJphyh2n8YBLPPZ4=
-github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
-github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw=
-github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s=
-github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
-github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
-github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
-github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
-github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
-github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
-github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
-github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
-github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
-github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
-github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ=
-github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
-github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
-github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
-github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8=
-github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c=
-github.com/moby/sys/mountinfo v0.5.0 h1:2Ks8/r6lopsxWi9m58nlwjaeSzUX9iiL1vj5qB/9ObI=
-github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 h1:dcztxKSvZ4Id8iPpHERQBbIJfabdt4wUm5qy3wOL2Zc=
-github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6/go.mod h1:E2VnQOmVuvZB6UYnnDB0qG5Nq/1tD9acaOpo6xmt0Kw=
-github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
-github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
-github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
-github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
-github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
-github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
-github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
-github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
-github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
-github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 h1:n6/2gBQ3RWajuToeY6ZtZTIKv2v7ThUy5KKusIT0yc0=
-github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00/go.mod h1:Pm3mSP3c5uWn86xMLZ5Sa7JB9GsEZySvHYXCTK4E9q4=
-github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
-github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
-github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
-github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
-github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
-github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
-github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
-github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
-github.com/onsi/ginkgo v1.16.4 h1:29JGrr5oVBm5ulCWet69zQkzWipVXIol6ygQUe/EzNc=
-github.com/onsi/ginkgo/v2 v2.1.6 h1:Fx2POJZfKRQcM1pH49qSZiYeu319wji004qX+GDovrU=
-github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
-github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
-github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
-github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799 h1:rc3tiVYb5z54aKaDfakKn0dDjIyPpTtszkjuMzyt7ec=
-github.com/opencontainers/image-spec v1.0.3-0.20211202183452-c5a74bcca799/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
-github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
-github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
-github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
-github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
-github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc=
-github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
-github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
-github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
-github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
-github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
-github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
-github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
-github.com/poy/onpar v0.0.0-20190519213022-ee068f8ea4d1 h1:oL4IBbcqwhhNWh31bjOX8C/OCy0zs9906d/VUru+bqg=
-github.com/poy/onpar v0.0.0-20190519213022-ee068f8ea4d1/go.mod h1:nSbFQvMj97ZyhFRSJYtut+msi4sOY6zJDGCdSc+/rZU=
-github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
-github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
-github.com/prometheus/client_golang v1.1.0/go.mod h1:I1FGZT9+L76gKKOs5djB6ezCbFQP1xR9D75/vuwEF3g=
-github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
-github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
-github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk=
-github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
-github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
-github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M=
-github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
-github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
-github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
-github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
-github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
-github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4=
-github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
-github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
-github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
-github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
-github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
-github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
-github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU=
-github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
-github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
-github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
-github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
-github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
-github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
-github.com/rubenv/sql-migrate v1.1.2 h1:9M6oj4e//owVVHYrFISmY9LBRw6gzkCNmD9MV36tZeQ=
-github.com/rubenv/sql-migrate v1.1.2/go.mod h1:/7TZymwxN8VWumcIxw1jjHEcR1djpdkMHQPT4FWdnbQ=
-github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
-github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
-github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
-github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
-github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
-github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
-github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ=
-github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
-github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
-github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
-github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
-github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
-github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
-github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
-github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
-github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
-github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
-github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
-github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
-github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
-github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
-github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
-github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
-github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
-github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
-github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
-github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
-github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
-github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
-github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
-github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
-github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
-github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
-github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
-github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
-github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
-github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
-github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
-github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
-github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
-github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
-github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
-github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
-github.com/swaggo/echo-swagger v1.4.0 h1:RCxLKySw1SceHLqnmc41pKyiIeE+OiD7NSI7FUOBlLo=
-github.com/swaggo/echo-swagger v1.4.0/go.mod h1:Wh3VlwjZGZf/LH0s81tz916JokuPG7y/ZqaqnckYqoQ=
-github.com/swaggo/files/v2 v2.0.0 h1:hmAt8Dkynw7Ssz46F6pn8ok6YmGZqHSVLZ+HQM7i0kw=
-github.com/swaggo/files/v2 v2.0.0/go.mod h1:24kk2Y9NYEJ5lHuCra6iVwkMjIekMCaFq/0JQj66kyM=
-github.com/swaggo/swag v1.8.12 h1:pctzkNPu0AlQP2royqX3apjKCQonAnf7KGoxeO4y64w=
-github.com/swaggo/swag v1.8.12/go.mod h1:lNfm6Gg+oAq3zRJQNEMBE66LIJKM44mxFqhEEgy2its=
-github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
-github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
-github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
-github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
-github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
-github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
-github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
-github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
-github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
-github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f h1:J9EGpcZtP0E/raorCMxlFGSTBrsSlaDGf3jU/qvAE2c=
-github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
-github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0=
-github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
-github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74=
-github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y=
-github.com/xlab/treeprint v1.1.0 h1:G/1DjNkPpfZCFt9CSh6b5/nY4VimlbHF3Rh4obvtzDk=
-github.com/xlab/treeprint v1.1.0/go.mod h1:gj5Gd3gPdKtR1ikdDK6fnFLdmIS0X30kTTuNd/WEJu0=
-github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
-github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-github.com/yuin/goldmark v1.4.0/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
-github.com/yvasiyarov/go-metrics v0.0.0-20140926110328-57bccd1ccd43 h1:+lm10QQTNSBd8DVTNGHx7o/IKu9HYDvLMffDhbyLccI=
-github.com/yvasiyarov/gorelic v0.0.0-20141212073537-a9bba5b9ab50 h1:hlE8//ciYMztlGpl/VA+Zm1AcTPHYkHJPbHqE6WJUXE=
-github.com/yvasiyarov/newrelic_platform_go v0.0.0-20140908184405-b21fdbd4370f h1:ERexzlUfuTvpE74urLSbIQW0Z/6hF9t8U4NsJLaioAY=
-github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=
-github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
-go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
-go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
-go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
-go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
-go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
-go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
-go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
-go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
-go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
-go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
-go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
-go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
-go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5 h1:+FNtrFTmVw0YZGpBGX56XDee331t6JAXeK2bcyhLOOc=
-go.starlark.net v0.0.0-20200306205701-8dd3e2ee1dd5/go.mod h1:nmDLcffg48OtT/PSW0Hg7FvpRQsQh5OSqIylirxKC7o=
-go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
-go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
-go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
-golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
-golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
-golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
-golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.0.0-20220513210258-46612604a0f9/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
-golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
-golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
-golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
-golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
-golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
-golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
-golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
-golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
-golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
-golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
-golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
-golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
-golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
-golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
-golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
-golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
-golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
-golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
-golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
-golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
-golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
-golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
-golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
-golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
-golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
-golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
-golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
-golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
-golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
-golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
-golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
-golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
-golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
-golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
-golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
-golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
-golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20220513224357-95641704303c/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
-golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
-golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
-golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg=
-golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
-golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20190801041406-cbf593c0f2f3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191002063906-3421d5a6bb1c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
-golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
-golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ=
-golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
-golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
-golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
-golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20220411224347-583f2d630306/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
-golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
-golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
-golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
-golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
-golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
-golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
-golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
-golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
-golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
-golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
-golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
-golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
-golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
-golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
-golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
-golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
-golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
-golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
-golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y=
-golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4=
-golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
-google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
-google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
-google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
-google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
-google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
-google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
-google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
-google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
-google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
-google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
-google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
-google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
-google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
-google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
-google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
-google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
-google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8=
-google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
-google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
-google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
-google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
-google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
-google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
-google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
-google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
-google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
-google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
-google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
-google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
-google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
-google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
-google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
-google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
-google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
-google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201019141844-1ed22bb0c154/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
-google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
-google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21 h1:hrbNEivu7Zn1pxvHk6MBrq9iE22woVILTHqexqBxe6I=
-google.golang.org/genproto v0.0.0-20220502173005-c8bf987b8c21/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4=
-google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
-google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
-google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
-google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
-google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
-google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
-google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
-google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
-google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
-google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
-google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
-google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
-google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
-google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
-google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
-google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
-google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
-google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
-google.golang.org/grpc v1.46.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
-google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8=
-google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
-google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
-google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
-google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
-google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
-google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
-google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
-google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
-google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
-google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
-google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
-google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
-google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
-gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
-gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
-gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
-gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
-gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
-gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
-gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
-gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
-gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
-gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
-gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
-gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
-gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk=
-gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0=
-helm.sh/helm/v3 v3.9.0 h1:qDSWViuF6SzZX5s5AB/NVRGWmdao7T5j4S4ebIkMGag=
-helm.sh/helm/v3 v3.9.0/go.mod h1:fzZfyslcPAWwSdkXrXlpKexFeE2Dei8N27FFQWt+PN0=
-honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
-honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
-honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
-k8s.io/api v0.25.3-rc.0 h1:abmQ96RwK/xVgFrDxIkxdCoQ4qr7Uh+sPfjIpecpJIg=
-k8s.io/api v0.25.3-rc.0/go.mod h1:KTkuGVHV7vKlkf1FHDtbF687n22h3pQ6ovWs/Eobm78=
-k8s.io/apiextensions-apiserver v0.25.2 h1:8uOQX17RE7XL02ngtnh3TgifY7EhekpK+/piwzQNnBo=
-k8s.io/apiextensions-apiserver v0.25.2/go.mod h1:iRwwRDlWPfaHhuBfQ0WMa5skdQfrE18QXJaJvIDLvE8=
-k8s.io/apimachinery v0.25.3-rc.0 h1:nhztVhLsZuw2xENfIrVXcsNUiemnlH/r+Bb8hbl/1gA=
-k8s.io/apimachinery v0.25.3-rc.0/go.mod h1:hqqA1X0bsgsxI6dXsJ4HnNTBOmJNxyPp8dw3u2fSHwA=
-k8s.io/apiserver v0.25.2 h1:YePimobk187IMIdnmsMxsfIbC5p4eX3WSOrS9x6FEYw=
-k8s.io/apiserver v0.25.2/go.mod h1:30r7xyQTREWCkG2uSjgjhQcKVvAAlqoD+YyrqR6Cn+I=
-k8s.io/cli-runtime v0.25.3-rc.0 h1:hTBm1tPNY4uXfpbeOZjT18AlzaEIN0CgfB6rz1XLuKA=
-k8s.io/cli-runtime v0.25.3-rc.0/go.mod h1:o3qnMjKIbAT8hrc5gByX+Pi3As4bqVxDtr6bkysAhWw=
-k8s.io/client-go v0.25.3-rc.0 h1:RDSXTIbzXU8jB1dElqSiF1nyMhiZgEzqVeGA874Hkm4=
-k8s.io/client-go v0.25.3-rc.0/go.mod h1:qkx9IzH1FM7r01F4vWZEYHXTPZadHtJpmzZQZyrrWdM=
-k8s.io/component-base v0.25.2 h1:Nve/ZyHLUBHz1rqwkjXm/Re6IniNa5k7KgzxZpTfSQY=
-k8s.io/component-base v0.25.2/go.mod h1:90W21YMr+Yjg7MX+DohmZLzjsBtaxQDDwaX4YxDkl60=
-k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
-k8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ=
-k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
-k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 h1:MQ8BAZPZlWk3S9K4a9NCkIFQtZShWqoha7snGixVgEA=
-k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1/go.mod h1:C/N6wCaBHeBHkHUesQOQy2/MZqGgMAFPqGsGQLdbZBU=
-k8s.io/kubectl v0.25.2 h1:2993lTeVimxKSWx/7z2PiJxUILygRa3tmC4QhFaeioA=
-k8s.io/kubectl v0.25.2/go.mod h1:eoBGJtKUj7x38KXelz+dqVtbtbKwCqyKzJWmBHU0prg=
-k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/lQhTmy+Hr/Cpue4=
-k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
-oras.land/oras-go v1.1.1 h1:gI00ftziRivKXaw1BdMeEoIA4uBgga33iVlOsEwefFs=
-oras.land/oras-go v1.1.1/go.mod h1:n2TE1ummt9MUyprGhT+Q7kGZUF4kVUpYysPFxeV2IpQ=
-rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
-rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
-rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
-sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k=
-sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
-sigs.k8s.io/kustomize/api v0.12.1 h1:7YM7gW3kYBwtKvoY216ZzY+8hM+lV53LUayghNRJ0vM=
-sigs.k8s.io/kustomize/api v0.12.1/go.mod h1:y3JUhimkZkR6sbLNwfJHxvo1TCLwuwm14sCYnkH6S1s=
-sigs.k8s.io/kustomize/kyaml v0.13.9 h1:Qz53EAaFFANyNgyOEJbT/yoIHygK40/ZcvU3rgry2Tk=
-sigs.k8s.io/kustomize/kyaml v0.13.9/go.mod h1:QsRbD0/KcU+wdk0/L0fIp2KLnohkVzs6fQ85/nOXac4=
-sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
-sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
-sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
-sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
diff --git a/servicemanager/.env.example b/servicemanager/.env.example
new file mode 100644 (file)
index 0000000..5f7bfe1
--- /dev/null
@@ -0,0 +1,12 @@
+KONG_DOMAIN=<string>
+KONG_PROTOCOL=<http or https protocol scheme>
+KONG_IPV4=<host string>
+KONG_DATA_PLANE_PORT=<port number>
+KONG_CONTROL_PLANE_PORT=<port number>
+CAPIF_PROTOCOL=<http or https protocol scheme>
+CAPIF_IPV4=<host>
+CAPIF_PORT=<port number>
+LOG_LEVEL=<Trace, Debug, Info, Warning, Error, Fatal or Panic>
+SERVICE_MANAGER_PORT=<port number>
+TEST_SERVICE_IPV4=<host string>
+TEST_SERVICE_PORT=<port number>
\ No newline at end of file
diff --git a/servicemanager/Dockerfile b/servicemanager/Dockerfile
new file mode 100644 (file)
index 0000000..ddb23ed
--- /dev/null
@@ -0,0 +1,45 @@
+#==================================================================================
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+#==================================================================================
+
+##
+## Build
+##
+FROM nexus3.o-ran-sc.org:10001/golang:1.19.2-bullseye AS build
+
+WORKDIR /app
+
+COPY go.mod .
+COPY go.sum .
+RUN go mod download
+
+COPY . .
+RUN go build -o /servicemanager
+
+##
+## Deploy
+##
+
+FROM ubuntu:22.04
+
+# We use the /app directory as this is where our servicemanager expects to find its .env file.
+RUN mkdir -p /app
+WORKDIR /app
+
+## Copy from "build" stage
+COPY --from=build /servicemanager .
+
+ENTRYPOINT ["/app/servicemanager"]
diff --git a/servicemanager/README.md b/servicemanager/README.md
new file mode 100644 (file)
index 0000000..a43d9de
--- /dev/null
@@ -0,0 +1,130 @@
+<!--
+-
+========================LICENSE_START=================================
+O-RAN-SC
+%%
+Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved.
+%%
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+     http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+========================LICENSE_END===================================
+
+-->
+
+# O-RAN-SC Non-RealTime RIC Service Management and Exposure
+
+This product is a Go implementation of a service that calls the CAPIF Core function. When publishing a service we create a Kong route and Kong service, https://konghq.com/. The InterfaceDescription that we return is updated to point to the Kong Data Plane. Therefore, the API interface that we return from Service Discovery has the Kong host and port, and not the original service's host and port. This allows the rApp's API call to be re-directed through Kong.
+
+## O-RAN-SC Non-RealTime RIC CAPIF Core Implementation
+
+This product is a Go implementation of the CAPIF Core function, which is based on the 3GPP "29.222 Common API Framework for 3GPP Northbound APIs (CAPIF)" interfaces, see https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=3450.
+
+See [CAPIF Core](../capifcore/README.md)
+
+## Generation of API Code
+
+The CAPIF APIs are generated from the OpenAPI specifications provided by 3GPP. The `generate.sh` script downloads the
+specifications from 3GPP, fixes them and then generates the APIs. While these files are checked into the repo, they can be re-generated using `generate.sh`.
+
+```sh
+./generate.sh
+```
+
+The specifications are downloaded from the following site; https://www.3gpp.org/ftp/Specs/archive/29_series. To see
+the APIs in swagger format, see the following link; https://github.com/jdegre/5GC_APIs/tree/Rel-16#common-api-framework-capif.
+**NOTE!** The documentation in this link is for release 16 of CAPIF, the downloaded specifications are for release 17.
+
+To fix the specifications there are three tools.
+- `commoncollector`, collects type definitions from peripheral specifications to keep down the number of dependencies to
+  other specifications. The types to collect are listed in the `definitions.txt`file. Some fixes are hard coded.
+- `enumfixer`, fixes enumeration definitions so they can be properly generated.
+- `specificationfixer`, fixes flaws in the specifications so they can be properly generated. All fixes are hard coded.
+
+## Set Up
+
+First, we need to run `generate.sh` as described above to generate our API code from the 3GPP spec.
+
+Before we can test or run R1-SME-Manager, we need to configure a .env file with the required parameters. Please see the template .env.example in the servicemanager directory.
+
+You can set the environmental variable SERVICE_MANAGER_ENV to specify the .env file. For example, the following command specifies to use the config file
+.env.development. If this flag is not set, first we try .env.development and then .env.
+
+```sh
+export SERVICE_MANAGER_ENV=development
+```
+
+### Capifcore and Kong
+
+We also need Kong and Capifcore to be running. Please see the examples in the `configs` folder.
+
+## Build
+
+After generating the API code, we can build the application with the following command.
+
+```sh
+go build
+```
+
+## Unit Tests
+
+To run the unit tests for the application, first ensure that the .env file is configured. In the following example, we specify `.env.test`. For now, we need to disable parallelism in the unit tests with -p=1.
+
+```sh
+export SERVICE_MANAGER_ENV=test
+go test -p=1 -count=1 ./...
+```
+
+## Run Locally
+
+To run as a local app, first ensure that the .env file is configured. In the following example, we specify `.env.development`.
+
+```sh
+export SERVICE_MANAGER_ENV=development
+./servicemanager
+```
+
+R1-SME-Manager is then available on the port configured in .env.
+
+## Building the Docker Image
+
+The application can also be built as a Docker image, by using the following command. We build the image without a .env file. This is supplied by volume mounting at container run-time.
+
+```sh
+docker image build . -t servicemanager
+```
+
+## Stand-alone Deployment on Kubernetes
+
+For a stand-alone deployment, please see the `deploy` folder for configurations to deploy to R1-SME-Manager to Kubernetes. We need the following steps.
+ - Deploy a PV for Kong's Postgres database (depends on your Kubernetes cluster)
+ - Deploy a PVC for Kong's Postgres database
+ - Deploy Kong with Postgres
+ - Deploy Capifcore
+ - Deploy R1-SME-Manager
+
+We consolidate the above steps into the script `deploy-to-k8s.sh`. To delete the full deployment, you can use `delete-from-k8s.sh`. The deploy folder has the following structure.
+
+- sme/
+  - servicemanager/
+    - deploy/
+      - src/
+      - manifests/
+
+We store the Kubernetes manifests files in the manifests in the subfolder. We store the shell scripts in the src folder. 
+
+In `deploy-to-k8s.sh`, we copy .env.example and use sed to replace the template values with values for testing/production. You will need to update this part of the script with your own values. There is an example sed replacement in function `substitute_manifest()` in `deploy-to-k8s.sh`. Here, you can substitute your own Docker images for Capifcore and Service Manager for local development.
+
+In addition there are 2 switches that are added for developer convenience.
+ * --repo # allow you to specify your own docker repo
+ * --env  # allow you to specify an additional env file, and set SERVICE_MANAGER_ENV to point to this file.
+
+`./deploy-to-k8s.sh --repo your-docker-repo-id --env ../../.env.minikube`
diff --git a/servicemanager/build-servicemanager-ubuntu.sh b/servicemanager/build-servicemanager-ubuntu.sh
new file mode 100755 (executable)
index 0000000..404e7a2
--- /dev/null
@@ -0,0 +1,36 @@
+#!/bin/bash
+##############################################################################
+#
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+##############################################################################
+set -eux
+
+echo "--> build-servicemanager-ubuntu.sh"
+
+# go installs tools like go-acc to $HOME/go/bin
+# ubuntu minion path lacks go
+export PATH=$PATH:/usr/local/go/bin:$HOME/go/bin
+export GO111MODULE=on
+go version
+
+# Get the go coverage tool helper
+go install github.com/ory/go-acc
+go get github.com/stretchr/testify/mock@v1.7.1
+go-acc ./... --ignore gentools,mocks,common,discoverserviceapi,invokermanagementapi,publishserviceapi,providermanagementapi
+
+sed -i 's/oransc\.org\/nonrtric\/servicemanager/servicemanager/' coverage.txt
+
+echo "--> build-servicemanager-ubuntu.sh ends"
diff --git a/servicemanager/container-tag.yaml b/servicemanager/container-tag.yaml
new file mode 100644 (file)
index 0000000..2480abf
--- /dev/null
@@ -0,0 +1,22 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#  ============LICENSE_END=================================================
+#
+
+# The Jenkins job requires a tag to build the Docker image.
+# By default this file is in the docker build directory,
+# but the location can configured in the JJB template.
+---
+tag: 0.1.0
diff --git a/servicemanager/deploy/manifests/capifcore.yaml b/servicemanager/deploy/manifests/capifcore.yaml
new file mode 100644 (file)
index 0000000..7efc107
--- /dev/null
@@ -0,0 +1,65 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#  ============LICENSE_END=================================================
+#
+
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: capifcore
+  namespace: servicemanager
+  labels:
+    app: capifcore
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: capifcore
+  template:
+    metadata:
+      labels:
+        app: capifcore
+        version: v1
+    spec:
+      containers:
+      - name: capifcore
+        image: o-ran-sc.org/nonrtric/plt/capifcore
+        imagePullPolicy: IfNotPresent
+        ports:
+        - containerPort: 8090
+        resources:
+          limits:
+            memory: 256Mi
+            cpu: "250m"
+          requests:
+            memory: 128Mi
+            cpu: "80m"
+
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: capifcore
+  namespace: servicemanager
+spec:
+  selector:
+    app: capifcore
+  ports:
+    - protocol: TCP
+      port: 80
+      targetPort: 8090
+      nodePort: 31570
+  type: NodePort
diff --git a/servicemanager/deploy/manifests/kong-postgres-pv.yaml b/servicemanager/deploy/manifests/kong-postgres-pv.yaml
new file mode 100644 (file)
index 0000000..4bdf2a9
--- /dev/null
@@ -0,0 +1,31 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#  ============LICENSE_END=================================================
+#
+
+apiVersion: v1
+kind: PersistentVolume
+metadata:
+  name: kong-postgresql-pv
+  labels:
+    type: local
+spec:
+  capacity:
+    storage: 2Gi
+  accessModes:
+    - ReadWriteOnce
+  hostPath:
+    path: /tmp/kong-postgresql-pv
+  persistentVolumeReclaimPolicy: Delete
\ No newline at end of file
diff --git a/servicemanager/deploy/manifests/kong-postgres-pvc.yaml b/servicemanager/deploy/manifests/kong-postgres-pvc.yaml
new file mode 100644 (file)
index 0000000..dd8e818
--- /dev/null
@@ -0,0 +1,28 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#  ============LICENSE_END=================================================
+#
+
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+  name: kong-postgresql-pvc
+  namespace: kong
+spec:
+  accessModes:
+    - ReadWriteOnce
+  resources:
+    requests:
+      storage: 2Gi
\ No newline at end of file
diff --git a/servicemanager/deploy/manifests/servicemanager.yaml b/servicemanager/deploy/manifests/servicemanager.yaml
new file mode 100644 (file)
index 0000000..3f937ff
--- /dev/null
@@ -0,0 +1,75 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#  ============LICENSE_END=================================================
+#
+
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: servicemanager
+  namespace: servicemanager
+  labels:
+    app: servicemanager
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app: servicemanager
+  template:
+    metadata:
+      labels:
+        app: servicemanager
+        version: v1
+    spec:
+      containers:
+      - name: servicemanager
+        image: o-ran-sc.org/nonrtric/plt/servicemanager
+        imagePullPolicy: IfNotPresent
+        env:
+            - name: SERVICE_MANAGER_ENV
+              value: ""
+        ports:
+        - containerPort: 8095
+        resources:
+          limits:
+            memory: 256Mi
+            cpu: "250m"
+          requests:
+            memory: 128Mi
+            cpu: "80m"
+        volumeMounts:
+        - name: config-volume
+          mountPath: /app/.env
+          subPath: .env
+      volumes:
+      - name: config-volume
+        configMap:
+          name: env-configmap
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: servicemanager
+  namespace: servicemanager
+spec:
+  selector:
+    app: servicemanager
+  ports:
+    - protocol: TCP
+      port: 80
+      targetPort: 8095
+      nodePort: 31575
+  type: NodePort
diff --git a/servicemanager/deploy/manifests/values.yaml b/servicemanager/deploy/manifests/values.yaml
new file mode 100644 (file)
index 0000000..e33c8c0
--- /dev/null
@@ -0,0 +1,509 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#  ============LICENSE_END=================================================
+#
+
+
+
+# Default values for Kong's Helm Chart.
+#
+# Sections:
+# - Deployment parameters
+# - Kong parameters
+# - Ingress Controller parameters
+# - Postgres sub-chart parameters
+# - Miscellaneous parameters
+# - Kong Enterprise parameters
+
+# For a detailed example of values.yaml, please see https://github.com/Kong/charts/blob/main/charts/kong/values.yaml
+
+# -----------------------------------------------------------------------------
+# Deployment parameters
+# -----------------------------------------------------------------------------
+
+deployment:
+  kong:
+    enabled: true
+  serviceAccount:
+    create: true
+    automountServiceAccountToken: false
+
+  test:
+    enabled: false
+  daemonset: false
+  hostNetwork: false
+  hostname: ""
+  prefixDir:
+    sizeLimit: 256Mi
+  tmpDir:
+    sizeLimit: 1Gi
+
+# -----------------------------------------------------------------------------
+# Kong parameters
+# -----------------------------------------------------------------------------
+
+env:
+  database: "postgres"
+  router_flavor: "traditional"
+  nginx_worker_processes: "2"
+  proxy_access_log: /dev/stdout
+  admin_access_log: /dev/stdout
+  admin_gui_access_log: /dev/stdout
+  portal_api_access_log: /dev/stdout
+  proxy_error_log: /dev/stderr
+  admin_error_log: /dev/stderr
+  admin_gui_error_log: /dev/stderr
+  portal_api_error_log: /dev/stderr
+  prefix: /kong_prefix/
+
+extraLabels: {}
+
+# Specify Kong's Docker image and repository details here
+image:
+  repository: kong
+  tag: "3.4"
+
+  # Specify a semver version if your image tag is not one (e.g. "nightly")
+  effectiveSemver:
+  pullPolicy: IfNotPresent
+
+# Specify Kong admin API service and listener configuration
+admin:
+  enabled: true
+  type: NodePort
+  loadBalancerClass:
+  annotations: {}
+  labels: {}
+
+  http:
+    # Enable plaintext HTTP listen for the admin API
+    enabled: true
+    servicePort: 8001
+    containerPort: 8001
+    nodePort: 32081
+    parameters: []
+
+  tls:
+    # Enable HTTPS listen for the admin API
+    enabled: true
+    servicePort: 8444
+    containerPort: 8444
+    nodePort: 32443
+    parameters:
+    - http2
+
+    client:
+      caBundle: ""
+      secretName: ""
+
+  # Kong admin ingress settings. Useful if you want to expose the Admin
+  # API of Kong outside the k8s cluster.
+  ingress:
+    # Enable/disable exposure using ingress.
+    enabled: false
+  
+# Specify Kong status listener configuration
+status:
+  enabled: true
+  http:
+    enabled: true
+    containerPort: 8100
+    parameters: []
+
+  tls:
+    enabled: false
+    containerPort: 8543
+    parameters: []
+
+clusterCaSecretName: ""
+
+cluster:
+  enabled: false
+
+  tls:
+    enabled: false
+
+  type: ClusterIP
+  loadBalancerClass:
+
+  # Kong cluster ingress settings. Useful if you want to split CP and DP
+  # in different clusters.
+  ingress:
+    # Enable/disable exposure using ingress.
+    enabled: false
+
+# Specify Kong proxy service configuration
+proxy:
+  # Enable creating a Kubernetes service for the proxy
+  enabled: true
+  type: LoadBalancer
+  loadBalancerClass:
+  nameOverride: ""
+  annotations: {}
+  labels:
+    enable-metrics: "true"
+
+  http:
+    # Enable plaintext HTTP listen for the proxy
+    enabled: true
+    servicePort: 80
+    containerPort: 8000
+    # Set a nodePort which is available if service type is NodePort
+    nodePort: 32080
+    parameters: []
+
+  tls:
+    # Enable HTTPS listen for the proxy
+    enabled: true
+    servicePort: 443
+    containerPort: 8443
+    parameters:
+    - http2
+
+  stream: []
+
+  ingress:
+    enabled: false
+
+udpProxy:
+  enabled: false
+
+plugins: {}
+
+secretVolumes: []
+
+# Enable/disable migration jobs, and set annotations for them
+migrations:
+  preUpgrade: true
+  postUpgrade: true
+  annotations:
+    sidecar.istio.io/inject: false
+  jobAnnotations: {}
+  backoffLimit:
+  resources: {}
+  
+# Kong's configuration for DB-less mode
+dblessConfig:
+  configMap: ""
+  secret: ""
+  config: |
+
+# -----------------------------------------------------------------------------
+# Ingress Controller parameters
+# -----------------------------------------------------------------------------
+
+ingressController:
+  enabled: true
+  image:
+    repository: kong/kubernetes-ingress-controller
+    tag: "3.0"
+    effectiveSemver:
+  args: []
+
+  gatewayDiscovery:
+    enabled: false
+    generateAdminApiService: false
+    adminApiService:
+      namespace: ""
+      name: ""
+
+  watchNamespaces: []
+
+  env:
+    kong_admin_tls_skip_verify: true
+
+  admissionWebhook:
+    enabled: true
+    failurePolicy: Ignore
+    port: 8080
+    certificate:
+      provided: false
+    namespaceSelector: {}
+    service:
+      labels: {}
+
+  ingressClass: kong
+  ingressClassAnnotations: {}
+
+  rbac:
+    create: true
+
+  livenessProbe:
+    httpGet:
+      path: "/healthz"
+      port: 10254
+      scheme: HTTP
+    initialDelaySeconds: 5
+    timeoutSeconds: 5
+    periodSeconds: 10
+    successThreshold: 1
+    failureThreshold: 3
+  readinessProbe:
+    httpGet:
+      path: "/readyz"
+      port: 10254
+      scheme: HTTP
+    initialDelaySeconds: 5
+    timeoutSeconds: 5
+    periodSeconds: 10
+    successThreshold: 1
+    failureThreshold: 3
+  resources: {}
+
+  konnect:
+    enabled: false
+
+  adminApi:
+    tls:
+      client:
+        enabled: false
+
+
+# -----------------------------------------------------------------------------
+# Postgres sub-chart parameters
+# -----------------------------------------------------------------------------
+
+postgresql:
+  enabled: true
+  auth:
+    username: kong
+    database: kong
+    password: kong
+    postgresPassword: kong
+  image:
+    # use postgres < 14 until is https://github.com/Kong/kong/issues/8533 resolved 
+    tag: 13.11.0-debian-11-r20
+  service:
+    ports:
+      postgresql: "5432"
+  volumePermissions:
+    enabled: true 
+  primary:
+    persistence:
+      existingClaim: kong-postgresql-pvc
+
+# -----------------------------------------------------------------------------
+# Configure cert-manager integration
+# -----------------------------------------------------------------------------
+
+certificates:
+  enabled: false
+
+# -----------------------------------------------------------------------------
+# Miscellaneous parameters
+# -----------------------------------------------------------------------------
+
+waitImage:
+  enabled: true
+  pullPolicy: IfNotPresent
+
+updateStrategy: {}
+
+resources: {}
+
+readinessProbe:
+  httpGet:
+    path: "/status/ready"
+    port: status
+    scheme: HTTP
+  initialDelaySeconds: 5
+  timeoutSeconds: 5
+  periodSeconds: 10
+  successThreshold: 1
+  failureThreshold: 3
+
+livenessProbe:
+  httpGet:
+    path: "/status"
+    port: status
+    scheme: HTTP
+  initialDelaySeconds: 5
+  timeoutSeconds: 5
+  periodSeconds: 10
+  successThreshold: 1
+  failureThreshold: 3
+
+lifecycle:
+  preStop:
+    exec:
+      command:
+        - kong
+        - quit
+        - '--wait=15'
+
+terminationGracePeriodSeconds: 30
+
+
+tolerations: []
+
+nodeSelector: {}
+
+podAnnotations:
+  kuma.io/gateway: enabled
+  traffic.sidecar.istio.io/includeInboundPorts: ""
+
+podLabels: {}
+
+replicaCount: 1
+
+deploymentAnnotations: {}
+
+autoscaling:
+  enabled: false
+
+podDisruptionBudget:
+  enabled: false
+
+podSecurityPolicy:
+  enabled: false
+  labels: {}
+  annotations: {}
+  spec:
+    privileged: false
+    fsGroup:
+      rule: RunAsAny
+    runAsUser:
+      rule: RunAsAny
+    runAsGroup:
+      rule: RunAsAny
+    seLinux:
+      rule: RunAsAny
+    supplementalGroups:
+      rule: RunAsAny
+    volumes:
+      - 'configMap'
+      - 'secret'
+      - 'emptyDir'
+      - 'projected'
+    allowPrivilegeEscalation: false
+    hostNetwork: false
+    hostIPC: false
+    hostPID: false
+    readOnlyRootFilesystem: true
+
+
+priorityClassName: ""
+
+securityContext: {}
+
+containerSecurityContext:
+  readOnlyRootFilesystem: true
+  allowPrivilegeEscalation: false
+  runAsUser: 1000
+  runAsNonRoot: true
+  seccompProfile:
+    type: RuntimeDefault
+  capabilities:
+    drop:
+    - ALL
+
+serviceMonitor:
+  enabled: false
+
+# -----------------------------------------------------------------------------
+# Kong Enterprise parameters
+# -----------------------------------------------------------------------------
+
+enterprise:
+  enabled: false
+
+manager:
+  enabled: true
+  type: NodePort
+  loadBalancerClass:
+  annotations: {}
+  labels: {}
+
+  http:
+    enabled: true
+    servicePort: 8002
+    containerPort: 8002
+    parameters: []
+
+  tls:
+    enabled: true
+    servicePort: 8445
+    containerPort: 8445
+    parameters:
+    - http2
+
+  ingress:
+    enabled: false
+
+portal:
+  enabled: true
+  type: NodePort
+  loadBalancerClass:
+  annotations: {}
+  labels: {}
+
+  http:
+    enabled: true
+    servicePort: 8003
+    containerPort: 8003
+    parameters: []
+
+  tls:
+    enabled: true
+    servicePort: 8446
+    containerPort: 8446
+    parameters:
+    - http2
+
+  ingress:
+    enabled: false
+
+portalapi:
+  enabled: true
+  type: NodePort
+  loadBalancerClass:
+  annotations: {}
+  labels: {}
+
+  http:
+    enabled: true
+    servicePort: 8004
+    containerPort: 8004
+    parameters: []
+
+  tls:
+    enabled: true
+    servicePort: 8447
+    containerPort: 8447
+    parameters:
+    - http2
+
+  ingress:
+    enabled: false
+
+clustertelemetry:
+  enabled: false
+  annotations: {}
+  labels: {}
+
+  tls:
+    enabled: false
+
+  type: ClusterIP
+  loadBalancerClass:
+
+  ingress:
+    enabled: false
+
+extraConfigMaps: []
+
+extraSecrets: []
+
+extraObjects: []
diff --git a/servicemanager/deploy/src/delete-from-k8s.sh b/servicemanager/deploy/src/delete-from-k8s.sh
new file mode 100755 (executable)
index 0000000..fd5289c
--- /dev/null
@@ -0,0 +1,38 @@
+#!/bin/bash
+##############################################################################
+#
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+##############################################################################
+
+echo $(date -u) "delete-from-k8s started"
+
+# Delete R1-SME-Manager with Capifcore
+kubectl delete -f ../manifests/servicemanager.yaml
+kubectl delete configmap env-configmap -n servicemanager
+kubectl delete -f ../manifests/capifcore.yaml
+kubectl delete ns servicemanager
+
+# Delete Kong
+go run ../../internal/kongclearup.go
+helm uninstall kong -n kong
+helm repo remove kong
+kubectl wait deploy/kong-kong --for=delete --timeout=-300s -n kong 
+
+# Delete storage for the Postgres used by Kong
+kubectl delete -f ../manifests/kong-postgres-pvc.yaml
+kubectl delete ns kong
+
+echo $(date -u) "delete-from-k8s completed"
\ No newline at end of file
diff --git a/servicemanager/deploy/src/deploy-to-k8s.sh b/servicemanager/deploy/src/deploy-to-k8s.sh
new file mode 100755 (executable)
index 0000000..9e81d61
--- /dev/null
@@ -0,0 +1,151 @@
+#!/bin/bash
+##############################################################################
+#
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#
+##############################################################################
+
+create_env_from_template(){
+    # Set up .env file for Kubernetes Config Map
+    echo "create_env_from_template"
+    cp -v ../../.env.example ./.env
+    sed -i 's/KONG_DOMAIN=<string>/KONG_DOMAIN=kong/' .env
+    sed -i 's/KONG_PROTOCOL=<http or https protocol scheme>/KONG_PROTOCOL=http/' .env
+    sed -i 's/KONG_IPV4=<host string>/KONG_IPV4=10.101.1.101/' .env
+    sed -i 's/KONG_DATA_PLANE_PORT=<port number>/KONG_DATA_PLANE_PORT=32080/' .env
+    sed -i 's/KONG_CONTROL_PLANE_PORT=<port number>/KONG_CONTROL_PLANE_PORT=32081/' .env
+    sed -i 's/CAPIF_PROTOCOL=<http or https protocol scheme>/CAPIF_PROTOCOL=http/' .env
+    sed -i 's/CAPIF_IPV4=<host>/CAPIF_IPV4=10.101.1.101/' .env
+    sed -i 's/CAPIF_PORT=<port number>/CAPIF_PORT=31570/' .env
+    sed -i 's/LOG_LEVEL=<Trace, Debug, Info, Warning, Error, Fatal or Panic>/LOG_LEVEL=Info/' .env
+    sed -i 's/SERVICE_MANAGER_PORT=<port number>/SERVICE_MANAGER_PORT=8095/' .env
+    sed -i 's/TEST_SERVICE_IPV4=<host string>/TEST_SERVICE_IPV4=10.101.1.101/' .env
+    sed -i 's/TEST_SERVICE_PORT=<port number>/TEST_SERVICE_PORT=30951/' .env
+}
+
+substitute_repo(){
+    echo "substitute_repo"
+    docker_repo=$1
+
+    # Use our own Capificore and ServiceManager images
+    sed -i "s/image: o-ran-sc.org\/nonrtric\/plt\/capifcore/image: $docker_repo\/capifcore:latest/" ../manifests/capifcore.yaml
+    sed -i 's/imagePullPolicy: IfNotPresent/imagePullPolicy: Always/' ../manifests/capifcore.yaml
+    sed -i "s/image: o-ran-sc.org\/nonrtric\/plt\/servicemanager/image: $docker_repo\/servicemanager:latest/" ../manifests/servicemanager.yaml
+    sed -i 's/imagePullPolicy: IfNotPresent/imagePullPolicy: Always/' ../manifests/servicemanager.yaml
+}
+
+add_env(){
+    echo "add_env"
+    additional_env=$1
+    # Add our own .env file
+    if [ -f $additional_env ]; then
+        echo "found additional env"
+        kubectl create configmap env-configmap --from-file=.env --from-file=$additional_env -n servicemanager
+
+        # Add additional env file to volume mounting
+        env_filename=$(basename "$additional_env")
+        echo "env_filename $env_filename"
+
+        mount_path_wc=$(grep "mountPath: /app/$env_filename" ../manifests/servicemanager.yaml | wc -l)
+        env_path_count=$((mount_path_wc))
+        if [ $env_path_count -eq 0 ]; then
+            echo "Adding mount path"
+            sed -i -e '/subPath: .env/a\' -e "        - name: config-volume\n          mountPath: /app/$env_filename\n          subPath: $env_filename" ../manifests/servicemanager.yaml
+        fi
+
+        # Update SERVICE_MANAGER_ENV to point to additional env
+        env_extension=$(basename "$additional_env" | awk -F. '{print $NF}')
+        echo "env_extension $env_extension"
+
+        sed -i "/- name: SERVICE_MANAGER_ENV/{n;s/              value: \"\"/              value: \"$env_extension\"/}" ../manifests/servicemanager.yaml
+    fi
+}
+
+echo $(date -u) "deploy-to-k8s started"
+
+# Check if the development switch is provided as a command-line argument
+USE_OWN_REPO=false
+ADD_ENV=false
+
+while [[ "$#" -gt 0 ]]; do
+    case "$1" in
+        -r|--repo)
+            USE_OWN_REPO=true
+            shift  # consume the switch
+            if [ -n "$1" ]; then
+                DOCKER_REPO="$1"
+                shift  # consume the value
+            else
+                echo "Error: Argument for $1 is missing." >&2
+                exit 1
+            fi
+            ;;
+        -e|--env)
+            ADD_ENV=true
+            shift  # consume the switch
+            if [ -n "$1" ]; then
+                ENV_PATH="$1"
+                shift  # consume the value
+            else
+                echo "Error: Argument for $1 is missing." >&2
+                exit 1
+            fi
+            ;;
+        *)
+            echo "Unknown argument: $1"
+            exit 1
+            ;;
+    esac
+done
+
+kubectl create ns kong
+
+# Set up storage for Postgres, used by Kong
+# Minikube uses dynamic provisioning
+CURRENT_CONTEXT=$(kubectl config current-context)
+if [ "$CURRENT_CONTEXT" != "minikube" ]; then
+    kubectl create -f ../manifests/kong-postgres-pv.yaml
+fi
+kubectl create -f ../manifests/kong-postgres-pvc.yaml
+
+# Deploy Kong
+helm repo add kong https://charts.konghq.com
+helm repo update
+helm install kong kong/kong -n kong -f ../manifests/values.yaml
+
+create_env_from_template
+
+# Check if the development switch is enabled
+if [ "$USE_OWN_REPO" = true ]; then
+    substitute_repo $DOCKER_REPO
+fi
+
+kubectl create ns servicemanager
+
+if [ "$ADD_ENV" = true ]; then
+    add_env $ENV_PATH
+else
+    kubectl create configmap env-configmap --from-file=.env -n servicemanager
+fi
+
+# Create the Kubernetes resources
+kubectl create -f ../manifests/capifcore.yaml
+kubectl create -f ../manifests/servicemanager.yaml
+
+kubectl rollout status deployment capifcore -n servicemanager --timeout=90s
+kubectl rollout status deployment servicemanager -n servicemanager --timeout=90s
+kubectl rollout status deployment kong-kong -n kong --timeout=90s
+
+echo $(date -u) "deploy-to-k8s completed"
diff --git a/servicemanager/docker-compose.yaml b/servicemanager/docker-compose.yaml
new file mode 100644 (file)
index 0000000..6815056
--- /dev/null
@@ -0,0 +1,44 @@
+#  ============LICENSE_START===============================================
+#  Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved.
+#  ========================================================================
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#       http://www.apache.org/licenses/LICENSE-2.0
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#  ============LICENSE_END=================================================
+#
+version: '3.5'
+
+services:
+  capifcore:
+    container_name: sme-capifcore
+    image: capifcore:latest
+    ports:
+      - 8090:8090
+    entrypoint: ["/capifcore"]
+    networks:
+      - capif
+
+  servicemanager:
+    container_name: servicemanager
+    image: servicemanager:latest
+    environment:
+      - SERVICE_MANAGER_ENV=""
+    ports:
+      - 8095:8095
+    depends_on:
+      - sme-capifcore
+    networks:
+      - capif
+
+networks:
+  capif:
+    driver: bridge
+    name: capifnet
\ No newline at end of file
similarity index 51%
rename from r1-sme-manager/generate-service-publish-and-discovery.sh
rename to servicemanager/generate.sh
index ca9f5ce..efe7a1a 100755 (executable)
@@ -1,8 +1,9 @@
+#!/bin/bash
 # -
 #   ========================LICENSE_START=================================
 #   O-RAN-SC
 #   %%
-#   Copyright (C) 2023: Nordix Foundation
+#   Copyright (C) 2024: OpenInfra Foundation Europe
 #   %%
 #   Licensed under the Apache License, Version 2.0 (the "License");
 #   you may not use this file except in compliance with the License.
 #   ========================LICENSE_END===================================
 #
 
-#!/bin/bash
-
 make_internal_dirs () {
-    echo "Make the internal directory structure"
-    mkdir -p internal/config
-    mkdir -p internal/discoverservice
+    echo "Make the internal API directory structure"
     mkdir -p internal/discoverserviceapi
-    mkdir -p internal/eventsapi
-    mkdir -p internal/eventservice
-    mkdir -p internal/helmmanagement
-    mkdir -p internal/invokermanagement
     mkdir -p internal/invokermanagementapi
-    mkdir -p internal/keycloak
-    mkdir -p internal/loggingapi
-    mkdir -p internal/providermanagement
     mkdir -p internal/providermanagementapi
-    mkdir -p internal/publishservice
     mkdir -p internal/publishserviceapi
-    mkdir -p internal/restclient
-}
-
-tear_down () {
-    echo "Tear down the internal directory"
-    rm -rf internal/
 }
 
 set_up_dir_paths () {
@@ -51,23 +34,6 @@ set_up_dir_paths () {
     capifcore_dir="$sme_dir/capifcore"
 }
 
-copy_test_wrappers () {
-    echo "Copy the test wrappers"
-    cp -v $capifcore_dir/internal/config/*.go internal/config
-    cp -v $capifcore_dir/internal/discoverservice/*.go internal/discoverservice
-    cp -v $capifcore_dir/internal/eventsapi/type*.go internal/eventsapi
-    cp -v $capifcore_dir/internal/eventservice/*.go internal/eventservice
-    cp -v $capifcore_dir/internal/helmmanagement/*.go internal/helmmanagement
-    cp -v $capifcore_dir/internal/invokermanagement/*.go internal/invokermanagement
-    cp -v $capifcore_dir/internal/invokermanagementapi/type*.go internal/invokermanagementapi
-    cp -v $capifcore_dir/internal/keycloak/*.go internal/keycloak
-    cp -v $capifcore_dir/internal/providermanagement/*.go internal/providermanagement
-    cp -v $capifcore_dir/internal/providermanagementapi/*.go internal/providermanagementapi
-    cp -v $capifcore_dir/internal/publishservice/*.go internal/publishservice
-    cp -v $capifcore_dir/internal/publishserviceapi/type*.go internal/publishserviceapi
-    cp -v $capifcore_dir/internal/restclient/*.go internal/restclient
-}
-
 curl_api_specs () {
     echo "Curl down the API specs"
     mkdir -p specs
@@ -86,25 +52,24 @@ curl_api_specs () {
     curl https://www.3gpp.org/ftp/Specs/archive/29_series/29.572/29572-h60.zip -o specs/common29572apidef.zip
 }
 
-jar_extraction () {
+spec_extraction () {
     cd specs/
-    echo "Jar extraction"
-    jar xvf apidef.zip
-    jar xvf common29122apidef.zip
-    jar xvf common29508apidef.zip
-    jar xvf common29510apidef.zip
-    jar xvf common29512apidef.zip
-    jar xvf common29514apidef.zip
-    jar xvf common29517apidef.zip
-    jar xvf common29518apidef.zip
-    jar xvf common29522apidef.zip
-    jar xvf common29523apidef.zip
-    jar xvf common29554apidef.zip
-    jar xvf common29571apidef.zip
-    jar xvf common29572apidef.zip
+    echo "Specifications extraction"
+    unzip -o apidef.zip
+    unzip -o common29122apidef.zip
+    unzip -o common29508apidef.zip
+    unzip -o common29510apidef.zip
+    unzip -o common29512apidef.zip
+    unzip -o common29514apidef.zip
+    unzip -o common29517apidef.zip
+    unzip -o common29518apidef.zip
+    unzip -o common29522apidef.zip
+    unzip -o common29523apidef.zip
+    unzip -o common29554apidef.zip
+    unzip -o common29571apidef.zip
+    unzip -o common29572apidef.zip
 }
 
-
 fix_with_sed () {
     echo "Fixing with sed"
 
@@ -120,7 +85,7 @@ fix_with_sed () {
     sed -i -e 'H;x;/^\(  *\)\n\1/{s/\n.*//;x;d;}' -e 's/.*//;x;/\MbsSession/{s/^\( *\).*/ \1/;x;d;}' TS29571_CommonData.yaml
     sed -i -e 'H;x;/^\(  *\)\n\1/{s/\n.*//;x;d;}' -e 's/.*//;x;/\SpatialValidityCond/{s/^\( *\).*/ \1/;x;d;}' TS29571_CommonData.yaml
 
-    # Remove attributes that can not be generated easily.
+    # Remove attributes that cannot be generated easily.
     sed -i '/accessTokenError.*/,+3d' TS29571_CommonData.yaml
     sed -i '/accessTokenRequest.*/,+3d' TS29571_CommonData.yaml
     sed -i '/oneOf.*/,+2d' TS29222_CAPIF_Publish_Service_API.yaml
@@ -148,20 +113,20 @@ gentools () {
 
     cd "$capifcore_dir/internal/gentools/enumfixer"
     go build .
-    ./enumfixer -apidir="$sme_dir/r1-sme-manager/specs"
+    ./enumfixer -apidir="$sme_dir/servicemanager/specs"
 
     echo "Gathering common references"
     cd "$capifcore_dir/internal/gentools/commoncollector"
     go build .
-    ./commoncollector -apidir="$sme_dir/r1-sme-manager/specs"
+    ./commoncollector -apidir="$sme_dir/servicemanager/specs"
 
     echo "Fixing misc in specifications"
     cd "$capifcore_dir/internal/gentools/specificationfixer"
     go build .
-    ./specificationfixer -apidir="$sme_dir/r1-sme-manager/specs"
+    ./specificationfixer -apidir="$sme_dir/servicemanager/specs"
 }
 
-code_generation () {
+generate_apis_from_spec () {
     go install github.com/deepmap/oapi-codegen/cmd/oapi-codegen@v1.10.1
     PATH=$PATH:~/go/bin
 
@@ -169,93 +134,81 @@ code_generation () {
 
     echo "Generating TS29122_CommonData"
     mkdir -p internal/common29122
-    oapi-codegen --config "$capifcore_dir/gogeneratorspecs/common29122/generator_settings.yaml" specs/TS29122_CommonData.yaml
+    oapi-codegen --config "gogeneratorspecs/common29122/generator_settings.yaml" specs/TS29122_CommonData.yaml
 
     echo "Generating aggregated CommonData"
     mkdir -p internal/common
-    oapi-codegen --config "$capifcore_dir/gogeneratorspecs/common/generator_settings.yaml" specs/CommonData.yaml
+    oapi-codegen --config "gogeneratorspecs/common/generator_settings.yaml" specs/CommonData.yaml
 
     echo "Generating TS29571_CommonData"
     mkdir -p internal/common29571
-    oapi-codegen --config "$capifcore_dir/gogeneratorspecs/common29571/generator_settings.yaml" specs/TS29571_CommonData.yaml
+    oapi-codegen --config "gogeneratorspecs/common29571/generator_settings.yaml" specs/TS29571_CommonData.yaml
 
     echo "Generating TS29222_CAPIF_Publish_Service_API"
     mkdir -p internal/publishserviceapi
-    oapi-codegen --config "$capifcore_dir/gogeneratorspecs/publishserviceapi/generator_settings_types.yaml" specs/TS29222_CAPIF_Publish_Service_API.yaml
-    oapi-codegen --config "$capifcore_dir/gogeneratorspecs/publishserviceapi/generator_settings_server.yaml" specs/TS29222_CAPIF_Publish_Service_API.yaml
+    oapi-codegen --config "gogeneratorspecs/publishserviceapi/generator_settings_types.yaml" specs/TS29222_CAPIF_Publish_Service_API.yaml
+    oapi-codegen --config "gogeneratorspecs/publishserviceapi/generator_settings_server.yaml" specs/TS29222_CAPIF_Publish_Service_API.yaml
+    oapi-codegen --config "gogeneratorspecs/publishserviceapi/generator_settings_client.yaml" specs/TS29222_CAPIF_Publish_Service_API.yaml
 
     echo "Generating TS29222_CAPIF_API_Invoker_Management_API"
     mkdir -p internal/invokermanagementapi
-    oapi-codegen --config "$capifcore_dir/gogeneratorspecs/invokermanagementapi/generator_settings_types.yaml" specs/TS29222_CAPIF_API_Invoker_Management_API.yaml
-    oapi-codegen --config "$capifcore_dir/gogeneratorspecs/invokermanagementapi/generator_settings_server.yaml" specs/TS29222_CAPIF_API_Invoker_Management_API.yaml
+    oapi-codegen --config "gogeneratorspecs/invokermanagementapi/generator_settings_types.yaml" specs/TS29222_CAPIF_API_Invoker_Management_API.yaml
+    oapi-codegen --config "gogeneratorspecs/invokermanagementapi/generator_settings_server.yaml" specs/TS29222_CAPIF_API_Invoker_Management_API.yaml
+    oapi-codegen --config "gogeneratorspecs/invokermanagementapi/generator_settings_client.yaml" specs/TS29222_CAPIF_API_Invoker_Management_API.yaml
 
     echo "Generating TS29222_CAPIF_API_Provider_Management_API"
     mkdir -p internal/providermanagementapi
-    oapi-codegen --config "$capifcore_dir/gogeneratorspecs/providermanagementapi/generator_settings_types.yaml" specs/TS29222_CAPIF_API_Provider_Management_API.yaml
-    oapi-codegen --config "$capifcore_dir/gogeneratorspecs/providermanagementapi/generator_settings_server.yaml" specs/TS29222_CAPIF_API_Provider_Management_API.yaml
+    oapi-codegen --config "gogeneratorspecs/providermanagementapi/generator_settings_types.yaml" specs/TS29222_CAPIF_API_Provider_Management_API.yaml
+    oapi-codegen --config "gogeneratorspecs/providermanagementapi/generator_settings_server.yaml" specs/TS29222_CAPIF_API_Provider_Management_API.yaml
+    oapi-codegen --config "gogeneratorspecs/providermanagementapi/generator_settings_client.yaml" specs/TS29222_CAPIF_API_Provider_Management_API.yaml
 
     echo "Generating TS29222_CAPIF_Discover_Service_API"
     mkdir -p internal/discoverserviceapi
-    oapi-codegen --config "$capifcore_dir/gogeneratorspecs/discoverserviceapi/generator_settings_types.yaml" specs/TS29222_CAPIF_Discover_Service_API.yaml
-    oapi-codegen --config "$capifcore_dir/gogeneratorspecs/discoverserviceapi/generator_settings_server.yaml" specs/TS29222_CAPIF_Discover_Service_API.yaml
-
-    echo "Generating TS29222_CAPIF_Logging_API_Invocation_API"
-    mkdir -p internal/loggingapi
-    oapi-codegen --config "$capifcore_dir/gogeneratorspecs/loggingapi/generator_settings_types.yaml" specs/TS29222_CAPIF_Logging_API_Invocation_API.yaml
-    oapi-codegen --config "$capifcore_dir/gogeneratorspecs/loggingapi/generator_settings_server.yaml" specs/TS29222_CAPIF_Logging_API_Invocation_API.yaml
-
-    echo "Generating TS29222_CAPIF_Routing_Info_API"
-    mkdir -p internal/routinginfoapi
-    oapi-codegen --config "$capifcore_dir/gogeneratorspecs/routinginfoapi/generator_settings_types.yaml" specs/TS29222_CAPIF_Routing_Info_API.yaml
-    oapi-codegen --config "$capifcore_dir/gogeneratorspecs/routinginfoapi/generator_settings_server.yaml" specs/TS29222_CAPIF_Routing_Info_API.yaml
-
-    echo "Generating TS29222_CAPIF_Access_Control_Policy_API"
-    mkdir -p internal/accesscontrolpolicyapi
-    oapi-codegen --config "$capifcore_dir/gogeneratorspecs/accesscontrolpolicyapi/generator_settings_types.yaml" specs/TS29222_CAPIF_Access_Control_Policy_API.yaml
-    oapi-codegen --config "$capifcore_dir/gogeneratorspecs/accesscontrolpolicyapi/generator_settings_server.yaml" specs/TS29222_CAPIF_Access_Control_Policy_API.yaml
-
-    echo "Generating TS29222_CAPIF_Events_API"
-    mkdir -p internal/eventsapi
-    oapi-codegen --config "$capifcore_dir/gogeneratorspecs/eventsapi/generator_settings_types.yaml" specs/TS29222_CAPIF_Events_API.yaml
-    oapi-codegen --config "$capifcore_dir/gogeneratorspecs/eventsapi/generator_settings_server.yaml" specs/TS29222_CAPIF_Events_API.yaml
-
-    echo "Clean up"
-    rm -rf specs
-}
-
-
-fix_package_imports () {
-    echo "Fix package imports"
-    if find "$cwd/internal" -type f -exec sed -i 's/oransc.org\/nonrtric\/capifcore/oransc.org\/nonrtric\/r1-sme-manager/g' {} +; then
-        echo "Package import replacement successful"
-    else
-        echo "Package import replacement failed"
-    fi
-}
-
-generate_mocks () {
-    echo "Generating mocks"
-    go generate ./...
+    oapi-codegen --config "gogeneratorspecs/discoverserviceapi/generator_settings_types.yaml" specs/TS29222_CAPIF_Discover_Service_API.yaml
+    oapi-codegen --config "gogeneratorspecs/discoverserviceapi/generator_settings_server.yaml" specs/TS29222_CAPIF_Discover_Service_API.yaml
+    oapi-codegen --config "gogeneratorspecs/discoverserviceapi/generator_settings_client.yaml" specs/TS29222_CAPIF_Discover_Service_API.yaml
 }
 
-running_tests () {
-    echo "Running tests"
-    cd internal
-    go clean -testcache
-    go test ./publishservice ./discoverservice
+run_tests () {
+    # Make sure that SERVICE_MANAGER_ENV is configured with the required .env file, e.g. 
+    # export SERVICE_MANAGER_ENV=development
+    cd "$cwd"
+    go test -p=1 -count=1 ./...
 }
 
 # Main code block
+echo $(date -u) "generate started"
+
+# Check if the run-tests switch is provided as a command-line argument
+RUN_TESTS=false
+while [[ "$#" -gt 0 ]]; do
+    case "$1" in
+        -t|--run-tests)
+            RUN_TESTS=true
+            shift  # consume the switch
+            ;;
+        *)
+            echo "Unknown argument: $1"
+            exit 1
+            ;;
+    esac
+    shift
+done
 
-tear_down
 make_internal_dirs
 set_up_dir_paths
-copy_test_wrappers
 curl_api_specs
-jar_extraction
+spec_extraction
 fix_with_sed
 gentools
-code_generation
-fix_package_imports
-generate_mocks
-running_tests
+generate_apis_from_spec
+
+# Check if the run-tests switch is enabled
+if [ "$RUN_TESTS" = true ]; then
+    echo "Running tests!"
+    run_tests
+else
+    echo "Not running tests."
+fi
+
+echo $(date -u) "generate completed"
\ No newline at end of file
diff --git a/servicemanager/go.mod b/servicemanager/go.mod
new file mode 100644 (file)
index 0000000..6be0d03
--- /dev/null
@@ -0,0 +1,40 @@
+module oransc.org/nonrtric/servicemanager
+
+go 1.19
+
+require (
+       github.com/deepmap/oapi-codegen v1.11.0
+       github.com/getkin/kin-openapi v0.106.0
+       github.com/go-resty/resty/v2 v2.10.0
+       github.com/joho/godotenv v1.5.1
+       github.com/labstack/echo/v4 v4.9.1
+       github.com/sirupsen/logrus v1.9.3
+       github.com/stretchr/testify v1.7.1
+)
+
+require gopkg.in/yaml.v2 v2.4.0 // indirect
+
+require (
+       github.com/davecgh/go-spew v1.1.1 // indirect
+       github.com/go-openapi/jsonpointer v0.19.5 // indirect
+       github.com/go-openapi/swag v0.21.1 // indirect
+       github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
+       github.com/google/uuid v1.3.0 // indirect
+       github.com/gorilla/mux v1.8.0 // indirect
+       github.com/invopop/yaml v0.1.0 // indirect
+       github.com/josharian/intern v1.0.0 // indirect
+       github.com/labstack/gommon v0.4.0 // indirect
+       github.com/mailru/easyjson v0.7.7 // indirect
+       github.com/mattn/go-colorable v0.1.13 // indirect
+       github.com/mattn/go-isatty v0.0.18 // indirect
+       github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
+       github.com/pmezard/go-difflib v1.0.0 // indirect
+       github.com/valyala/bytebufferpool v1.0.0 // indirect
+       github.com/valyala/fasttemplate v1.2.2 // indirect
+       golang.org/x/crypto v0.14.0 // indirect
+       golang.org/x/net v0.17.0 // indirect
+       golang.org/x/sys v0.13.0 // indirect
+       golang.org/x/text v0.13.0 // indirect
+       golang.org/x/time v0.3.0 // indirect
+       gopkg.in/yaml.v3 v3.0.1 // indirect
+)
diff --git a/servicemanager/go.sum b/servicemanager/go.sum
new file mode 100644 (file)
index 0000000..99a1740
--- /dev/null
@@ -0,0 +1,223 @@
+github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
+github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
+github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
+github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
+github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.0-20210816181553-5444fa50b93d/go.mod h1:tmAIfUFEirG/Y8jhZ9M+h36obRZAk/1fcSpXwAVlfqE=
+github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
+github.com/deepmap/oapi-codegen v1.11.0 h1:f/X2NdIkaBKsSdpeuwLnY/vDI0AtPUrmB5LMgc7YD+A=
+github.com/deepmap/oapi-codegen v1.11.0/go.mod h1:k+ujhoQGxmQYBZBbxhOZNZf4j08qv5mC+OH+fFTnKxM=
+github.com/getkin/kin-openapi v0.94.0/go.mod h1:LWZfzOd7PRy8GJ1dJ6mCU6tNdSfOwRac1BUPam4aw6Q=
+github.com/getkin/kin-openapi v0.106.0 h1:hrqfqJPAvWvuO/V0lCr/xyQOq4Gy21mcr28JJOSRcEI=
+github.com/getkin/kin-openapi v0.106.0/go.mod h1:9Dhr+FasATJZjS4iOLvB0hkaxgYdulrNYm2e9epLWOo=
+github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
+github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
+github.com/go-chi/chi/v5 v5.0.7/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
+github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
+github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
+github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
+github.com/go-openapi/swag v0.21.1 h1:wm0rhTb5z7qpJRHBdPOMuY4QjVUMbF6/kwoYeRAOrKU=
+github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
+github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
+github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
+github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
+github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
+github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
+github.com/go-playground/validator/v10 v10.11.0/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
+github.com/go-resty/resty/v2 v2.10.0 h1:Qla4W/+TMmv0fOeeRqzEpXPLfTUnR5HZ1+lGs+CkiCo=
+github.com/go-resty/resty/v2 v2.10.0/go.mod h1:iiP/OpA0CkcL3IGt1O0+/SIItFUbkkyw5BGXiVdTu+A=
+github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
+github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
+github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
+github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
+github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
+github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
+github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
+github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
+github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
+github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
+github.com/invopop/yaml v0.1.0 h1:YW3WGUoJEXYfzWBjn00zIlrw7brGVD0fUKRYDPAPhrc=
+github.com/invopop/yaml v0.1.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
+github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
+github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
+github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
+github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
+github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
+github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
+github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
+github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
+github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
+github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
+github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
+github.com/labstack/echo/v4 v4.7.2/go.mod h1:xkCDAdFCIf8jsFQ5NnbK7oqaF/yU1A1X20Ltm0OvSks=
+github.com/labstack/echo/v4 v4.9.1 h1:GliPYSpzGKlyOhqIbG8nmHBo3i1saKWFOgh41AN3b+Y=
+github.com/labstack/echo/v4 v4.9.1/go.mod h1:Pop5HLc+xoc4qhTZ1ip6C0RtP7Z+4VzRLWZZFKqbbjo=
+github.com/labstack/gommon v0.3.1/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
+github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
+github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
+github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
+github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
+github.com/lestrrat-go/backoff/v2 v2.0.8/go.mod h1:rHP/q/r9aT27n24JQLa7JhSQZCKBBOiM/uP402WwN8Y=
+github.com/lestrrat-go/blackmagic v1.0.0/go.mod h1:TNgH//0vYSs8VXDCfkZLgIrVTTXQELZffUV0tz3MtdQ=
+github.com/lestrrat-go/blackmagic v1.0.1/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
+github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
+github.com/lestrrat-go/iter v1.0.1/go.mod h1:zIdgO1mRKhn8l9vrZJZz9TUMMFbQbLeTsbqPDrJ/OJc=
+github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
+github.com/lestrrat-go/jwx v1.2.24/go.mod h1:zoNuZymNl5lgdcu6P7K6ie2QRll5HVfF4xwxBBK1NxY=
+github.com/lestrrat-go/option v1.0.0/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
+github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
+github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
+github.com/matryer/moq v0.2.7/go.mod h1:kITsx543GOENm48TUAQyJ9+SAvFSr7iGQXPoth/VUBk=
+github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
+github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
+github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
+github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
+github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
+github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
+github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
+github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
+github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
+github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
+github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
+github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
+github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
+github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
+github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
+github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
+github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
+github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
+github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
+github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
+github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
+github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
+github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
+github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
+github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
+github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
+golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
+golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.0.0-20220513210258-46612604a0f9/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
+golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
+golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
+golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20220513224357-95641704303c/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
+golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
+golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
+golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220513210249-45d2b4557a2a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
+golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
+golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
+golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U=
+golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
+golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
+golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
+golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
+golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
+golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
+golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20220411224347-583f2d630306/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
+golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
+golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
+google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
+google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
+gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
+gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
+gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
+gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
+gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
+gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/servicemanager/gogeneratorspecs/common/generator_settings.yaml b/servicemanager/gogeneratorspecs/common/generator_settings.yaml
new file mode 100644 (file)
index 0000000..bc16d80
--- /dev/null
@@ -0,0 +1,29 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#   %%
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#   ========================LICENSE_END===================================
+#
+
+output:
+  internal/common/common.gen.go
+package: common
+generate:
+  - types
+  - skip-prune
+  - spec
+import-mapping:
+  TS29571_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29571
diff --git a/servicemanager/gogeneratorspecs/common29122/generator_settings.yaml b/servicemanager/gogeneratorspecs/common29122/generator_settings.yaml
new file mode 100644 (file)
index 0000000..0477f64
--- /dev/null
@@ -0,0 +1,30 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#   %%
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#   ========================LICENSE_END===================================
+#
+
+output:
+  internal/common29122/common29122.gen.go
+package: common29122
+generate:
+  - types
+  - skip-prune
+  - spec
+import-mapping:
+  TS29571_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29571
+  CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common
\ No newline at end of file
diff --git a/servicemanager/gogeneratorspecs/common29571/generator_settings.yaml b/servicemanager/gogeneratorspecs/common29571/generator_settings.yaml
new file mode 100644 (file)
index 0000000..b73b3fc
--- /dev/null
@@ -0,0 +1,27 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#   %%
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#   ========================LICENSE_END===================================
+#
+
+output:
+  internal/common29571/common29571.gen.go
+package: common29571
+generate:
+  - types
+  - skip-prune
+  - spec
\ No newline at end of file
diff --git a/servicemanager/gogeneratorspecs/discoverserviceapi/generator_settings_client.yaml b/servicemanager/gogeneratorspecs/discoverserviceapi/generator_settings_client.yaml
new file mode 100644 (file)
index 0000000..27bf534
--- /dev/null
@@ -0,0 +1,29 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#   %%
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#   ========================LICENSE_END===================================
+#
+
+output:
+  internal/discoverserviceapi/discoverserviceapi-client.gen.go
+package: discoverserviceapi
+generate:
+  - client
+import-mapping:
+  TS29122_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29122
+  TS29571_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29571
+  TS29222_CAPIF_Publish_Service_API.yaml: oransc.org/nonrtric/servicemanager/internal/publishserviceapi
\ No newline at end of file
diff --git a/servicemanager/gogeneratorspecs/discoverserviceapi/generator_settings_server.yaml b/servicemanager/gogeneratorspecs/discoverserviceapi/generator_settings_server.yaml
new file mode 100644 (file)
index 0000000..2aa30d9
--- /dev/null
@@ -0,0 +1,30 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#   %%
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#   ========================LICENSE_END===================================
+#
+
+output:
+  internal/discoverserviceapi/discoverserviceapi-server.gen.go
+package: discoverserviceapi
+generate:
+  - server
+  - spec
+import-mapping:
+  TS29122_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29122
+  TS29571_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29571
+  TS29222_CAPIF_Publish_Service_API.yaml: oransc.org/nonrtric/servicemanager/internal/publishserviceapi
\ No newline at end of file
diff --git a/servicemanager/gogeneratorspecs/discoverserviceapi/generator_settings_types.yaml b/servicemanager/gogeneratorspecs/discoverserviceapi/generator_settings_types.yaml
new file mode 100644 (file)
index 0000000..8dafa35
--- /dev/null
@@ -0,0 +1,29 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#   %%
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#   ========================LICENSE_END===================================
+#
+
+output:
+  internal/discoverserviceapi/discoverserviceapi-types.gen.go
+package: discoverserviceapi
+generate:
+  - types
+import-mapping:
+  TS29122_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29122
+  TS29571_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29571
+  TS29222_CAPIF_Publish_Service_API.yaml: oransc.org/nonrtric/servicemanager/internal/publishserviceapi
\ No newline at end of file
diff --git a/servicemanager/gogeneratorspecs/invokermanagementapi/generator_settings_client.yaml b/servicemanager/gogeneratorspecs/invokermanagementapi/generator_settings_client.yaml
new file mode 100644 (file)
index 0000000..f49a568
--- /dev/null
@@ -0,0 +1,29 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#   %%
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#   ========================LICENSE_END===================================
+#
+
+output:
+  internal/invokermanagementapi/invokermanagementapi-client.gen.go
+package: invokermanagementapi
+generate:
+  - client
+import-mapping:
+  TS29122_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29122
+  TS29571_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29571
+  TS29222_CAPIF_Publish_Service_API.yaml: oransc.org/nonrtric/servicemanager/internal/publishserviceapi
\ No newline at end of file
diff --git a/servicemanager/gogeneratorspecs/invokermanagementapi/generator_settings_server.yaml b/servicemanager/gogeneratorspecs/invokermanagementapi/generator_settings_server.yaml
new file mode 100644 (file)
index 0000000..d0ca36d
--- /dev/null
@@ -0,0 +1,30 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#   %%
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#   ========================LICENSE_END===================================
+#
+
+output:
+  internal/invokermanagementapi/invokermanagementapi-server.gen.go
+package: invokermanagementapi
+generate:
+  - server
+  - spec
+import-mapping:
+  TS29122_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29122
+  TS29571_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29571
+  TS29222_CAPIF_Publish_Service_API.yaml: oransc.org/nonrtric/servicemanager/internal/publishserviceapi
\ No newline at end of file
diff --git a/servicemanager/gogeneratorspecs/invokermanagementapi/generator_settings_types.yaml b/servicemanager/gogeneratorspecs/invokermanagementapi/generator_settings_types.yaml
new file mode 100644 (file)
index 0000000..aa36d21
--- /dev/null
@@ -0,0 +1,29 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#   %%
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#   ========================LICENSE_END===================================
+#
+
+output:
+  internal/invokermanagementapi/invokermanagementapi-types.gen.go
+package: invokermanagementapi
+generate:
+  - types
+import-mapping:
+  TS29122_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29122
+  TS29571_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29571
+  TS29222_CAPIF_Publish_Service_API.yaml: oransc.org/nonrtric/servicemanager/internal/publishserviceapi
\ No newline at end of file
diff --git a/servicemanager/gogeneratorspecs/providermanagementapi/generator_settings_client.yaml b/servicemanager/gogeneratorspecs/providermanagementapi/generator_settings_client.yaml
new file mode 100644 (file)
index 0000000..b24878f
--- /dev/null
@@ -0,0 +1,28 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#   %%
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#   ========================LICENSE_END===================================
+#
+
+output:
+  internal/providermanagementapi/providermanagementapi-client.gen.go
+package: providermanagementapi
+generate:
+  - client
+import-mapping:
+  TS29122_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29122
+  TS29571_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29571
\ No newline at end of file
diff --git a/servicemanager/gogeneratorspecs/providermanagementapi/generator_settings_server.yaml b/servicemanager/gogeneratorspecs/providermanagementapi/generator_settings_server.yaml
new file mode 100644 (file)
index 0000000..2e149f0
--- /dev/null
@@ -0,0 +1,29 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#   %%
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#   ========================LICENSE_END===================================
+#
+
+output:
+  internal/providermanagementapi/providermanagementapi-server.gen.go
+package: providermanagementapi
+generate:
+  - server
+  - spec
+import-mapping:
+  TS29122_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29122
+  TS29571_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29571
\ No newline at end of file
diff --git a/servicemanager/gogeneratorspecs/providermanagementapi/generator_settings_types.yaml b/servicemanager/gogeneratorspecs/providermanagementapi/generator_settings_types.yaml
new file mode 100644 (file)
index 0000000..d17b5e1
--- /dev/null
@@ -0,0 +1,28 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#   %%
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#   ========================LICENSE_END===================================
+#
+
+output:
+  internal/providermanagementapi/providermanagementapi-types.gen.go
+package: providermanagementapi
+generate:
+  - types
+import-mapping:
+  TS29122_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29122
+  TS29571_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29571
\ No newline at end of file
diff --git a/servicemanager/gogeneratorspecs/publishserviceapi/generator_settings_client.yaml b/servicemanager/gogeneratorspecs/publishserviceapi/generator_settings_client.yaml
new file mode 100644 (file)
index 0000000..2d192b9
--- /dev/null
@@ -0,0 +1,29 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2023-2024: OpenInfra Foundation Europe
+#   %%
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#   ========================LICENSE_END===================================
+#
+
+output:
+  internal/publishserviceapi/publishserviceapi-client.gen.go
+package: publishserviceapi
+generate:
+  - client
+import-mapping:
+  TS29122_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29122
+  TS29571_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29571
+  CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common
\ No newline at end of file
diff --git a/servicemanager/gogeneratorspecs/publishserviceapi/generator_settings_server.yaml b/servicemanager/gogeneratorspecs/publishserviceapi/generator_settings_server.yaml
new file mode 100644 (file)
index 0000000..0f81222
--- /dev/null
@@ -0,0 +1,30 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#   %%
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#   ========================LICENSE_END===================================
+#
+
+output:
+  internal/publishserviceapi/publishserviceapi-server.gen.go
+package: publishserviceapi
+generate:
+  - server
+  - spec
+import-mapping:
+  TS29122_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29122
+  TS29571_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29571
+  CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common
\ No newline at end of file
diff --git a/servicemanager/gogeneratorspecs/publishserviceapi/generator_settings_types.yaml b/servicemanager/gogeneratorspecs/publishserviceapi/generator_settings_types.yaml
new file mode 100644 (file)
index 0000000..9017321
--- /dev/null
@@ -0,0 +1,29 @@
+# -
+#   ========================LICENSE_START=================================
+#   O-RAN-SC
+#   %%
+#   Copyright (C) 2024: OpenInfra Foundation Europe
+#   %%
+#   Licensed under the Apache License, Version 2.0 (the "License");
+#   you may not use this file except in compliance with the License.
+#   You may obtain a copy of the License at
+#
+#        http://www.apache.org/licenses/LICENSE-2.0
+#
+#   Unless required by applicable law or agreed to in writing, software
+#   distributed under the License is distributed on an "AS IS" BASIS,
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#   See the License for the specific language governing permissions and
+#   limitations under the License.
+#   ========================LICENSE_END===================================
+#
+
+output:
+  internal/publishserviceapi/publishserviceapi-types.gen.go
+package: publishserviceapi
+generate:
+  - types
+import-mapping:
+  TS29122_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29122
+  TS29571_CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common29571
+  CommonData.yaml: oransc.org/nonrtric/servicemanager/internal/common
\ No newline at end of file
diff --git a/servicemanager/internal/common/common.gen.go b/servicemanager/internal/common/common.gen.go
new file mode 100644 (file)
index 0000000..d101fb7
--- /dev/null
@@ -0,0 +1,627 @@
+// Package common provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/deepmap/oapi-codegen version v1.10.1 DO NOT EDIT.
+package common
+
+import (
+       "bytes"
+       "compress/gzip"
+       "encoding/base64"
+       "fmt"
+       "net/url"
+       "path"
+       "strings"
+
+       "github.com/getkin/kin-openapi/openapi3"
+       externalRef0 "oransc.org/nonrtric/servicemanager/internal/common29571"
+)
+
+// Defines values for AfResultStatus.
+const (
+       AfResultStatusOTHER AfResultStatus = "OTHER"
+
+       AfResultStatusRELOCNOALLOWED AfResultStatus = "RELOC_NO_ALLOWED"
+
+       AfResultStatusSUCCESS AfResultStatus = "SUCCESS"
+
+       AfResultStatusTEMPORARYCONGESTION AfResultStatus = "TEMPORARY_CONGESTION"
+)
+
+// Defines values for FlowDirection.
+const (
+       FlowDirectionBIDIRECTIONAL FlowDirection = "BIDIRECTIONAL"
+
+       FlowDirectionDOWNLINK FlowDirection = "DOWNLINK"
+
+       FlowDirectionUNSPECIFIED FlowDirection = "UNSPECIFIED"
+
+       FlowDirectionUPLINK FlowDirection = "UPLINK"
+)
+
+// Defines values for NotificationMethod.
+const (
+       NotificationMethodONETIME NotificationMethod = "ONE_TIME"
+
+       NotificationMethodONEVENTDETECTION NotificationMethod = "ON_EVENT_DETECTION"
+
+       NotificationMethodPERIODIC NotificationMethod = "PERIODIC"
+)
+
+// Defines values for SupportedGADShapes.
+const (
+       SupportedGADShapesELLIPSOIDARC SupportedGADShapes = "ELLIPSOID_ARC"
+
+       SupportedGADShapesLOCAL2DPOINTUNCERTAINTYELLIPSE SupportedGADShapes = "LOCAL_2D_POINT_UNCERTAINTY_ELLIPSE"
+
+       SupportedGADShapesLOCAL3DPOINTUNCERTAINTYELLIPSOID SupportedGADShapes = "LOCAL_3D_POINT_UNCERTAINTY_ELLIPSOID"
+
+       SupportedGADShapesPOINT SupportedGADShapes = "POINT"
+
+       SupportedGADShapesPOINTALTITUDE SupportedGADShapes = "POINT_ALTITUDE"
+
+       SupportedGADShapesPOINTALTITUDEUNCERTAINTY SupportedGADShapes = "POINT_ALTITUDE_UNCERTAINTY"
+
+       SupportedGADShapesPOINTUNCERTAINTYCIRCLE SupportedGADShapes = "POINT_UNCERTAINTY_CIRCLE"
+
+       SupportedGADShapesPOINTUNCERTAINTYELLIPSE SupportedGADShapes = "POINT_UNCERTAINTY_ELLIPSE"
+
+       SupportedGADShapesPOLYGON SupportedGADShapes = "POLYGON"
+)
+
+// IP address and/or FQDN.
+type AddrFqdn struct {
+       // Indicates an FQDN.
+       Fqdn *string `json:"fqdn,omitempty"`
+
+       // Contains an IP adresse.
+       IpAddr *externalRef0.IpAddr `json:"ipAddr,omitempty"`
+}
+
+// Identifies the result of application layer handling.
+type AfResultInfo struct {
+       // Possible values are:
+       // - SUCCESS: The application layer is ready or the relocation is completed.
+       // - TEMPORARY_CONGESTION: The application relocation fails due to temporary congestion.
+       // - RELOC_NO_ALLOWED: The application relocation fails because application relocation is not allowed.
+       // - OTHER: The application relocation fails due to other reason.
+       AfStatus AfResultStatus `json:"afStatus"`
+
+       // Contains EAS IP replacement information.
+       EasIpReplaceInfos *[]externalRef0.EasIpReplacementInfo `json:"easIpReplaceInfos,omitempty"`
+
+       // At least one of the "routeInfo" attribute and the "routeProfId" attribute shall be included in the "RouteToLocation" data type.
+       TrafficRoute *externalRef0.RouteToLocation `json:"trafficRoute"`
+
+       // If present and set to "true" it indicates that buffering of uplink traffic to the target DNAI is needed.
+       UpBuffInd *bool `json:"upBuffInd,omitempty"`
+}
+
+// Possible values are:
+// - SUCCESS: The application layer is ready or the relocation is completed.
+// - TEMPORARY_CONGESTION: The application relocation fails due to temporary congestion.
+// - RELOC_NO_ALLOWED: The application relocation fails because application relocation is not allowed.
+// - OTHER: The application relocation fails due to other reason.
+type AfResultStatus string
+
+// Indicates value of altitude.
+type Altitude float64
+
+// Indicates value of angle.
+type Angle int
+
+// Indicates a Civic address.
+type CivicAddress struct {
+       A1         *string `json:"A1,omitempty"`
+       A2         *string `json:"A2,omitempty"`
+       A3         *string `json:"A3,omitempty"`
+       A4         *string `json:"A4,omitempty"`
+       A5         *string `json:"A5,omitempty"`
+       A6         *string `json:"A6,omitempty"`
+       ADDCODE    *string `json:"ADDCODE,omitempty"`
+       BLD        *string `json:"BLD,omitempty"`
+       FLR        *string `json:"FLR,omitempty"`
+       HNO        *string `json:"HNO,omitempty"`
+       HNS        *string `json:"HNS,omitempty"`
+       LMK        *string `json:"LMK,omitempty"`
+       LOC        *string `json:"LOC,omitempty"`
+       NAM        *string `json:"NAM,omitempty"`
+       PC         *string `json:"PC,omitempty"`
+       PCN        *string `json:"PCN,omitempty"`
+       PLC        *string `json:"PLC,omitempty"`
+       POBOX      *string `json:"POBOX,omitempty"`
+       POD        *string `json:"POD,omitempty"`
+       POM        *string `json:"POM,omitempty"`
+       PRD        *string `json:"PRD,omitempty"`
+       PRM        *string `json:"PRM,omitempty"`
+       RD         *string `json:"RD,omitempty"`
+       RDBR       *string `json:"RDBR,omitempty"`
+       RDSEC      *string `json:"RDSEC,omitempty"`
+       RDSUBBR    *string `json:"RDSUBBR,omitempty"`
+       ROOM       *string `json:"ROOM,omitempty"`
+       SEAT       *string `json:"SEAT,omitempty"`
+       STS        *string `json:"STS,omitempty"`
+       UNIT       *string `json:"UNIT,omitempty"`
+       Country    *string `json:"country,omitempty"`
+       Method     *string `json:"method,omitempty"`
+       ProvidedBy *string `json:"providedBy,omitempty"`
+       UsageRules *string `json:"usageRules,omitempty"`
+}
+
+// Describes a communication failure detected by AMF
+type CommunicationFailure struct {
+       NasReleaseCode *string `json:"nasReleaseCode,omitempty"`
+
+       // Represents the NGAP cause.
+       RanReleaseCode *externalRef0.NgApCause `json:"ranReleaseCode,omitempty"`
+}
+
+// Indicates value of confidence.
+type Confidence int
+
+// Represents the content version of some content.
+type ContentVersion int
+
+// EllipsoidArc defines model for EllipsoidArc.
+type EllipsoidArc struct {
+       // Embedded struct due to allOf(#/components/schemas/GADShape)
+       GADShape `yaml:",inline"`
+       // Embedded fields due to inline allOf schema
+       // Indicates value of confidence.
+       Confidence Confidence `json:"confidence"`
+
+       // Indicates value of angle.
+       IncludedAngle Angle `json:"includedAngle"`
+
+       // Indicates value of the inner radius.
+       InnerRadius InnerRadius `json:"innerRadius"`
+
+       // Indicates value of angle.
+       OffsetAngle Angle `json:"offsetAngle"`
+
+       // Geographical coordinates.
+       Point GeographicalCoordinates `json:"point"`
+
+       // Indicates value of uncertainty.
+       UncertaintyRadius Uncertainty `json:"uncertaintyRadius"`
+}
+
+// Identifies an Ethernet flow.
+type EthFlowDescription struct {
+       // String identifying a MAC address formatted in the hexadecimal notation according to clause 1.1 and clause 2.1 of RFC 7042.
+       DestMacAddr *externalRef0.MacAddr48 `json:"destMacAddr,omitempty"`
+
+       // String identifying a MAC address formatted in the hexadecimal notation according to clause 1.1 and clause 2.1 of RFC 7042.
+       DestMacAddrEnd *externalRef0.MacAddr48 `json:"destMacAddrEnd,omitempty"`
+       EthType        string                  `json:"ethType"`
+
+       // Defines a packet filter of an IP flow.
+       FDesc *FlowDescription `json:"fDesc,omitempty"`
+
+       // Possible values are
+       // - DOWNLINK: The corresponding filter applies for traffic to the UE.
+       // - UPLINK: The corresponding filter applies for traffic from the UE.
+       // - BIDIRECTIONAL: The corresponding filter applies for traffic both to and from the UE.
+       // - UNSPECIFIED: The corresponding filter applies for traffic to the UE (downlink), but has no specific direction declared. The service data flow detection shall apply the filter for uplink traffic as if the filter was bidirectional. The PCF shall not use the value UNSPECIFIED in filters created by the network in NW-initiated procedures. The PCF shall only include the value UNSPECIFIED in filters in UE-initiated procedures if the same value is received from the SMF.
+       FDir *FlowDirection `json:"fDir,omitempty"`
+
+       // String identifying a MAC address formatted in the hexadecimal notation according to clause 1.1 and clause 2.1 of RFC 7042.
+       SourceMacAddr *externalRef0.MacAddr48 `json:"sourceMacAddr,omitempty"`
+
+       // String identifying a MAC address formatted in the hexadecimal notation according to clause 1.1 and clause 2.1 of RFC 7042.
+       SrcMacAddrEnd *externalRef0.MacAddr48 `json:"srcMacAddrEnd,omitempty"`
+       VlanTags      *[]string               `json:"vlanTags,omitempty"`
+}
+
+// Defines a packet filter of an IP flow.
+type FlowDescription string
+
+// Possible values are
+// - DOWNLINK: The corresponding filter applies for traffic to the UE.
+// - UPLINK: The corresponding filter applies for traffic from the UE.
+// - BIDIRECTIONAL: The corresponding filter applies for traffic both to and from the UE.
+// - UNSPECIFIED: The corresponding filter applies for traffic to the UE (downlink), but has no specific direction declared. The service data flow detection shall apply the filter for uplink traffic as if the filter was bidirectional. The PCF shall not use the value UNSPECIFIED in filters created by the network in NW-initiated procedures. The PCF shall only include the value UNSPECIFIED in filters in UE-initiated procedures if the same value is received from the SMF.
+type FlowDirection string
+
+// Common base type for GAD shapes.
+type GADShape struct {
+       // Indicates supported GAD shapes.
+       Shape SupportedGADShapes `json:"shape"`
+}
+
+// Geographic area specified by different shape.
+type GeographicArea interface{}
+
+// Geographical coordinates.
+type GeographicalCoordinates struct {
+       Lat float64 `json:"lat"`
+       Lon float64 `json:"lon"`
+}
+
+// Indicates value of the inner radius.
+type InnerRadius int32
+
+// Range of IPv4 addresses
+type Ipv4AddressRange struct {
+       // String identifying a IPv4 address formatted in the 'dotted decimal' notation as defined in RFC 1166.
+       End *externalRef0.Ipv4Addr `json:"end,omitempty"`
+
+       // String identifying a IPv4 address formatted in the 'dotted decimal' notation as defined in RFC 1166.
+       Start *externalRef0.Ipv4Addr `json:"start,omitempty"`
+}
+
+// Local2dPointUncertaintyEllipse defines model for Local2dPointUncertaintyEllipse.
+type Local2dPointUncertaintyEllipse struct {
+       // Embedded struct due to allOf(#/components/schemas/GADShape)
+       GADShape `yaml:",inline"`
+       // Embedded fields due to inline allOf schema
+       // Indicates value of confidence.
+       Confidence Confidence `json:"confidence"`
+
+       // Indicates a Local origin in a reference system
+       LocalOrigin LocalOrigin `json:"localOrigin"`
+
+       // Relative Cartesian Location
+       Point RelativeCartesianLocation `json:"point"`
+
+       // Ellipse with uncertainty.
+       UncertaintyEllipse UncertaintyEllipse `json:"uncertaintyEllipse"`
+}
+
+// Local3dPointUncertaintyEllipsoid defines model for Local3dPointUncertaintyEllipsoid.
+type Local3dPointUncertaintyEllipsoid struct {
+       // Embedded struct due to allOf(#/components/schemas/GADShape)
+       GADShape `yaml:",inline"`
+       // Embedded fields due to inline allOf schema
+       // Indicates value of confidence.
+       Confidence Confidence `json:"confidence"`
+
+       // Indicates a Local origin in a reference system
+       LocalOrigin LocalOrigin `json:"localOrigin"`
+
+       // Relative Cartesian Location
+       Point RelativeCartesianLocation `json:"point"`
+
+       // Ellipsoid with uncertainty
+       UncertaintyEllipsoid UncertaintyEllipsoid `json:"uncertaintyEllipsoid"`
+}
+
+// Indicates a Local origin in a reference system
+type LocalOrigin struct {
+       CoordinateId *string `json:"coordinateId,omitempty"`
+
+       // Geographical coordinates.
+       Point *GeographicalCoordinates `json:"point,omitempty"`
+}
+
+// Describes a network area information in which the NF service consumer requests the number of UEs.
+type NetworkAreaInfo struct {
+       // Contains a list of E-UTRA cell identities.
+       Ecgis *[]externalRef0.Ecgi `json:"ecgis,omitempty"`
+
+       // Contains a list of NG RAN nodes.
+       GRanNodeIds *[]externalRef0.GlobalRanNodeId `json:"gRanNodeIds,omitempty"`
+
+       // Contains a list of NR cell identities.
+       Ncgis *[]externalRef0.Ncgi `json:"ncgis,omitempty"`
+
+       // Contains a list of tracking area identities.
+       Tais *[]externalRef0.Tai `json:"tais,omitempty"`
+}
+
+// Possible values are:
+// - PERIODIC
+// - ONE_TIME
+// - ON_EVENT_DETECTION
+type NotificationMethod string
+
+// Indicates value of orientation angle.
+type Orientation int
+
+// Point defines model for Point.
+type Point struct {
+       // Embedded struct due to allOf(#/components/schemas/GADShape)
+       GADShape `yaml:",inline"`
+       // Embedded fields due to inline allOf schema
+       // Geographical coordinates.
+       Point GeographicalCoordinates `json:"point"`
+}
+
+// PointAltitude defines model for PointAltitude.
+type PointAltitude struct {
+       // Embedded struct due to allOf(#/components/schemas/GADShape)
+       GADShape `yaml:",inline"`
+       // Embedded fields due to inline allOf schema
+       // Indicates value of altitude.
+       Altitude Altitude `json:"altitude"`
+
+       // Geographical coordinates.
+       Point GeographicalCoordinates `json:"point"`
+}
+
+// PointAltitudeUncertainty defines model for PointAltitudeUncertainty.
+type PointAltitudeUncertainty struct {
+       // Embedded struct due to allOf(#/components/schemas/GADShape)
+       GADShape `yaml:",inline"`
+       // Embedded fields due to inline allOf schema
+       // Indicates value of altitude.
+       Altitude Altitude `json:"altitude"`
+
+       // Indicates value of confidence.
+       Confidence Confidence `json:"confidence"`
+
+       // Geographical coordinates.
+       Point GeographicalCoordinates `json:"point"`
+
+       // Indicates value of uncertainty.
+       UncertaintyAltitude Uncertainty `json:"uncertaintyAltitude"`
+
+       // Ellipse with uncertainty.
+       UncertaintyEllipse UncertaintyEllipse `json:"uncertaintyEllipse"`
+}
+
+// List of points.
+type PointList []GeographicalCoordinates
+
+// PointUncertaintyCircle defines model for PointUncertaintyCircle.
+type PointUncertaintyCircle struct {
+       // Embedded struct due to allOf(#/components/schemas/GADShape)
+       GADShape `yaml:",inline"`
+       // Embedded fields due to inline allOf schema
+       // Geographical coordinates.
+       Point GeographicalCoordinates `json:"point"`
+
+       // Indicates value of uncertainty.
+       Uncertainty Uncertainty `json:"uncertainty"`
+}
+
+// PointUncertaintyEllipse defines model for PointUncertaintyEllipse.
+type PointUncertaintyEllipse struct {
+       // Embedded struct due to allOf(#/components/schemas/GADShape)
+       GADShape `yaml:",inline"`
+       // Embedded fields due to inline allOf schema
+       // Indicates value of confidence.
+       Confidence Confidence `json:"confidence"`
+
+       // Geographical coordinates.
+       Point GeographicalCoordinates `json:"point"`
+
+       // Ellipse with uncertainty.
+       UncertaintyEllipse UncertaintyEllipse `json:"uncertaintyEllipse"`
+}
+
+// Polygon defines model for Polygon.
+type Polygon struct {
+       // Embedded struct due to allOf(#/components/schemas/GADShape)
+       GADShape `yaml:",inline"`
+       // Embedded fields due to inline allOf schema
+       // List of points.
+       PointList PointList `json:"pointList"`
+}
+
+// Relative Cartesian Location
+type RelativeCartesianLocation struct {
+       // string with format 'float' as defined in OpenAPI.
+       X externalRef0.Float `json:"x"`
+
+       // string with format 'float' as defined in OpenAPI.
+       Z *externalRef0.Float `json:"z,omitempty"`
+}
+
+// Represents the type of reporting that the subscription requires.
+type ReportingInformation struct {
+       // indicating a time in seconds.
+       GrpRepTime *externalRef0.DurationSec `json:"grpRepTime,omitempty"`
+       ImmRep     *bool                     `json:"immRep,omitempty"`
+
+       // Unsigned Integer, i.e. only value 0 and integers above 0 are permissible.
+       MaxReportNbr *externalRef0.Uinteger `json:"maxReportNbr,omitempty"`
+
+       // string with format 'date-time' as defined in OpenAPI.
+       MonDur *externalRef0.DateTime `json:"monDur,omitempty"`
+
+       // Possible values are:
+       // - ACTIVATE: The event notification is activated.
+       // - DEACTIVATE: The event notification is deactivated and shall be muted. The available
+       //    event(s) shall be stored.
+       // - RETRIEVAL: The event notification shall be sent to the NF service consumer(s),
+       //   after that, is muted again.
+       NotifFlag *externalRef0.NotificationFlag `json:"notifFlag,omitempty"`
+
+       // Possible values are:
+       // - PERIODIC
+       // - ONE_TIME
+       // - ON_EVENT_DETECTION
+       NotifMethod *NotificationMethod `json:"notifMethod,omitempty"`
+
+       // Criteria for partitioning the UEs before applying the sampling ratio.
+       PartitionCriteria *[]externalRef0.PartitioningCriteria `json:"partitionCriteria,omitempty"`
+
+       // indicating a time in seconds.
+       RepPeriod *externalRef0.DurationSec `json:"repPeriod,omitempty"`
+
+       // Unsigned integer indicating Sampling Ratio (see clauses 4.15.1 of 3GPP TS 23.502), expressed in percent.
+       SampRatio *externalRef0.SamplingRatio `json:"sampRatio,omitempty"`
+}
+
+// Indicates supported GAD shapes.
+type SupportedGADShapes string
+
+// Indicates TSC Traffic pattern.
+type TscaiInputContainer struct {
+       // string with format 'date-time' as defined in OpenAPI.
+       BurstArrivalTime *externalRef0.DateTime `json:"burstArrivalTime,omitempty"`
+
+       // Unsigned Integer, i.e. only value 0 and integers above 0 are permissible.
+       Periodicity *externalRef0.Uinteger `json:"periodicity,omitempty"`
+
+       // Unsigned Integer, i.e. only value 0 and integers above 0 are permissible.
+       SurTimeInNumMsg *externalRef0.Uinteger `json:"surTimeInNumMsg,omitempty"`
+
+       // Unsigned Integer, i.e. only value 0 and integers above 0 are permissible.
+       SurTimeInTime *externalRef0.Uinteger `json:"surTimeInTime,omitempty"`
+}
+
+// Indicates value of uncertainty.
+type Uncertainty float32
+
+// Ellipse with uncertainty.
+type UncertaintyEllipse struct {
+       // Indicates value of orientation angle.
+       OrientationMajor Orientation `json:"orientationMajor"`
+
+       // Indicates value of uncertainty.
+       SemiMajor Uncertainty `json:"semiMajor"`
+
+       // Indicates value of uncertainty.
+       SemiMinor Uncertainty `json:"semiMinor"`
+}
+
+// Ellipsoid with uncertainty
+type UncertaintyEllipsoid struct {
+       // Indicates value of orientation angle.
+       OrientationMajor Orientation `json:"orientationMajor"`
+
+       // Indicates value of uncertainty.
+       SemiMajor Uncertainty `json:"semiMajor"`
+
+       // Indicates value of uncertainty.
+       SemiMinor Uncertainty `json:"semiMinor"`
+
+       // Indicates value of uncertainty.
+       Vertical Uncertainty `json:"vertical"`
+}
+
+// Base64 encoded, gzipped, json marshaled Swagger object
+var swaggerSpec = []string{
+
+       "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",
+}
+
+// GetSwagger returns the content of the embedded swagger specification file
+// or error if failed to decode
+func decodeSpec() ([]byte, error) {
+       zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, ""))
+       if err != nil {
+               return nil, fmt.Errorf("error base64 decoding spec: %s", err)
+       }
+       zr, err := gzip.NewReader(bytes.NewReader(zipped))
+       if err != nil {
+               return nil, fmt.Errorf("error decompressing spec: %s", err)
+       }
+       var buf bytes.Buffer
+       _, err = buf.ReadFrom(zr)
+       if err != nil {
+               return nil, fmt.Errorf("error decompressing spec: %s", err)
+       }
+
+       return buf.Bytes(), nil
+}
+
+var rawSpec = decodeSpecCached()
+
+// a naive cached of a decoded swagger spec
+func decodeSpecCached() func() ([]byte, error) {
+       data, err := decodeSpec()
+       return func() ([]byte, error) {
+               return data, err
+       }
+}
+
+// Constructs a synthetic filesystem for resolving external references when loading openapi specifications.
+func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) {
+       var res = make(map[string]func() ([]byte, error))
+       if len(pathToFile) > 0 {
+               res[pathToFile] = rawSpec
+       }
+
+       pathPrefix := path.Dir(pathToFile)
+
+       for rawPath, rawFunc := range externalRef0.PathToRawSpec(path.Join(pathPrefix, "TS29571_CommonData.yaml")) {
+               if _, ok := res[rawPath]; ok {
+                       // it is not possible to compare functions in golang, so always overwrite the old value
+               }
+               res[rawPath] = rawFunc
+       }
+       return res
+}
+
+// GetSwagger returns the Swagger specification corresponding to the generated code
+// in this file. The external references of Swagger specification are resolved.
+// The logic of resolving external references is tightly connected to "import-mapping" feature.
+// Externally referenced files must be embedded in the corresponding golang packages.
+// Urls can be supported but this task was out of the scope.
+func GetSwagger() (swagger *openapi3.T, err error) {
+       var resolvePath = PathToRawSpec("")
+
+       loader := openapi3.NewLoader()
+       loader.IsExternalRefsAllowed = true
+       loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) {
+               var pathToFile = url.String()
+               pathToFile = path.Clean(pathToFile)
+               getSpec, ok := resolvePath[pathToFile]
+               if !ok {
+                       err1 := fmt.Errorf("path not found: %s", pathToFile)
+                       return nil, err1
+               }
+               return getSpec()
+       }
+       var specData []byte
+       specData, err = rawSpec()
+       if err != nil {
+               return
+       }
+       swagger, err = loader.LoadFromData(specData)
+       if err != nil {
+               return
+       }
+       return
+}
diff --git a/servicemanager/internal/common29122/common29122.gen.go b/servicemanager/internal/common29122/common29122.gen.go
new file mode 100644 (file)
index 0000000..abb1342
--- /dev/null
@@ -0,0 +1,505 @@
+// Package common29122 provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/deepmap/oapi-codegen version v1.10.1 DO NOT EDIT.
+package common29122
+
+import (
+       "bytes"
+       "compress/gzip"
+       "encoding/base64"
+       "fmt"
+       "net/url"
+       "path"
+       "strings"
+       "time"
+
+       "github.com/getkin/kin-openapi/openapi3"
+       externalRef0 "oransc.org/nonrtric/servicemanager/internal/common"
+       externalRef1 "oransc.org/nonrtric/servicemanager/internal/common29571"
+)
+
+// Defines values for Event.
+const (
+       EventFAILEDRESOURCESALLOCATION Event = "FAILED_RESOURCES_ALLOCATION"
+
+       EventLOSSOFBEARER Event = "LOSS_OF_BEARER"
+
+       EventRECOVERYOFBEARER Event = "RECOVERY_OF_BEARER"
+
+       EventRELEASEOFBEARER Event = "RELEASE_OF_BEARER"
+
+       EventSESSIONTERMINATION Event = "SESSION_TERMINATION"
+
+       EventSUCCESSFULRESOURCESALLOCATION Event = "SUCCESSFUL_RESOURCES_ALLOCATION"
+
+       EventUSAGEREPORT Event = "USAGE_REPORT"
+)
+
+// Defines values for ResultReason.
+const (
+       ResultReasonOTHERREASON ResultReason = "OTHER_REASON"
+
+       ResultReasonROAMINGNOTALLOWED ResultReason = "ROAMING_NOT_ALLOWED"
+)
+
+// Represents an accumulated usage.
+type AccumulatedUsage struct {
+       // Unsigned integer identifying a volume in units of bytes.
+       DownlinkVolume *Volume `json:"downlinkVolume,omitempty"`
+
+       // Unsigned integer identifying a period of time in units of seconds.
+       Duration *DurationSec `json:"duration,omitempty"`
+
+       // Unsigned integer identifying a volume in units of bytes.
+       TotalVolume *Volume `json:"totalVolume,omitempty"`
+
+       // Unsigned integer identifying a volume in units of bytes.
+       UplinkVolume *Volume `json:"uplinkVolume,omitempty"`
+}
+
+// Represents a successful acknowledgement of a notification.
+type Acknowledgement struct {
+       // A human-readable explanation specific to this successful acknowledgement
+       Details string `json:"details"`
+}
+
+// integer indicating a bandwidth in bits per second.
+type Bandwidth int
+
+// string identifying a BDT Reference ID as defined in clause 5.3.3 of 3GPP TS 29.154.
+type BdtReferenceId string
+
+// This data type is defined in the same way as the BdtReferenceId data type, but with the nullable property set to true.
+type BdtReferenceIdRm string
+
+// string with format "binary" as defined in OpenAPI Specification.
+type Binary string
+
+// String with format "byte" as defined in OpenAPI Specification, i.e, base64-encoded characters.
+type Bytes string
+
+// Represents one configuration processing result for a group's members.
+type ConfigResult interface{}
+
+// string with format "date-time" as defined in OpenAPI.
+type DateTime time.Time
+
+// string with format "date-time" as defined in OpenAPI with "nullable=true" property.
+type DateTimeRm time.Time
+
+// string with format "date-time" as defined in OpenAPI with "readOnly=true" property.
+type DateTimeRo time.Time
+
+// integer between and including 1 and 7 denoting a weekday. 1 shall indicate Monday, and the subsequent weekdays shall be indicated with the next higher numbers. 7 shall indicate Sunday.
+type DayOfWeek int
+
+// Unsigned integer identifying a period of time in units of minutes.
+type DurationMin int32
+
+// Unsigned integer identifying a period of time in units of seconds.
+type DurationSec int
+
+// Unsigned integer identifying a period of time in units of seconds with "nullable=true" property.
+type DurationSecRm int
+
+// Unsigned integer identifying a period of time in units of seconds with "readOnly=true" property.
+type DurationSecRo int
+
+// Represents Ethernet flow information.
+type EthFlowInfo struct {
+       // Indicates the packet filters of the Ethernet flow. It shall contain UL and/or DL Ethernet flow description.
+       EthFlowDescriptions *[]externalRef0.EthFlowDescription `json:"ethFlowDescriptions,omitempty"`
+
+       // Indicates the Ethernet flow identifier.
+       FlowId int `json:"flowId"`
+}
+
+// Possible values are - SESSION_TERMINATION: Indicates that Rx session is terminated. - LOSS_OF_BEARER : Indicates a loss of a bearer. - RECOVERY_OF_BEARER: Indicates a recovery of a bearer. - RELEASE_OF_BEARER: Indicates a release of a bearer. - USAGE_REPORT: Indicates the usage report event.  - FAILED_RESOURCES_ALLOCATION: Indicates the resource allocation is failed. - SUCCESSFUL_RESOURCES_ALLOCATION: Indicates the resource allocation is successful.
+type Event string
+
+// Represents an event report.
+type EventReport struct {
+       // Represents an accumulated usage.
+       AccumulatedUsage *AccumulatedUsage `json:"accumulatedUsage,omitempty"`
+
+       // Possible values are - SESSION_TERMINATION: Indicates that Rx session is terminated. - LOSS_OF_BEARER : Indicates a loss of a bearer. - RECOVERY_OF_BEARER: Indicates a recovery of a bearer. - RELEASE_OF_BEARER: Indicates a release of a bearer. - USAGE_REPORT: Indicates the usage report event.  - FAILED_RESOURCES_ALLOCATION: Indicates the resource allocation is failed. - SUCCESSFUL_RESOURCES_ALLOCATION: Indicates the resource allocation is successful.
+       Event Event `json:"event"`
+
+       // Identifies the IP flows that were sent during event subscription
+       FlowIds *[]int `json:"flowIds,omitempty"`
+}
+
+// string containing a local identifier followed by "@" and a domain identifier. Both the local identifier and the domain identifier shall be encoded as strings that do not contain any "@" characters. See Clauses 4.6.2 and 4.6.3 of 3GPP TS 23.682 for more information.
+type ExternalGroupId string
+
+// string containing a local identifier followed by "@" and a domain identifier. Both the local identifier and the domain identifier shall be encoded as strings that do not contain any "@" characters. See Clause 4.6.2 of 3GPP TS 23.682 for more information.
+type ExternalId string
+
+// Represents IP flow information.
+type FlowInfo struct {
+       // Indicates the packet filters of the IP flow. Refer to clause 5.3.8 of 3GPP TS 29.214 for encoding. It shall contain UL and/or DL IP flow description.
+       FlowDescriptions *[]string `json:"flowDescriptions,omitempty"`
+
+       // Indicates the IP flow identifier.
+       FlowId int `json:"flowId"`
+}
+
+// Represents the description of invalid parameters, for a request rejected due to invalid parameters.
+type InvalidParam struct {
+       // Attribute's name encoded as a JSON Pointer, or header's name.
+       Param string `json:"param"`
+
+       // A human-readable reason, e.g. "must be a positive integer".
+       Reason *string `json:"reason,omitempty"`
+}
+
+// string identifying a Ipv4 address formatted in the "dotted decimal" notation as defined in IETF RFC 1166.
+type Ipv4Addr string
+
+// string identifying a Ipv4 address formatted in the "dotted decimal" notation as defined in IETF RFC 1166, with "readOnly=true" property.
+type Ipv4AddrRo string
+
+// string identifying a Ipv6 address formatted according to clause 4 in IETF RFC 5952. The mixed Ipv4 Ipv6 notation according to clause 5 of IETF RFC 5952 shall not be used.
+type Ipv6Addr string
+
+// string identifying a Ipv6 address formatted according to clause 4 in IETF RFC 5952, with "readOnly=true" property. The mixed Ipv4 Ipv6 notation according to clause 5 of IETF RFC 5952 shall not be used.
+type Ipv6AddrRo string
+
+// string formatted according to IETF RFC 3986 identifying a referenced resource.
+type Link string
+
+// String formatted according to IETF RFC 3986 identifying a referenced resource, but with the nullable property set to true.
+type LinkRm string
+
+// Represents a user location area.
+type LocationArea struct {
+       // Indicates a list of Cell Global Identities of the user which identifies the cell the UE is registered.
+       CellIds *[]string `json:"cellIds,omitempty"`
+
+       // Identifies a list of civic addresses of the user where the UE is located.
+       CivicAddresses *[]externalRef0.CivicAddress `json:"civicAddresses,omitempty"`
+
+       // Indicates a list of eNodeB identities in which the UE is currently located.
+       EnodeBIds *[]string `json:"enodeBIds,omitempty"`
+
+       // Identifies a list of geographic area of the user where the UE is located.
+       GeographicAreas *[]externalRef0.GeographicArea `json:"geographicAreas,omitempty"`
+
+       // Identifies a list of Routing Area Identities of the user where the UE is located.
+       RoutingAreaIds *[]string `json:"routingAreaIds,omitempty"`
+
+       // Identifies a list of Tracking Area Identities of the user where the UE is located.
+       TrackingAreaIds *[]string `json:"trackingAreaIds,omitempty"`
+}
+
+// Represents a user location area when the UE is attached to 5G.
+type LocationArea5G struct {
+       // Identifies a list of civic addresses of the user where the UE is located.
+       CivicAddresses *[]externalRef0.CivicAddress `json:"civicAddresses,omitempty"`
+
+       // Identifies a list of geographic area of the user where the UE is located.
+       GeographicAreas *[]externalRef0.GeographicArea `json:"geographicAreas,omitempty"`
+
+       // Describes a network area information in which the NF service consumer requests the number of UEs.
+       NwAreaInfo *externalRef0.NetworkAreaInfo `json:"nwAreaInfo,omitempty"`
+}
+
+// String encoding a Mobile Country Code part of the PLMN, comprising 3 digits, as defined in 3GPP TS 38.413.
+type Mcc string
+
+// String encoding a Mobile Network Code part of the PLMN, comprising 2 or 3 digits, as defined in 3GPP TS 38.413.
+type Mnc string
+
+// string formatted according to clause 3.3 of 3GPP TS 23.003 that describes an MSISDN.
+type Msisdn string
+
+// Represents the information to be conveyed in a bearer level event(s) notification.
+type NotificationData struct {
+       // Contains the reported event and applicable information
+       EventReports []EventReport `json:"eventReports"`
+
+       // string formatted according to IETF RFC 3986 identifying a referenced resource.
+       Transaction Link `json:"transaction"`
+}
+
+// Represents the identifier of a PLMN.
+type PlmnId struct {
+       // String encoding a Mobile Country Code part of the PLMN, comprising 3 digits, as defined in 3GPP TS 38.413.
+       Mcc Mcc `json:"mcc"`
+
+       // String encoding a Mobile Network Code part of the PLMN, comprising 2 or 3 digits, as defined in 3GPP TS 38.413.
+       Mnc Mnc `json:"mnc"`
+}
+
+// Unsigned integer with valid values between 0 and 65535.
+type Port int
+
+// Unsigned integer with valid values between 0 and 65535, with "readOnly=true" property.
+type PortRo int
+
+// Represents additional information and details on an error response.
+type ProblemDetails struct {
+       // A machine-readable application error cause specific to this occurrence of the problem. This IE should be present and provide application-related error information, if available.
+       Cause *string `json:"cause,omitempty"`
+
+       // A human-readable explanation specific to this occurrence of the problem.
+       Detail *string `json:"detail,omitempty"`
+
+       // string providing an URI formatted according to IETF RFC 3986.
+       Instance *Uri `json:"instance,omitempty"`
+
+       // Description of invalid parameters, for a request rejected due to invalid parameters.
+       InvalidParams *[]InvalidParam `json:"invalidParams,omitempty"`
+
+       // The HTTP status code for this occurrence of the problem.
+       Status *int `json:"status,omitempty"`
+
+       // A string used to indicate the features supported by an API that is used as defined in clause  6.6 in 3GPP TS 29.500. The string shall contain a bitmask indicating supported features in  hexadecimal representation Each character in the string shall take a value of "0" to "9",  "a" to "f" or "A" to "F" and shall represent the support of 4 features as described in  table 5.2.2-3. The most significant character representing the highest-numbered features shall  appear first in the string, and the character representing features 1 to 4 shall appear last  in the string. The list of features and their numbering (starting with 1) are defined  separately for each API. If the string contains a lower number of characters than there are  defined features for an API, all features that would be represented by characters that are not  present in the string are not supported.
+       SupportedFeatures *externalRef1.SupportedFeatures `json:"supportedFeatures,omitempty"`
+
+       // A short, human-readable summary of the problem type. It should not change from occurrence to occurrence of the problem.
+       Title *string `json:"title,omitempty"`
+
+       // string providing an URI formatted according to IETF RFC 3986.
+       Type *Uri `json:"type,omitempty"`
+}
+
+// string chosen by the SCEF to serve as identifier in a resource URI.
+type ResourceId string
+
+// Possible values are - ROAMING_NOT_ALLOWED: Identifies the configuration parameters are not allowed by roaming agreement. - OTHER_REASON: Identifies the configuration parameters are not configured due to other reason.
+type ResultReason string
+
+// string that identifies an SCS/AS.
+type ScsAsId string
+
+// Represents a sponsor information.
+type SponsorInformation struct {
+       // It indicates Application Service Provider ID.
+       AspId string `json:"aspId"`
+
+       // It indicates Sponsor ID.
+       SponsorId string `json:"sponsorId"`
+}
+
+// Represents a notification that can be sent to test whether a chosen notification mechanism works.
+type TestNotification struct {
+       // string formatted according to IETF RFC 3986 identifying a referenced resource.
+       Subscription Link `json:"subscription"`
+}
+
+// String with format partial-time or full-time as defined in clause 5.6 of IETF RFC 3339. Examples, 20:15:00, 20:15:00-08:00 (for 8 hours behind UTC).
+type TimeOfDay string
+
+// Represents a time window identified by a start time and a stop time.
+type TimeWindow struct {
+       // string with format "date-time" as defined in OpenAPI.
+       StartTime DateTime `json:"startTime"`
+
+       // string with format "date-time" as defined in OpenAPI.
+       StopTime DateTime `json:"stopTime"`
+}
+
+// string providing an URI formatted according to IETF RFC 3986.
+type Uri string
+
+// Represents a usage threshold.
+type UsageThreshold struct {
+       // Unsigned integer identifying a volume in units of bytes.
+       DownlinkVolume *Volume `json:"downlinkVolume,omitempty"`
+
+       // Unsigned integer identifying a period of time in units of seconds.
+       Duration *DurationSec `json:"duration,omitempty"`
+
+       // Unsigned integer identifying a volume in units of bytes.
+       TotalVolume *Volume `json:"totalVolume,omitempty"`
+
+       // Unsigned integer identifying a volume in units of bytes.
+       UplinkVolume *Volume `json:"uplinkVolume,omitempty"`
+}
+
+// Represents the same as the UsageThreshold data type but with the nullable:true property.
+type UsageThresholdRm struct {
+       // Unsigned integer identifying a volume in units of bytes with "nullable=true" property.
+       DownlinkVolume *VolumeRm `json:"downlinkVolume"`
+
+       // Unsigned integer identifying a period of time in units of seconds with "nullable=true" property.
+       Duration *DurationSecRm `json:"duration"`
+
+       // Unsigned integer identifying a volume in units of bytes with "nullable=true" property.
+       TotalVolume *VolumeRm `json:"totalVolume"`
+
+       // Unsigned integer identifying a volume in units of bytes with "nullable=true" property.
+       UplinkVolume *VolumeRm `json:"uplinkVolume"`
+}
+
+// Unsigned integer identifying a volume in units of bytes.
+type Volume int64
+
+// Unsigned integer identifying a volume in units of bytes with "nullable=true" property.
+type VolumeRm int64
+
+// Represents the configuration information for the delivery of notifications over Websockets.
+type WebsockNotifConfig struct {
+       // Set by the SCS/AS to indicate that the Websocket delivery is requested.
+       RequestWebsocketUri *bool `json:"requestWebsocketUri,omitempty"`
+
+       // string formatted according to IETF RFC 3986 identifying a referenced resource.
+       WebsocketUri *Link `json:"websocketUri,omitempty"`
+}
+
+// Base64 encoded, gzipped, json marshaled Swagger object
+var swaggerSpec = []string{
+
+       "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",
+}
+
+// GetSwagger returns the content of the embedded swagger specification file
+// or error if failed to decode
+func decodeSpec() ([]byte, error) {
+       zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, ""))
+       if err != nil {
+               return nil, fmt.Errorf("error base64 decoding spec: %s", err)
+       }
+       zr, err := gzip.NewReader(bytes.NewReader(zipped))
+       if err != nil {
+               return nil, fmt.Errorf("error decompressing spec: %s", err)
+       }
+       var buf bytes.Buffer
+       _, err = buf.ReadFrom(zr)
+       if err != nil {
+               return nil, fmt.Errorf("error decompressing spec: %s", err)
+       }
+
+       return buf.Bytes(), nil
+}
+
+var rawSpec = decodeSpecCached()
+
+// a naive cached of a decoded swagger spec
+func decodeSpecCached() func() ([]byte, error) {
+       data, err := decodeSpec()
+       return func() ([]byte, error) {
+               return data, err
+       }
+}
+
+// Constructs a synthetic filesystem for resolving external references when loading openapi specifications.
+func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) {
+       var res = make(map[string]func() ([]byte, error))
+       if len(pathToFile) > 0 {
+               res[pathToFile] = rawSpec
+       }
+
+       pathPrefix := path.Dir(pathToFile)
+
+       for rawPath, rawFunc := range externalRef0.PathToRawSpec(path.Join(pathPrefix, "CommonData.yaml")) {
+               if _, ok := res[rawPath]; ok {
+                       // it is not possible to compare functions in golang, so always overwrite the old value
+               }
+               res[rawPath] = rawFunc
+       }
+       for rawPath, rawFunc := range externalRef1.PathToRawSpec(path.Join(pathPrefix, "TS29571_CommonData.yaml")) {
+               if _, ok := res[rawPath]; ok {
+                       // it is not possible to compare functions in golang, so always overwrite the old value
+               }
+               res[rawPath] = rawFunc
+       }
+       return res
+}
+
+// GetSwagger returns the Swagger specification corresponding to the generated code
+// in this file. The external references of Swagger specification are resolved.
+// The logic of resolving external references is tightly connected to "import-mapping" feature.
+// Externally referenced files must be embedded in the corresponding golang packages.
+// Urls can be supported but this task was out of the scope.
+func GetSwagger() (swagger *openapi3.T, err error) {
+       var resolvePath = PathToRawSpec("")
+
+       loader := openapi3.NewLoader()
+       loader.IsExternalRefsAllowed = true
+       loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) {
+               var pathToFile = url.String()
+               pathToFile = path.Clean(pathToFile)
+               getSpec, ok := resolvePath[pathToFile]
+               if !ok {
+                       err1 := fmt.Errorf("path not found: %s", pathToFile)
+                       return nil, err1
+               }
+               return getSpec()
+       }
+       var specData []byte
+       specData, err = rawSpec()
+       if err != nil {
+               return
+       }
+       swagger, err = loader.LoadFromData(specData)
+       if err != nil {
+               return
+       }
+       return
+}
diff --git a/servicemanager/internal/common29571/common29571.gen.go b/servicemanager/internal/common29571/common29571.gen.go
new file mode 100644 (file)
index 0000000..96a9c13
--- /dev/null
@@ -0,0 +1,3524 @@
+// Package common29571 provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/deepmap/oapi-codegen version v1.10.1 DO NOT EDIT.
+package common29571
+
+import (
+       "bytes"
+       "compress/gzip"
+       "encoding/base64"
+       "encoding/json"
+       "fmt"
+       "net/url"
+       "path"
+       "strings"
+       "time"
+
+       openapi_types "github.com/deepmap/oapi-codegen/pkg/types"
+       "github.com/getkin/kin-openapi/openapi3"
+)
+
+// Defines values for AccessType.
+const (
+       AccessTypeN3GPPACCESS AccessType = "3GPP_ACCESS"
+
+       AccessTypeNON3GPPACCESS AccessType = "NON_3GPP_ACCESS"
+)
+
+// Defines values for AuthStatus.
+const (
+       AuthStatusEAPFAILURE AuthStatus = "EAP_FAILURE"
+
+       AuthStatusEAPSUCCESS AuthStatus = "EAP_SUCCESS"
+
+       AuthStatusPENDING AuthStatus = "PENDING"
+)
+
+// Defines values for BroadcastDeliveryStatus.
+const (
+       BroadcastDeliveryStatusACTIVATED BroadcastDeliveryStatus = "ACTIVATED"
+
+       BroadcastDeliveryStatusTERMINATED BroadcastDeliveryStatus = "TERMINATED"
+)
+
+// Defines values for ChangeType.
+const (
+       ChangeTypeADD ChangeType = "ADD"
+
+       ChangeTypeMOVE ChangeType = "MOVE"
+
+       ChangeTypeREMOVE ChangeType = "REMOVE"
+
+       ChangeTypeREPLACE ChangeType = "REPLACE"
+)
+
+// Defines values for CollectionPeriodRmmLteMdt.
+const (
+       CollectionPeriodRmmLteMdtN1024 CollectionPeriodRmmLteMdt = "1024"
+
+       CollectionPeriodRmmLteMdtN10240 CollectionPeriodRmmLteMdt = "10240"
+
+       CollectionPeriodRmmLteMdtN1280 CollectionPeriodRmmLteMdt = "1280"
+
+       CollectionPeriodRmmLteMdtN2048 CollectionPeriodRmmLteMdt = "2048"
+
+       CollectionPeriodRmmLteMdtN2560 CollectionPeriodRmmLteMdt = "2560"
+
+       CollectionPeriodRmmLteMdtN5120 CollectionPeriodRmmLteMdt = "5120"
+
+       CollectionPeriodRmmLteMdtN60000 CollectionPeriodRmmLteMdt = "60000"
+)
+
+// Defines values for CollectionPeriodRmmNrMdt.
+const (
+       CollectionPeriodRmmNrMdtN1024 CollectionPeriodRmmNrMdt = "1024"
+
+       CollectionPeriodRmmNrMdtN10240 CollectionPeriodRmmNrMdt = "10240"
+
+       CollectionPeriodRmmNrMdtN2048 CollectionPeriodRmmNrMdt = "2048"
+
+       CollectionPeriodRmmNrMdtN5120 CollectionPeriodRmmNrMdt = "5120"
+
+       CollectionPeriodRmmNrMdtN60000 CollectionPeriodRmmNrMdt = "60000"
+)
+
+// Defines values for CoreNetworkType.
+const (
+       CoreNetworkTypeEPC CoreNetworkType = "EPC"
+
+       CoreNetworkTypeN5GC CoreNetworkType = "5GC"
+)
+
+// Defines values for DlDataDeliveryStatus.
+const (
+       DlDataDeliveryStatusBUFFERED DlDataDeliveryStatus = "BUFFERED"
+
+       DlDataDeliveryStatusDISCARDED DlDataDeliveryStatus = "DISCARDED"
+
+       DlDataDeliveryStatusTRANSMITTED DlDataDeliveryStatus = "TRANSMITTED"
+)
+
+// Defines values for DnaiChangeType.
+const (
+       DnaiChangeTypeEARLY DnaiChangeType = "EARLY"
+
+       DnaiChangeTypeEARLYLATE DnaiChangeType = "EARLY_LATE"
+
+       DnaiChangeTypeLATE DnaiChangeType = "LATE"
+)
+
+// Defines values for EventForMdt.
+const (
+       EventForMdtA2EVENT EventForMdt = "A2_EVENT"
+
+       EventForMdtOUTOFCOVERAG EventForMdt = "OUT_OF_COVERAG"
+)
+
+// Defines values for HttpMethod.
+const (
+       HttpMethodCONNECT HttpMethod = "CONNECT"
+
+       HttpMethodDELETE HttpMethod = "DELETE"
+
+       HttpMethodGET HttpMethod = "GET"
+
+       HttpMethodHEAD HttpMethod = "HEAD"
+
+       HttpMethodOPTIONS HttpMethod = "OPTIONS"
+
+       HttpMethodPATCH HttpMethod = "PATCH"
+
+       HttpMethodPOST HttpMethod = "POST"
+
+       HttpMethodPUT HttpMethod = "PUT"
+
+       HttpMethodTRACE HttpMethod = "TRACE"
+)
+
+// Defines values for JobType.
+const (
+       JobTypeIMMEDIATEMDTANDTRACE JobType = "IMMEDIATE_MDT_AND_TRACE"
+
+       JobTypeIMMEDIATEMDTONLY JobType = "IMMEDIATE_MDT_ONLY"
+
+       JobTypeLOGGEDMBSFNMDT JobType = "LOGGED_MBSFN_MDT"
+
+       JobTypeLOGGEDMDTONLY JobType = "LOGGED_MDT_ONLY"
+
+       JobTypeRCEFREPORTSONLY JobType = "RCEF_REPORTS_ONLY"
+
+       JobTypeRLFREPORTSONLY JobType = "RLF_REPORTS_ONLY"
+
+       JobTypeTRACEONLY JobType = "TRACE_ONLY"
+)
+
+// Defines values for LcsServiceAuth.
+const (
+       LcsServiceAuthLOCATIONALLOWEDWITHNOTIFICATION LcsServiceAuth = "LOCATION_ALLOWED_WITH_NOTIFICATION"
+
+       LcsServiceAuthLOCATIONALLOWEDWITHOUTNOTIFICATION LcsServiceAuth = "LOCATION_ALLOWED_WITHOUT_NOTIFICATION"
+
+       LcsServiceAuthLOCATIONALLOWEDWITHOUTRESPONSE LcsServiceAuth = "LOCATION_ALLOWED_WITHOUT_RESPONSE"
+
+       LcsServiceAuthLOCATIONRESTRICTEDWITHOUTRESPONSE LcsServiceAuth = "LOCATION_RESTRICTED_WITHOUT_RESPONSE"
+
+       LcsServiceAuthNOTIFICATIONANDVERIFICATIONONLY LcsServiceAuth = "NOTIFICATION_AND_VERIFICATION_ONLY"
+
+       LcsServiceAuthNOTIFICATIONONLY LcsServiceAuth = "NOTIFICATION_ONLY"
+)
+
+// Defines values for LineType.
+const (
+       LineTypeDSL LineType = "DSL"
+
+       LineTypePON LineType = "PON"
+)
+
+// Defines values for LoggingDurationMdt.
+const (
+       LoggingDurationMdtN1200 LoggingDurationMdt = "1200"
+
+       LoggingDurationMdtN2400 LoggingDurationMdt = "2400"
+
+       LoggingDurationMdtN3600 LoggingDurationMdt = "3600"
+
+       LoggingDurationMdtN5400 LoggingDurationMdt = "5400"
+
+       LoggingDurationMdtN600 LoggingDurationMdt = "600"
+
+       LoggingDurationMdtN7200 LoggingDurationMdt = "7200"
+)
+
+// Defines values for LoggingDurationNrMdt.
+const (
+       LoggingDurationNrMdtN1200 LoggingDurationNrMdt = "1200"
+
+       LoggingDurationNrMdtN2400 LoggingDurationNrMdt = "2400"
+
+       LoggingDurationNrMdtN3600 LoggingDurationNrMdt = "3600"
+
+       LoggingDurationNrMdtN5400 LoggingDurationNrMdt = "5400"
+
+       LoggingDurationNrMdtN600 LoggingDurationNrMdt = "600"
+
+       LoggingDurationNrMdtN7200 LoggingDurationNrMdt = "7200"
+)
+
+// Defines values for LoggingIntervalMdt.
+const (
+       LoggingIntervalMdtN1024 LoggingIntervalMdt = "1024"
+
+       LoggingIntervalMdtN128 LoggingIntervalMdt = "128"
+
+       LoggingIntervalMdtN2048 LoggingIntervalMdt = "2048"
+
+       LoggingIntervalMdtN256 LoggingIntervalMdt = "256"
+
+       LoggingIntervalMdtN3072 LoggingIntervalMdt = "3072"
+
+       LoggingIntervalMdtN4096 LoggingIntervalMdt = "4096"
+
+       LoggingIntervalMdtN512 LoggingIntervalMdt = "512"
+
+       LoggingIntervalMdtN6144 LoggingIntervalMdt = "6144"
+)
+
+// Defines values for LoggingIntervalNrMdt.
+const (
+       LoggingIntervalNrMdtInfinity LoggingIntervalNrMdt = "infinity"
+
+       LoggingIntervalNrMdtN1024 LoggingIntervalNrMdt = "1024"
+
+       LoggingIntervalNrMdtN128 LoggingIntervalNrMdt = "128"
+
+       LoggingIntervalNrMdtN2048 LoggingIntervalNrMdt = "2048"
+
+       LoggingIntervalNrMdtN256 LoggingIntervalNrMdt = "256"
+
+       LoggingIntervalNrMdtN3072 LoggingIntervalNrMdt = "3072"
+
+       LoggingIntervalNrMdtN320 LoggingIntervalNrMdt = "320"
+
+       LoggingIntervalNrMdtN4096 LoggingIntervalNrMdt = "4096"
+
+       LoggingIntervalNrMdtN512 LoggingIntervalNrMdt = "512"
+
+       LoggingIntervalNrMdtN6144 LoggingIntervalNrMdt = "6144"
+
+       LoggingIntervalNrMdtN640 LoggingIntervalNrMdt = "640"
+)
+
+// Defines values for MatchingOperator.
+const (
+       MatchingOperatorCONTAINS MatchingOperator = "CONTAINS"
+
+       MatchingOperatorENDSWITH MatchingOperator = "ENDS_WITH"
+
+       MatchingOperatorFULLMATCH MatchingOperator = "FULL_MATCH"
+
+       MatchingOperatorMATCHALL MatchingOperator = "MATCH_ALL"
+
+       MatchingOperatorNOTCONTAIN MatchingOperator = "NOT_CONTAIN"
+
+       MatchingOperatorNOTENDWITH MatchingOperator = "NOT_END_WITH"
+
+       MatchingOperatorNOTSTARTWITH MatchingOperator = "NOT_START_WITH"
+
+       MatchingOperatorSTARTSWITH MatchingOperator = "STARTS_WITH"
+)
+
+// Defines values for MbsServiceType.
+const (
+       MbsServiceTypeBROADCAST MbsServiceType = "BROADCAST"
+
+       MbsServiceTypeMULTICAST MbsServiceType = "MULTICAST"
+)
+
+// Defines values for MeasurementLteForMdt.
+const (
+       MeasurementLteForMdtM1 MeasurementLteForMdt = "M1"
+
+       MeasurementLteForMdtM2 MeasurementLteForMdt = "M2"
+
+       MeasurementLteForMdtM3 MeasurementLteForMdt = "M3"
+
+       MeasurementLteForMdtM4DL MeasurementLteForMdt = "M4_DL"
+
+       MeasurementLteForMdtM4UL MeasurementLteForMdt = "M4_UL"
+
+       MeasurementLteForMdtM5DL MeasurementLteForMdt = "M5_DL"
+
+       MeasurementLteForMdtM5UL MeasurementLteForMdt = "M5_UL"
+
+       MeasurementLteForMdtM6DL MeasurementLteForMdt = "M6_DL"
+
+       MeasurementLteForMdtM6UL MeasurementLteForMdt = "M6_UL"
+
+       MeasurementLteForMdtM7DL MeasurementLteForMdt = "M7_DL"
+
+       MeasurementLteForMdtM7UL MeasurementLteForMdt = "M7_UL"
+
+       MeasurementLteForMdtM8 MeasurementLteForMdt = "M8"
+
+       MeasurementLteForMdtM9 MeasurementLteForMdt = "M9"
+)
+
+// Defines values for MeasurementNrForMdt.
+const (
+       MeasurementNrForMdtM1 MeasurementNrForMdt = "M1"
+
+       MeasurementNrForMdtM2 MeasurementNrForMdt = "M2"
+
+       MeasurementNrForMdtM3 MeasurementNrForMdt = "M3"
+
+       MeasurementNrForMdtM4DL MeasurementNrForMdt = "M4_DL"
+
+       MeasurementNrForMdtM4UL MeasurementNrForMdt = "M4_UL"
+
+       MeasurementNrForMdtM5DL MeasurementNrForMdt = "M5_DL"
+
+       MeasurementNrForMdtM5UL MeasurementNrForMdt = "M5_UL"
+
+       MeasurementNrForMdtM6DL MeasurementNrForMdt = "M6_DL"
+
+       MeasurementNrForMdtM6UL MeasurementNrForMdt = "M6_UL"
+
+       MeasurementNrForMdtM7DL MeasurementNrForMdt = "M7_DL"
+
+       MeasurementNrForMdtM7UL MeasurementNrForMdt = "M7_UL"
+
+       MeasurementNrForMdtM8 MeasurementNrForMdt = "M8"
+
+       MeasurementNrForMdtM9 MeasurementNrForMdt = "M9"
+)
+
+// Defines values for MeasurementPeriodLteMdt.
+const (
+       MeasurementPeriodLteMdtN1024 MeasurementPeriodLteMdt = "1024"
+
+       MeasurementPeriodLteMdtN10240 MeasurementPeriodLteMdt = "10240"
+
+       MeasurementPeriodLteMdtN1280 MeasurementPeriodLteMdt = "1280"
+
+       MeasurementPeriodLteMdtN2048 MeasurementPeriodLteMdt = "2048"
+
+       MeasurementPeriodLteMdtN2560 MeasurementPeriodLteMdt = "2560"
+
+       MeasurementPeriodLteMdtN5120 MeasurementPeriodLteMdt = "5120"
+
+       MeasurementPeriodLteMdtN60000 MeasurementPeriodLteMdt = "60000"
+)
+
+// Defines values for NotificationControl.
+const (
+       NotificationControlNOTREQUESTED NotificationControl = "NOT_REQUESTED"
+
+       NotificationControlREQUESTED NotificationControl = "REQUESTED"
+)
+
+// Defines values for NotificationFlag.
+const (
+       NotificationFlagACTIVATE NotificationFlag = "ACTIVATE"
+
+       NotificationFlagDEACTIVATE NotificationFlag = "DEACTIVATE"
+
+       NotificationFlagRETRIEVAL NotificationFlag = "RETRIEVAL"
+)
+
+// Defines values for PartitioningCriteria.
+const (
+       PartitioningCriteriaDNN PartitioningCriteria = "DNN"
+
+       PartitioningCriteriaGEOAREA PartitioningCriteria = "GEOAREA"
+
+       PartitioningCriteriaSNSSAI PartitioningCriteria = "SNSSAI"
+
+       PartitioningCriteriaSUBPLMN PartitioningCriteria = "SUBPLMN"
+
+       PartitioningCriteriaTAC PartitioningCriteria = "TAC"
+)
+
+// Defines values for PatchOperation.
+const (
+       PatchOperationAdd PatchOperation = "add"
+
+       PatchOperationCopy PatchOperation = "copy"
+
+       PatchOperationMove PatchOperation = "move"
+
+       PatchOperationRemove PatchOperation = "remove"
+
+       PatchOperationReplace PatchOperation = "replace"
+
+       PatchOperationTest PatchOperation = "test"
+)
+
+// Defines values for PduSessionType.
+const (
+       PduSessionTypeETHERNET PduSessionType = "ETHERNET"
+
+       PduSessionTypeIPV4 PduSessionType = "IPV4"
+
+       PduSessionTypeIPV4V6 PduSessionType = "IPV4V6"
+
+       PduSessionTypeIPV6 PduSessionType = "IPV6"
+
+       PduSessionTypeUNSTRUCTURED PduSessionType = "UNSTRUCTURED"
+)
+
+// Defines values for PositioningMethodMdt.
+const (
+       PositioningMethodMdtECELLID PositioningMethodMdt = "E_CELL_ID"
+
+       PositioningMethodMdtGNSS PositioningMethodMdt = "GNSS"
+)
+
+// Defines values for PreemptionCapability.
+const (
+       PreemptionCapabilityMAYPREEMPT PreemptionCapability = "MAY_PREEMPT"
+
+       PreemptionCapabilityNOTPREEMPT PreemptionCapability = "NOT_PREEMPT"
+)
+
+// Defines values for PreemptionVulnerability.
+const (
+       PreemptionVulnerabilityNOTPREEMPTABLE PreemptionVulnerability = "NOT_PREEMPTABLE"
+
+       PreemptionVulnerabilityPREEMPTABLE PreemptionVulnerability = "PREEMPTABLE"
+)
+
+// Defines values for PresenceState.
+const (
+       PresenceStateINACTIVE PresenceState = "INACTIVE"
+
+       PresenceStateINAREA PresenceState = "IN_AREA"
+
+       PresenceStateOUTOFAREA PresenceState = "OUT_OF_AREA"
+
+       PresenceStateUNKNOWN PresenceState = "UNKNOWN"
+)
+
+// Defines values for QosResourceType.
+const (
+       QosResourceTypeCRITICALGBR QosResourceType = "CRITICAL_GBR"
+
+       QosResourceTypeNONCRITICALGBR QosResourceType = "NON_CRITICAL_GBR"
+
+       QosResourceTypeNONGBR QosResourceType = "NON_GBR"
+)
+
+// Defines values for RatType.
+const (
+       RatTypeEUTRA RatType = "EUTRA"
+
+       RatTypeEUTRAU RatType = "EUTRA_U"
+
+       RatTypeGERA RatType = "GERA"
+
+       RatTypeLTEM RatType = "LTE-M"
+
+       RatTypeNBIOT RatType = "NBIOT"
+
+       RatTypeNR RatType = "NR"
+
+       RatTypeNRGEO RatType = "NR_GEO"
+
+       RatTypeNRLEO RatType = "NR_LEO"
+
+       RatTypeNRMEO RatType = "NR_MEO"
+
+       RatTypeNROTHERSAT RatType = "NR_OTHER_SAT"
+
+       RatTypeNRREDCAP RatType = "NR_REDCAP"
+
+       RatTypeNRU RatType = "NR_U"
+
+       RatTypeTRUSTEDN3GA RatType = "TRUSTED_N3GA"
+
+       RatTypeTRUSTEDWLAN RatType = "TRUSTED_WLAN"
+
+       RatTypeUTRA RatType = "UTRA"
+
+       RatTypeVIRTUAL RatType = "VIRTUAL"
+
+       RatTypeWIRELINE RatType = "WIRELINE"
+
+       RatTypeWIRELINEBBF RatType = "WIRELINE_BBF"
+
+       RatTypeWIRELINECABLE RatType = "WIRELINE_CABLE"
+
+       RatTypeWLAN RatType = "WLAN"
+)
+
+// Defines values for ReflectiveQoSAttribute.
+const (
+       ReflectiveQoSAttributeNORQOS ReflectiveQoSAttribute = "NO_RQOS"
+
+       ReflectiveQoSAttributeRQOS ReflectiveQoSAttribute = "RQOS"
+)
+
+// Defines values for ReportAmountMdt.
+const (
+       ReportAmountMdtInfinity ReportAmountMdt = "infinity"
+
+       ReportAmountMdtN1 ReportAmountMdt = "1"
+
+       ReportAmountMdtN16 ReportAmountMdt = "16"
+
+       ReportAmountMdtN2 ReportAmountMdt = "2"
+
+       ReportAmountMdtN32 ReportAmountMdt = "32"
+
+       ReportAmountMdtN4 ReportAmountMdt = "4"
+
+       ReportAmountMdtN64 ReportAmountMdt = "64"
+
+       ReportAmountMdtN8 ReportAmountMdt = "8"
+)
+
+// Defines values for ReportIntervalMdt.
+const (
+       ReportIntervalMdtN1024 ReportIntervalMdt = "1024"
+
+       ReportIntervalMdtN10240 ReportIntervalMdt = "10240"
+
+       ReportIntervalMdtN120 ReportIntervalMdt = "120"
+
+       ReportIntervalMdtN1800000 ReportIntervalMdt = "1800000"
+
+       ReportIntervalMdtN2048 ReportIntervalMdt = "2048"
+
+       ReportIntervalMdtN240 ReportIntervalMdt = "240"
+
+       ReportIntervalMdtN360000 ReportIntervalMdt = "360000"
+
+       ReportIntervalMdtN3600000 ReportIntervalMdt = "3600000"
+
+       ReportIntervalMdtN480 ReportIntervalMdt = "480"
+
+       ReportIntervalMdtN5120 ReportIntervalMdt = "5120"
+
+       ReportIntervalMdtN60000 ReportIntervalMdt = "60000"
+
+       ReportIntervalMdtN640 ReportIntervalMdt = "640"
+
+       ReportIntervalMdtN720000 ReportIntervalMdt = "720000"
+)
+
+// Defines values for ReportIntervalNrMdt.
+const (
+       ReportIntervalNrMdtN1024 ReportIntervalNrMdt = "1024"
+
+       ReportIntervalNrMdtN10240 ReportIntervalNrMdt = "10240"
+
+       ReportIntervalNrMdtN120 ReportIntervalNrMdt = "120"
+
+       ReportIntervalNrMdtN1800000 ReportIntervalNrMdt = "1800000"
+
+       ReportIntervalNrMdtN2048 ReportIntervalNrMdt = "2048"
+
+       ReportIntervalNrMdtN20480 ReportIntervalNrMdt = "20480"
+
+       ReportIntervalNrMdtN240 ReportIntervalNrMdt = "240"
+
+       ReportIntervalNrMdtN360000 ReportIntervalNrMdt = "360000"
+
+       ReportIntervalNrMdtN3600000 ReportIntervalNrMdt = "3600000"
+
+       ReportIntervalNrMdtN40960 ReportIntervalNrMdt = "40960"
+
+       ReportIntervalNrMdtN480 ReportIntervalNrMdt = "480"
+
+       ReportIntervalNrMdtN5120 ReportIntervalNrMdt = "5120"
+
+       ReportIntervalNrMdtN60000 ReportIntervalNrMdt = "60000"
+
+       ReportIntervalNrMdtN640 ReportIntervalNrMdt = "640"
+
+       ReportIntervalNrMdtN720000 ReportIntervalNrMdt = "720000"
+)
+
+// Defines values for ReportTypeMdt.
+const (
+       ReportTypeMdtEVENTTRIGGED ReportTypeMdt = "EVENT_TRIGGED"
+
+       ReportTypeMdtPERIODICAL ReportTypeMdt = "PERIODICAL"
+)
+
+// Defines values for ReportingTrigger.
+const (
+       ReportingTriggerALLRRMEVENTTRIGGERS ReportingTrigger = "ALL_RRM_EVENT_TRIGGERS"
+
+       ReportingTriggerEVENTA2 ReportingTrigger = "EVENT_A2"
+
+       ReportingTriggerEVENTA2PERIODIC ReportingTrigger = "EVENT_A2_PERIODIC"
+
+       ReportingTriggerPERIODICAL ReportingTrigger = "PERIODICAL"
+)
+
+// Defines values for RestrictionType.
+const (
+       RestrictionTypeALLOWEDAREAS RestrictionType = "ALLOWED_AREAS"
+
+       RestrictionTypeNOTALLOWEDAREAS RestrictionType = "NOT_ALLOWED_AREAS"
+)
+
+// Defines values for RoamingOdb.
+const (
+       RoamingOdbOUTSIDEHOMEPLMN RoamingOdb = "OUTSIDE_HOME_PLMN"
+
+       RoamingOdbOUTSIDEHOMEPLMNCOUNTRY RoamingOdb = "OUTSIDE_HOME_PLMN_COUNTRY"
+)
+
+// Defines values for SatelliteBackhaulCategory.
+const (
+       SatelliteBackhaulCategoryGEO SatelliteBackhaulCategory = "GEO"
+
+       SatelliteBackhaulCategoryLEO SatelliteBackhaulCategory = "LEO"
+
+       SatelliteBackhaulCategoryMEO SatelliteBackhaulCategory = "MEO"
+
+       SatelliteBackhaulCategoryNONSATELLITE SatelliteBackhaulCategory = "NON_SATELLITE"
+
+       SatelliteBackhaulCategoryOTHERSAT SatelliteBackhaulCategory = "OTHER_SAT"
+)
+
+// Defines values for ScheduledCommunicationType.
+const (
+       ScheduledCommunicationTypeBIDIRECTIONAL ScheduledCommunicationType = "BIDIRECTIONAL"
+
+       ScheduledCommunicationTypeDOWNLINKONLY ScheduledCommunicationType = "DOWNLINK_ONLY"
+
+       ScheduledCommunicationTypeUPLINKONLY ScheduledCommunicationType = "UPLINK_ONLY"
+)
+
+// Defines values for SensorMeasurement.
+const (
+       SensorMeasurementBAROMETRICPRESSURE SensorMeasurement = "BAROMETRIC_PRESSURE"
+
+       SensorMeasurementUEORIENTATION SensorMeasurement = "UE_ORIENTATION"
+
+       SensorMeasurementUESPEED SensorMeasurement = "UE_SPEED"
+)
+
+// Defines values for SscMode.
+const (
+       SscModeSSCMODE1 SscMode = "SSC_MODE_1"
+
+       SscModeSSCMODE2 SscMode = "SSC_MODE_2"
+
+       SscModeSSCMODE3 SscMode = "SSC_MODE_3"
+)
+
+// Defines values for StationaryIndication.
+const (
+       StationaryIndicationMOBILE StationaryIndication = "MOBILE"
+
+       StationaryIndicationSTATIONARY StationaryIndication = "STATIONARY"
+)
+
+// Defines values for TraceDepth.
+const (
+       TraceDepthMAXIMUM TraceDepth = "MAXIMUM"
+
+       TraceDepthMAXIMUMWOVENDOREXTENSION TraceDepth = "MAXIMUM_WO_VENDOR_EXTENSION"
+
+       TraceDepthMEDIUM TraceDepth = "MEDIUM"
+
+       TraceDepthMEDIUMWOVENDOREXTENSION TraceDepth = "MEDIUM_WO_VENDOR_EXTENSION"
+
+       TraceDepthMINIMUM TraceDepth = "MINIMUM"
+
+       TraceDepthMINIMUMWOVENDOREXTENSION TraceDepth = "MINIMUM_WO_VENDOR_EXTENSION"
+)
+
+// Defines values for TrafficProfile.
+const (
+       TrafficProfileDUALTRANSDLFIRST TrafficProfile = "DUAL_TRANS_DL_FIRST"
+
+       TrafficProfileDUALTRANSULFIRST TrafficProfile = "DUAL_TRANS_UL_FIRST"
+
+       TrafficProfileMULTITRANS TrafficProfile = "MULTI_TRANS"
+
+       TrafficProfileSINGLETRANSDL TrafficProfile = "SINGLE_TRANS_DL"
+
+       TrafficProfileSINGLETRANSUL TrafficProfile = "SINGLE_TRANS_UL"
+)
+
+// Defines values for TransportProtocol.
+const (
+       TransportProtocolTCP TransportProtocol = "TCP"
+
+       TransportProtocolUDP TransportProtocol = "UDP"
+)
+
+// Defines values for UeAuth.
+const (
+       UeAuthAUTHORIZED UeAuth = "AUTHORIZED"
+
+       UeAuthNOTAUTHORIZED UeAuth = "NOT_AUTHORIZED"
+)
+
+// Defines values for UpConfidentiality.
+const (
+       UpConfidentialityNOTNEEDED UpConfidentiality = "NOT_NEEDED"
+
+       UpConfidentialityPREFERRED UpConfidentiality = "PREFERRED"
+
+       UpConfidentialityREQUIRED UpConfidentiality = "REQUIRED"
+)
+
+// Defines values for UpIntegrity.
+const (
+       UpIntegrityNOTNEEDED UpIntegrity = "NOT_NEEDED"
+
+       UpIntegrityPREFERRED UpIntegrity = "PREFERRED"
+
+       UpIntegrityREQUIRED UpIntegrity = "REQUIRED"
+)
+
+// Defines values for UriScheme.
+const (
+       UriSchemeHttp UriScheme = "http"
+
+       UriSchemeHttps UriScheme = "https"
+)
+
+// Unsigned Integer, i.e. only value 0 and integers above 0 are permissible.
+type N5GMmCause Uinteger
+
+// The 5GPRUK ID is string in NAI format as specified in clause 28.7.19 of 3GPP TS 23.003.
+type N5GPrukId string
+
+// Unsigned integer representing a 5G QoS Identifier (see clause 5.7.2.1 of 3GPP TS 23.501, within the range 0 to 255.
+type N5Qi int
+
+// Unsigned integer indicating the 5QI Priority Level (see clauses 5.7.3.3 and 5.7.4 of 3GPP TS 23.501, within the range 1 to 127.Values are ordered in decreasing order of priority,  i.e. with 1 as the highest priority and 127 as the lowest priority.
+type N5QiPriorityLevel int
+
+// This data type is defined in the same way as the '5QiPriorityLevel' data type, but with the OpenAPI 'nullable: true' property.
+type N5QiPriorityLevelRm int
+
+// This data type is defined in the same way as the '5QiPriorityLevel' data type, but with the OpenAPI 'nullable: true' property. "
+type N5QiRm int
+
+// Indicates whether the access is  via 3GPP or via non-3GPP.
+type AccessType string
+
+// Indicates wether the access is via 3GPP or via non-3GPP but with the OpenAPI  'nullable: true' property."
+type AccessTypeRm interface{}
+
+// The ACS information for the 5G-RG is defined in BBF TR-069 [42] or in BBF TR-369
+type AcsInfo struct {
+       // String identifying a IPv4 address formatted in the 'dotted decimal' notation as defined in RFC 1166.
+       AcsIpv4Addr *Ipv4Addr `json:"acsIpv4Addr,omitempty"`
+
+       // String identifying an IPv6 address formatted according to clause 4 of RFC5952. The mixed IPv4 IPv6 notation according to clause 5 of RFC5952 shall not be used.
+       AcsIpv6Addr *Ipv6Addr `json:"acsIpv6Addr,omitempty"`
+
+       // String providing an URI formatted according to RFC 3986.
+       AcsUrl *Uri `json:"acsUrl,omitempty"`
+}
+
+// This data type is defined in the same way as the 'AcsInfo' data type, but with the  OpenAPI 'nullable: true' property.
+type AcsInfoRm interface{}
+
+// The enumeration AdditionalQosFlowInfo provides additional QoS flow information (see clause  9.3.1.12 3GPP TS 38.413 [11]). It shall comply with the provisions defined in table 5.5.3.12-1.
+type AdditionalQosFlowInfo interface{}
+
+// Contains the maximum aggregated uplink and downlink bit rates.
+type Ambr struct {
+       // String representing a bit rate; the prefixes follow the standard symbols from The International System of Units, and represent x1000 multipliers, with the exception that prefix "K" is used to represent the standard symbol "k".
+       Downlink BitRate `json:"downlink"`
+
+       // String representing a bit rate; the prefixes follow the standard symbols from The International System of Units, and represent x1000 multipliers, with the exception that prefix "K" is used to represent the standard symbol "k".
+       Uplink BitRate `json:"uplink"`
+}
+
+// This data type is defined in the same way as the 'Ambr' data type, but with the OpenAPI 'nullable: true' property."
+type AmbrRm interface{}
+
+// String identifying the AMF ID composed of AMF Region ID (8 bits), AMF Set ID (10 bits) and AMF  Pointer (6 bits) as specified in clause 2.10.1 of 3GPP TS 23.003. It is encoded as a string of  6 hexadecimal characters (i.e., 24 bits).
+type AmfId string
+
+// Fully Qualified Domain Name
+type AmfName Fqdn
+
+// String identifying the AMF Set ID (10 bits) as specified in clause 2.10.1 of 3GPP TS 23.003.  It is encoded as a string of 3 hexadecimal characters where the first character is limited to  values 0 to 3 (i.e. 10 bits)
+type AmfRegionId string
+
+// String identifying the AMF Set ID (10 bits) as specified in clause 2.10.1 of 3GPP TS 23.003.  It is encoded as a string of 3 hexadecimal characters where the first character is limited to  values 0 to 3 (i.e. 10 bits).
+type AmfSetId string
+
+// Contains the APN rate control status e.g. of the AMF.
+type ApnRateStatus struct {
+       // When present, it shall indicate the number of additional exception reports the AF is allowed to send downlink in the  given time unit for the given APN (all PDN connections of the UE to this APN, see clause 4.7.7.3 in 3GPP TS 23.401.
+       RemainExReportsDl *int `json:"remainExReportsDl,omitempty"`
+
+       // When present, it shall indicate the number of additional exception reports the UE is allowed to send uplink in the given time unit for the given APN (all PDN connections of the UE to this APN, see clause 4.7.7.3 in 3GPP TS 23.401.
+       RemainExReportsUl *int `json:"remainExReportsUl,omitempty"`
+
+       // When present, it shall contain the number of packets the UE is allowed to send uplink in the given time unit for the given APN (all PDN connections of the UE to this APN see clause 4.7.7.3 in 3GPP TS 23.401.
+       RemainPacketsDl *int `json:"remainPacketsDl,omitempty"`
+
+       // When present, it shall contain the number of packets the UE is allowed to send uplink in the given time unit for the given APN (all PDN connections of the UE to this APN see clause 4.7.7.3 in 3GPP TS 23.401.
+       RemainPacketsUl *int `json:"remainPacketsUl,omitempty"`
+
+       // string with format 'date-time' as defined in OpenAPI.
+       ValidityTime *DateTime `json:"validityTime,omitempty"`
+}
+
+// Application provided charging identifier allowing correlation of charging information.
+type ApplicationChargingId string
+
+// String providing an application identifier.
+type ApplicationId string
+
+// String providing an application identifier with the OpenAPI 'nullable: true' property.
+type ApplicationIdRm string
+
+// Provides area information.
+type Area interface{}
+
+// Values are operator specific.
+type AreaCode string
+
+// This data type is defined in the same way as the 'AreaCode' data type, but with the OpenAPI 'nullable: true' property.
+type AreaCodeRm string
+
+// Contain the area based on Cells or Tracking Areas.
+type AreaScope struct {
+       EutraCellIdList *[]EutraCellId `json:"eutraCellIdList,omitempty"`
+       NrCellIdList    *[]NrCellId    `json:"nrCellIdList,omitempty"`
+
+       // A map (list of key-value pairs) where PlmnId converted to a string serves as key
+       TacInfoPerPlmn *AreaScope_TacInfoPerPlmn `json:"tacInfoPerPlmn,omitempty"`
+       TacList        *[]Tac                    `json:"tacList,omitempty"`
+}
+
+// A map (list of key-value pairs) where PlmnId converted to a string serves as key
+type AreaScope_TacInfoPerPlmn struct {
+       AdditionalProperties map[string]TacInfo `json:"-"`
+}
+
+// Integer where the allowed values correspond to the value range of an unsigned 16-bit integer.
+type AreaSessionId Uint16
+
+// Integer value indicating the ARFCN applicable for a downlink, uplink or bi-directional (TDD) NR global frequency raster, as definition of "ARFCN-ValueNR" IE in clause 6.3.2 of 3GPP TS 38.331.
+type ArfcnValueNR int
+
+// Contains Allocation and Retention Priority information.
+type Arp struct {
+       // The enumeration PreemptionCapability indicates the pre-emption capability of a request on other QoS flows. See clause 5.7.2.2 of 3GPP TS 23.501. It shall comply with the provisions defined in table 5.5.3.1-1.
+       PreemptCap PreemptionCapability `json:"preemptCap"`
+
+       // The enumeration PreemptionVulnerability indicates the pre-emption vulnerability of the QoS flow to pre-emption from other QoS flows. See clause 5.7.2.2 of 3GPP TS 23.501. It shall comply with the provisions defined in table 5.5.3.2-1
+       PreemptVuln PreemptionVulnerability `json:"preemptVuln"`
+
+       // nullable true shall not be used for this attribute. Unsigned integer indicating the ARP Priority Level (see clause 5.7.2.2 of 3GPP TS 23.501, within the range 1 to 15.Values are ordered in decreasing order of priority, i.e. with 1 as the highest priority and 15 as the lowest priority.
+       PriorityLevel *ArpPriorityLevel `json:"priorityLevel"`
+}
+
+// nullable true shall not be used for this attribute. Unsigned integer indicating the ARP Priority Level (see clause 5.7.2.2 of 3GPP TS 23.501, within the range 1 to 15.Values are ordered in decreasing order of priority, i.e. with 1 as the highest priority and 15 as the lowest priority.
+type ArpPriorityLevel int
+
+// This data type is defined in the same way as the 'ArpPriorityLevel' data type, but with the OpenAPI 'nullable: true' property.
+type ArpPriorityLevelRm int
+
+// This data type is defined in the same way as the 'Arp' data type, but with the OpenAPI 'nullable: true' property.
+type ArpRm interface{}
+
+// contains a search parameter and its positive or negative content.
+type Atom struct {
+       // contains the name of a defined query parameter.
+       Attr string `json:"attr"`
+
+       // indicates whether the negative condition applies for the query condition.
+       Negative *bool       `json:"negative,omitempty"`
+       Value    interface{} `json:"value"`
+}
+
+// Containes Capability to support procedures related to Access Traffic Steering, Switching, Splitting.
+type AtsssCapability struct {
+       // Indicates the ATSSS-LL capability to support procedures related to Access Traffic Steering, Switching, Splitting (see clauses 4.2.10, 5.32 of 3GPP TS 23.501). true: Supported false (default): Not Supported
+       AtsssLL *bool `json:"atsssLL,omitempty"`
+
+       // Indicates the MPTCP capability to support procedures related to Access Traffic Steering, Switching, Splitting (see clauses 4.2.10, 5.32 of 3GPP TS 23.501 true: Supported false (default): Not Supported
+       Mptcp *bool `json:"mptcp,omitempty"`
+
+       // This IE is only used by the UPF to indicate whether the UPF supports RTT measurement without PMF (see clauses 5.32.2, 6.3.3.3 of 3GPP TS 23.501 true: Supported false (default): Not Supported
+       RttWithoutPmf *bool `json:"rttWithoutPmf,omitempty"`
+}
+
+// Possible values are:
+// - "EAP_SUCCESS": The NSSAA status is EAP-Success.
+// - "EAP_FAILURE": The NSSAA status is EAP-Failure.
+// - "PENDING": The NSSAA status is Pending.
+type AuthStatus string
+
+// Unsigned integer indicating Averaging Window (see clause 5.7.3.6 and 5.7.4 of 3GPP TS 23.501), expressed in milliseconds.
+type AverWindow int
+
+// This data type is defined in the same way as the 'AverWindow' data type, but with the OpenAPI 'nullable: true' property.
+type AverWindowRm int
+
+// Provides details of the Backup AMF.
+type BackupAmfInfo struct {
+       // Fully Qualified Domain Name
+       BackupAmf AmfName `json:"backupAmf"`
+
+       // If present, this IE shall contain the list of GUAMI(s) (supported by the AMF) for which the backupAmf IE applies.
+       GuamiList *[]Guami `json:"guamiList,omitempty"`
+}
+
+// Parameters "replaceableInd" and "rechargeableInd" are only included if the value of Parameter "batteryInd" is true.
+type BatteryIndication struct {
+       // This IE shall indicate whether the UE is battery powered or not. true: the UE is battery powered; false or absent: the UE is not battery powered
+       BatteryInd *bool `json:"batteryInd,omitempty"`
+
+       // This IE shall indicate whether the battery of the UE is rechargeable or not. true: the battery of UE is rechargeable; false or absent: the battery of the UE is not rechargeable.
+       RechargeableInd *bool `json:"rechargeableInd,omitempty"`
+
+       // This IE shall indicate whether the battery of the UE is replaceable or not. true: the battery of the UE is replaceable; false or absent: the battery of the UE is not replaceable.
+       ReplaceableInd *bool `json:"replaceableInd,omitempty"`
+}
+
+// This data type is defined in the same way as the 'BatteryIndication' data type, but with the OpenAPI 'nullable: true' property.
+type BatteryIndicationRm interface{}
+
+// string with format 'binary' as defined in OpenAPI.
+type Binary string
+
+// string with format 'binary' as defined in OpenAPI OpenAPI with 'nullable: true' property.
+type BinaryRm string
+
+// String representing a bit rate; the prefixes follow the standard symbols from The International System of Units, and represent x1000 multipliers, with the exception that prefix "K" is used to represent the standard symbol "k".
+type BitRate string
+
+// This data type is defined in the same way as the 'BitRate' data type, but with the OpenAPI 'nullable: true' property.
+type BitRateRm string
+
+// Broadcast MBS Session's Delivery Status
+type BroadcastDeliveryStatus string
+
+// string with format 'bytes' as defined in OpenAPI
+type Bytes []byte
+
+// string with format 'bytes' as defined in OpenAPI OpenAPI with 'nullable: true' property.
+type BytesRm []byte
+
+// String representing the C-MSISDN as defined in clause 18.7 of 3GPP TS 23.003.
+type CMsisdn string
+
+// String representing the C-MSISDN as defined in clause 18.7 of 3GPP TS 23.003 with the OpenAPI 'nullable: true' property.
+type CMsisdnRm string
+
+// String containing a Closed Access Group Identifier.
+type CagId string
+
+// Contains a Cell Global Identification as defined in 3GPP TS 23.003, clause 4.3.1.
+type CellGlobalId struct {
+       CellId string `json:"cellId"`
+       Lac    string `json:"lac"`
+
+       // When PlmnId needs to be converted to string (e.g. when used in maps as key), the string  shall be composed of three digits "mcc" followed by "-" and two or three digits "mnc".
+       PlmnId PlmnId `json:"plmnId"`
+}
+
+// It contains data which need to be changed.
+type ChangeItem struct {
+       // indicates the path of the source JSON element (according to JSON Pointer syntax)  being moved or copied to the location indicated by the "path" attribute. It shall  be present if the "op" attribute is of value "MOVE".
+       From     *string      `json:"from,omitempty"`
+       NewValue *interface{} `json:"newValue,omitempty"`
+
+       // Indicates the type of change to be performed.
+       Op        ChangeType   `json:"op"`
+       OrigValue *interface{} `json:"origValue,omitempty"`
+
+       // contains a JSON pointer value (as defined in IETF RFC 6901) that references a target  location within the resource on which the change has been applied.
+       Path string `json:"path"`
+}
+
+// Indicates the type of change to be performed.
+type ChangeType string
+
+// Integer where the allowed values correspond to the value range of an unsigned 32-bit integer.
+type ChargingId int
+
+// A conjunctive normal form
+type Cnf struct {
+       CnfUnits []CnfUnit `json:"cnfUnits"`
+}
+
+// During the processing of cnfUnits attribute, all the members in the array shall be  interpreted as logically concatenated with logical "AND".
+type CnfUnit struct {
+       CnfUnit []Atom `json:"cnfUnit"`
+}
+
+// The enumeration CollectionPeriodRmmLteMdt defines Collection period for RRM measurements LTE for MDT in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.15-1.
+type CollectionPeriodRmmLteMdt string
+
+// The enumeration CollectionPeriodRmmNrMdt defines Collection period for RRM measurements NR for MDT in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.19-1
+type CollectionPeriodRmmNrMdt string
+
+// The ComplexQuery data type is either a conjunctive normal form or a disjunctive normal form.  The attribute names "cnfUnits" and "dnfUnits" (see clause 5.2.4.11 and clause 5.2.4.12)  serve as discriminator.
+type ComplexQuery interface{}
+
+// It contains the Core Network type 5GC or EPC.
+type CoreNetworkType string
+
+// It contains the Core Network type 5GC or EPC but with the OpenAPI 'nullable: true' property.
+type CoreNetworkTypeRm interface{}
+
+// string with format 'date' as defined in OpenAPI.
+type Date openapi_types.Date
+
+// string with format 'date' as defined in OpenAPI OpenAPI with 'nullable: true' property.
+type DateRm openapi_types.Date
+
+// string with format 'date-time' as defined in OpenAPI.
+type DateTime time.Time
+
+// string with format 'date-time' as defined in OpenAPI with 'nullable:true' property.
+type DateTimeRm time.Time
+
+// integer between and including 1 and 7 denoting a weekday. 1 shall indicate Monday, and the subsequent weekdays  shall be indicated with the next higher numbers. 7 shall indicate Sunday.
+type DayOfWeek int
+
+// Contains a Traffic Descriptor.
+type DddTrafficDescriptor struct {
+       // String identifying a IPv4 address formatted in the 'dotted decimal' notation as defined in RFC 1166.
+       Ipv4Addr *Ipv4Addr `json:"ipv4Addr,omitempty"`
+
+       // String identifying an IPv6 address formatted according to clause 4 of RFC5952. The mixed IPv4 IPv6 notation according to clause 5 of RFC5952 shall not be used.
+       Ipv6Addr *Ipv6Addr `json:"ipv6Addr,omitempty"`
+
+       // String identifying a MAC address formatted in the hexadecimal notation according to clause 1.1 and clause 2.1 of RFC 7042.
+       MacAddr *MacAddr48 `json:"macAddr,omitempty"`
+
+       // Unsigned Integer, i.e. only value 0 and integers above 0 are permissible.
+       PortNumber *Uinteger `json:"portNumber,omitempty"`
+}
+
+// Fully Qualified Domain Name
+type DiameterIdentity Fqdn
+
+// Fully Qualified Domain Name, but it also allows the null value
+type DiameterIdentityRm FqdnRm
+
+// Possible values are:
+//   - BUFFERED: The first downlink data is buffered with extended buffering matching the
+//     source of the downlink traffic.
+//   - TRANSMITTED: The first downlink data matching the source of the downlink traffic is
+//     transmitted after previous buffering or discarding of corresponding packet(s) because
+//     the UE of the PDU Session becomes ACTIVE, and buffered data can be delivered to UE.
+//   - DISCARDED: The first downlink data matching the source of the downlink traffic is
+//     discarded because the Extended Buffering time, as determined by the SMF, expires or
+//     the amount of downlink data to be buffered is exceeded.
+type DlDataDeliveryStatus string
+
+// This data type is defined in the same way as the ' DlDataDeliveryStatus ' data type, but with the OpenAPI 'nullable: true' property.
+type DlDataDeliveryStatusRm interface{}
+
+// DNAI (Data network access identifier), see clause 5.6.7 of 3GPP TS 23.501.
+type Dnai string
+
+// Possible values are:
+//   - EARLY: Early notification of UP path reconfiguration.
+//   - EARLY_LATE: Early and late notification of UP path reconfiguration. This value shall
+//     only be present in the subscription to the DNAI change event.
+//   - LATE: Late notification of UP path reconfiguration.
+type DnaiChangeType string
+
+// It can take the values  as specified for DnaiChangeType but with the OpenAPI 'nullable: true' property.
+type DnaiChangeTypeRm interface{}
+
+// This data type is defined in the same way as the 'Dnai' data type, but with the OpenAPI 'nullable: true' property.
+type DnaiRm string
+
+// A disjunctive normal form.
+type Dnf struct {
+       DnfUnits []DnfUnit `json:"dnfUnits"`
+}
+
+// During the processing of dnfUnits attribute, all the members in the array shall be  interpreted as logically concatenated with logical "OR".
+type DnfUnit struct {
+       DnfUnit []Atom `json:"dnfUnit"`
+}
+
+// String representing a Data Network as defined in clause 9A of 3GPP TS 23.003;  it shall contain either a DNN Network Identifier, or a full DNN with both the Network  Identifier and Operator Identifier, as specified in 3GPP TS 23.003 clause 9.1.1 and 9.1.2. It shall be coded as string in which the labels are separated by dots  (e.g. "Label1.Label2.Label3").
+type Dnn string
+
+// String representing a Data Network as defined in clause 9A of 3GPP TS 23.003;  it shall contain either a DNN Network Identifier, or a full DNN with both the  Network Identifier and Operator Identifier, as specified in 3GPP TS 23.003 clause 9.1.1  and 9.1.2. It shall be coded as string in which the labels are separated by dots  (e.g. 'Label1.Label2.Label3') with the OpenAPI 'nullable: true' property.
+type DnnRm string
+
+// string with format 'double' as defined in OpenAPI
+type Double float64
+
+// string with format 'double' as defined in OpenAPI with 'nullable: true' property.
+type DoubleRm float64
+
+// indicating a time in seconds.
+type DurationSec int
+
+// indicating a time in seconds with OpenAPI defined 'nullable: true' property.
+type DurationSecRm int
+
+// It indicates the QoS Characteristics for a Non-standardised or not pre-configured 5QI for downlink and uplink.
+type Dynamic5Qi struct {
+       // Unsigned integer indicating Averaging Window (see clause 5.7.3.6 and 5.7.4 of 3GPP TS 23.501), expressed in milliseconds.
+       AverWindow *AverWindow `json:"averWindow,omitempty"`
+
+       // Unsigned integer indicating Packet Delay Budget (see clauses 5.7.3.4 and 5.7.4 of 3GPP TS 23.501 [8])), expressed in 0.01 milliseconds.
+       CnPacketDelayBudgetDl *ExtPacketDelBudget `json:"cnPacketDelayBudgetDl,omitempty"`
+
+       // Unsigned integer indicating Packet Delay Budget (see clauses 5.7.3.4 and 5.7.4 of 3GPP TS 23.501 [8])), expressed in 0.01 milliseconds.
+       CnPacketDelayBudgetUl *ExtPacketDelBudget `json:"cnPacketDelayBudgetUl,omitempty"`
+
+       // Unsigned integer indicating Maximum Data Burst Volume (see clauses 5.7.3.7 and 5.7.4 of 3GPP TS 23.501), expressed in Bytes.
+       ExtMaxDataBurstVol *ExtMaxDataBurstVol `json:"extMaxDataBurstVol,omitempty"`
+
+       // Unsigned integer indicating Packet Delay Budget (see clauses 5.7.3.4 and 5.7.4 of 3GPP TS 23.501 [8])), expressed in 0.01 milliseconds.
+       ExtPacketDelBudget *ExtPacketDelBudget `json:"extPacketDelBudget,omitempty"`
+
+       // Unsigned integer indicating Maximum Data Burst Volume (see clauses 5.7.3.7 and 5.7.4 of 3GPP TS 23.501), expressed in Bytes.
+       MaxDataBurstVol *MaxDataBurstVol `json:"maxDataBurstVol,omitempty"`
+
+       // Unsigned integer indicating Packet Delay Budget (see clauses 5.7.3.4 and 5.7.4 of 3GPP TS 23.501), expressed in milliseconds.
+       PacketDelayBudget PacketDelBudget `json:"packetDelayBudget"`
+
+       // String representing Packet Error Rate (see clause 5.7.3.5 and 5.7.4 of 3GPP TS 23.501, expressed as a "scalar x 10-k" where the scalar and the exponent k are each encoded as one decimal digit.
+       PacketErrRate PacketErrRate `json:"packetErrRate"`
+
+       // Unsigned integer indicating the 5QI Priority Level (see clauses 5.7.3.3 and 5.7.4 of 3GPP TS 23.501, within the range 1 to 127.Values are ordered in decreasing order of priority,  i.e. with 1 as the highest priority and 127 as the lowest priority.
+       PriorityLevel N5QiPriorityLevel `json:"priorityLevel"`
+
+       // The enumeration QosResourceType indicates whether a QoS Flow is non-GBR, delay critical GBR, or non-delay critical GBR (see clauses 5.7.3.4 and 5.7.3.5 of 3GPP TS 23.501). It shall comply with the provisions defined in table 5.5.3.6-1.
+       ResourceType QosResourceType `json:"resourceType"`
+}
+
+// This represents the identifier of the eNB ID as specified in clause 9.2.1.37 of  3GPP TS 36.413. The string shall be formatted with the following pattern  '^('MacroeNB-[A-Fa-f0-9]{5}|LMacroeNB-[A-Fa-f0-9]{6}|SMacroeNB-[A-Fa-f0-9]{5} |HomeeNB-[A-Fa-f0-9]{7})$'. The value of the eNB ID shall be encoded in hexadecimal representation. Each character in the  string shall take a value of "0" to "9", "a" to "f" or "A" to "F" and shall represent 4 bits.  The padding 0 shall be added to make multiple nibbles, so the most significant character  representing the padding 0 if required together with the 4 most significant bits of the eNB ID  shall appear first in the string, and the character representing the 4 least significant bit  of the eNB ID (to form a nibble) shall appear last in the string.
+type ENbId string
+
+// Contains EAS IP replacement information for a Source and a Target EAS.
+type EasIpReplacementInfo struct {
+       // Represents the IP address and port of an EAS server.
+       Source EasServerAddress `json:"source"`
+
+       // Represents the IP address and port of an EAS server.
+       Target EasServerAddress `json:"target"`
+}
+
+// Represents the IP address and port of an EAS server.
+type EasServerAddress struct {
+       // Contains an IP adresse.
+       Ip IpAddr `json:"ip"`
+
+       // Unsigned Integer, i.e. only value 0 and integers above 0 are permissible.
+       Port Uinteger `json:"port"`
+}
+
+// Contains the ECGI (E-UTRAN Cell Global Identity), as described in 3GPP 23.003
+type Ecgi struct {
+       // 28-bit string identifying an E-UTRA Cell Id as specified in clause 9.3.1.9 of  3GPP TS 38.413, in hexadecimal representation. Each character in the string shall take a  value of "0" to "9", "a" to "f" or "A" to "F" and shall represent 4 bits. The most  significant character representing the 4 most significant bits of the Cell Id shall appear  first in the string, and the character representing the 4 least significant bit of the  Cell Id shall appear last in the string.
+       EutraCellId EutraCellId `json:"eutraCellId"`
+
+       // This represents the Network Identifier, which together with a PLMN ID is used to identify an SNPN (see 3GPP TS 23.003 and 3GPP TS 23.501 clause 5.30.2.1).
+       Nid *Nid `json:"nid,omitempty"`
+
+       // When PlmnId needs to be converted to string (e.g. when used in maps as key), the string  shall be composed of three digits "mcc" followed by "-" and two or three digits "mnc".
+       PlmnId PlmnId `json:"plmnId"`
+}
+
+// This data type is defined in the same way as the 'Ecgi' data type, but with the OpenAPI 'nullable: true' property.
+type EcgiRm interface{}
+
+// Contains the Edge Configuration Server Address Configuration Information as defined in clause 5.2.3.6.1 of 3GPP TS 23.502.
+type EcsServerAddr struct {
+       EcsFqdnList      *[]Fqdn   `json:"ecsFqdnList,omitempty"`
+       EcsIpAddressList *[]IpAddr `json:"ecsIpAddressList,omitempty"`
+       EcsProviderId    *string   `json:"ecsProviderId,omitempty"`
+       EcsUriList       *[]Uri    `json:"ecsUriList,omitempty"`
+}
+
+// This data type is defined in the same way as the ' EcsServerAddr ' data type, but with the OpenAPI 'nullable: true' property.
+type EcsServerAddrRm interface{}
+
+// Empty JSON object { }, it is defined with the keyword additionalProperties false
+type EmptyObject map[string]interface{}
+
+// 28-bit string identifying an E-UTRA Cell Id as specified in clause 9.3.1.9 of  3GPP TS 38.413, in hexadecimal representation. Each character in the string shall take a  value of "0" to "9", "a" to "f" or "A" to "F" and shall represent 4 bits. The most  significant character representing the 4 most significant bits of the Cell Id shall appear  first in the string, and the character representing the 4 least significant bit of the  Cell Id shall appear last in the string.
+type EutraCellId string
+
+// This data type is defined in the same way as the 'EutraCellId' data type, but with the OpenAPI 'nullable: true' property.
+type EutraCellIdRm string
+
+// Contains the E-UTRA user location.
+type EutraLocation struct {
+       // The value represents the elapsed time in minutes since the last network contact of the mobile station.  Value "0" indicates that the location information was obtained after a successful paging procedure for Active Location Retrieval when the UE is in idle mode or after a successful NG-RAN location reporting procedure with the eNB when the UE is in connected mode.  Any other value than "0" indicates that the location information is the last known one.  See 3GPP TS 29.002 clause 17.7.8.
+       AgeOfLocationInformation *int `json:"ageOfLocationInformation,omitempty"`
+
+       // Contains the ECGI (E-UTRAN Cell Global Identity), as described in 3GPP 23.003
+       Ecgi Ecgi `json:"ecgi"`
+
+       // Refers to Calling Geodetic Location. See ITU-T Recommendation Q.763 (1999) [24] clause 3.88.2. Only the description of an ellipsoid point with uncertainty circle is allowed to be used.
+       GeodeticInformation *string `json:"geodeticInformation,omitempty"`
+
+       // Refer to geographical Information. See 3GPP TS 23.032 clause 7.3.2. Only the description of an ellipsoid point with uncertainty circle is allowed to be used.
+       GeographicalInformation *string `json:"geographicalInformation,omitempty"`
+
+       // One of the six attributes n3IwfId, gNbIdm, ngeNbId, wagfId, tngfId, eNbId shall be present.
+       GlobalENbId *GlobalRanNodeId `json:"globalENbId,omitempty"`
+
+       // One of the six attributes n3IwfId, gNbIdm, ngeNbId, wagfId, tngfId, eNbId shall be present.
+       GlobalNgenbId *GlobalRanNodeId `json:"globalNgenbId,omitempty"`
+
+       // This flag when present shall indicate that the Ecgi shall be ignored When present, it shall be set as follows: - true: ecgi shall be ignored. - false (default): ecgi shall not be ignored.
+       IgnoreEcgi *bool `json:"ignoreEcgi,omitempty"`
+       IgnoreTai  *bool `json:"ignoreTai,omitempty"`
+
+       // Contains the tracking area identity as described in 3GPP 23.003
+       Tai Tai `json:"tai"`
+
+       // string with format 'date-time' as defined in OpenAPI.
+       UeLocationTimestamp *DateTime `json:"ueLocationTimestamp,omitempty"`
+}
+
+// This data type is defined in the same way as the 'EutraLocation' data type, but with the OpenAPI 'nullable: true' property.
+type EutraLocationRm interface{}
+
+// The enumeration EventForMdt defines events triggered measurement for logged MDT in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.11-1
+type EventForMdt string
+
+// Unsigned integer indicating Maximum Data Burst Volume (see clauses 5.7.3.7 and 5.7.4 of 3GPP TS 23.501), expressed in Bytes.
+type ExtMaxDataBurstVol int
+
+// This data type is defined in the same way as the 'ExtMaxDataBurstVol' data type, but with the OpenAPI 'nullable: true' property.
+type ExtMaxDataBurstVolRm int
+
+// Unsigned integer indicating Packet Delay Budget (see clauses 5.7.3.4 and 5.7.4 of 3GPP TS 23.501 [8])), expressed in 0.01 milliseconds.
+type ExtPacketDelBudget int
+
+// This data type is defined in the same way as the 'ExtPacketDelBudget' data type, but with the OpenAPI 'nullable: true' property. "
+type ExtPacketDelBudgetRm int
+
+// ExtSnssai defines model for ExtSnssai.
+type ExtSnssai struct {
+       // Embedded struct due to allOf(#/components/schemas/Snssai)
+       Snssai `yaml:",inline"`
+       // Embedded struct due to allOf(#/components/schemas/SnssaiExtension)
+       SnssaiExtension `yaml:",inline"`
+}
+
+// String identifying External Group Identifier that identifies a group made up of one or more  subscriptions associated to a group of IMSIs, as specified in clause 19.7.3 of 3GPP TS 23.003.
+type ExternalGroupId string
+
+// String identifying External Group Identifier that identifies a group made up of one or more  subscriptions associated to a group of IMSIs, as specified in clause 19.7.3 of  3GPP TS 23.003  with the OpenAPI 'nullable: true' property.
+type ExternalGroupIdRm string
+
+// string with format 'float' as defined in OpenAPI.
+type Float float32
+
+// string with format 'float' as defined in OpenAPI with the OpenAPI defined 'nullable: true' property.
+type FloatRm float32
+
+// Fully Qualified Domain Name
+type Fqdn string
+
+// a matching rule for a FQDN pattern
+type FqdnPatternMatchingRule interface{}
+
+// Fully Qualified Domain Name, but it also allows the null value
+type FqdnRm interface{}
+
+// Provides the G-NB identifier.
+type GNbId struct {
+       // Unsigned integer representing the bit length of the gNB ID as defined in clause 9.3.1.6 of 3GPP TS 38.413 [11], within the range 22 to 32.
+       BitLength int `json:"bitLength"`
+
+       // This represents the identifier of the gNB. The value of the gNB ID shall be encoded in hexadecimal representation. Each character in the string shall take a value of "0" to "9", "a" to "f" or "A" to "F" and shall represent 4 bits. The padding 0 shall be added to make multiple nibbles,  the most significant character representing the padding 0 if required together with the 4 most significant bits of the gNB ID shall appear first in the string, and the character representing the 4 least significant bit of the gNB ID shall appear last in the string.
+       GNBValue string `json:"gNBValue"`
+}
+
+// Global Cable Identifier uniquely identifying the connection between the 5G-CRG or FN-CRG to the 5GS. See clause 28.15.4 of 3GPP TS 23.003. This shall be encoded as a string per clause 28.15.4 of 3GPP TS 23.003, and compliant with the syntax specified  in clause 2.2  of IETF RFC 7542 for the username part of a NAI. The GCI value is specified in CableLabs WR-TR-5WWC-ARCH.
+type Gci string
+
+// Exactly one of cgi, sai or lai shall be present.
+type GeraLocation interface{}
+
+// string with format 'bytes' as defined in OpenAPI
+type Gli Bytes
+
+// One of the six attributes n3IwfId, gNbIdm, ngeNbId, wagfId, tngfId, eNbId shall be present.
+type GlobalRanNodeId interface{}
+
+// String identifying a Gpsi shall contain either an External Id or an MSISDN.  It shall be formatted as follows -External Identifier= "extid-'extid', where 'extid'  shall be formatted according to clause 19.7.2 of 3GPP TS 23.003 that describes an  External Identifier.
+type Gpsi string
+
+// String identifying a Gpsi shall contain either an External Id or an MSISDN. It shall be  formatted as follows -External Identifier= 'extid-'extid', where 'extid' shall be formatted  according to clause 19.7.2 of 3GPP TS 23.003 that describes an External Identifier with the  OpenAPI 'nullable: true' property.
+type GpsiRm string
+
+// String identifying a group of devices network internal globally unique ID which identifies a set of IMSIs, as specified in clause 19.9 of 3GPP TS 23.003.
+type GroupId string
+
+// String identifying a group of devices network internal globally unique ID which identifies a set of IMSIs, as specified in clause 19.9 of 3GPP TS 23.003 with the OpenAPI 'nullable: true' property.
+type GroupIdRm string
+
+// Globally Unique AMF Identifier constructed out of PLMN, Network and AMF identity.
+type Guami struct {
+       // String identifying the AMF ID composed of AMF Region ID (8 bits), AMF Set ID (10 bits) and AMF  Pointer (6 bits) as specified in clause 2.10.1 of 3GPP TS 23.003. It is encoded as a string of  6 hexadecimal characters (i.e., 24 bits).
+       AmfId AmfId `json:"amfId"`
+
+       // Contains the serving core network operator PLMN ID and, for an SNPN, the NID that together with the PLMN ID identifies the SNPN.
+       PlmnId PlmnIdNid `json:"plmnId"`
+}
+
+// This data type is defined in the same way as the 'Guami' data type, but with the OpenAPI 'nullable: true' property.
+type GuamiRm interface{}
+
+// Hypertext Application Language (HAL) template contains the extended 3GPP hypermedia format.
+type HalTemplate struct {
+       // The media type that should be used for the corresponding request. If the attribute is missing, or contains an unrecognized value, the client should act as if the  contentType is set to "application/json".
+       ContentType *string `json:"contentType,omitempty"`
+
+       // HTTP methodes.
+       Method HttpMethod `json:"method"`
+
+       // The properties that should be included in the body of the corresponding request.  If the contentType attribute is set to "application/json", then this attribute  describes the attributes of the JSON object of the body.
+       Properties *[]Property `json:"properties,omitempty"`
+
+       // A human-readable string that can be used to identify this template
+       Title *string `json:"title,omitempty"`
+}
+
+// This IE represents the identifier of the HFC node Id as specified in CableLabs WR-TR-5WWC-ARCH. It is provisioned by the wireline operator as part of wireline operations and may contain up to six characters.
+type HfcNId string
+
+// This data type is defined in the same way as the 'HfcNId' data type, but with the OpenAPI 'nullable: true' property.
+type HfcNIdRm string
+
+// REpresents the HFC Node Identifer received over NGAP.
+type HfcNodeId struct {
+       // This IE represents the identifier of the HFC node Id as specified in CableLabs WR-TR-5WWC-ARCH. It is provisioned by the wireline operator as part of wireline operations and may contain up to six characters.
+       HfcNId HfcNId `json:"hfcNId"`
+}
+
+// This data type is defined in the same way as the 'HfcNodeId' data type, but with the OpenAPI 'nullable: true' property.
+type HfcNodeIdRm interface{}
+
+// HTTP methodes.
+type HttpMethod string
+
+// Ingress Tunnel Address Information
+type IngressTunAddrInfo struct {
+       IngressTunAddr []TunnelAddress `json:"ingressTunAddr"`
+}
+
+// string with format 'int32' as defined in OpenAPI.
+type Int32 int32
+
+// string with format 'int32' as defined in OpenAPI with the OpenAPI defined 'nullable: true' property.
+type Int32Rm int32
+
+// string with format 'int64' as defined in OpenAPI.
+type Int64 int64
+
+// string with format 'int64' as defined in OpenAPI with the OpenAPI defined 'nullable: true' property.
+type Int64Rm int64
+
+// Indicates the Inter Frequency Target information.
+type InterFreqTargetInfo struct {
+       // When present, this IE shall contain a list of the physical cell identities where the UE is requested to perform measurement logging for the indicated frequency.
+       CellIdList *[]PhysCellId `json:"cellIdList,omitempty"`
+
+       // Integer value indicating the ARFCN applicable for a downlink, uplink or bi-directional (TDD) NR global frequency raster, as definition of "ARFCN-ValueNR" IE in clause 6.3.2 of 3GPP TS 38.331.
+       DlCarrierFreq ArfcnValueNR `json:"dlCarrierFreq"`
+}
+
+// It contains an invalid parameter and a related description.
+type InvalidParam struct {
+       // If the invalid parameter is an attribute in a JSON body, this IE shall contain the  attribute's name and shall be encoded as a JSON Pointer. If the invalid parameter is  an HTTP header, this IE shall be formatted as the concatenation of the string "header "  plus the name of such header. If the invalid parameter is a query parameter, this IE  shall be formatted as the concatenation of the string "query " plus the name of such  query parameter. If the invalid parameter is a variable part in the path of a resource  URI, this IE shall contain the name of the variable, including the symbols "{" and "}"  used in OpenAPI specification as the notation to represent variable path segments.
+       Param string `json:"param"`
+
+       // A human-readable reason, e.g. "must be a positive integer". In cases involving failed  operations in a PATCH request, the reason string should identify the operation that  failed using the operation's array index to assist in correlation of the invalid  parameter with the failed operation, e.g." Replacement value invalid for attribute  (failed operation index= 4)"
+       Reason *string `json:"reason,omitempty"`
+}
+
+// Contains an IP adresse.
+type IpAddr interface{}
+
+// String identifying a IPv4 address formatted in the 'dotted decimal' notation as defined in RFC 1166.
+type Ipv4Addr string
+
+// "String identifying a IPv4 address mask formatted in the 'dotted decimal' notation as defined in RFC 1166."
+type Ipv4AddrMask string
+
+// String identifying a IPv4 address mask formatted in the 'dotted decimal' notation as defined in RFC 1166 with the OpenAPI defined 'nullable: true' property.
+type Ipv4AddrMaskRm string
+
+// String identifying a IPv4 address formatted in the 'dotted decimal' notation as defined in RFC 1166 with the OpenAPI defined 'nullable: true' property.
+type Ipv4AddrRm string
+
+// Ipv6Addr defines model for Ipv6Addr.
+type Ipv6Addr struct {
+       // Embedded fields due to inline allOf schema
+       // Embedded fields due to inline allOf schema
+}
+
+// Ipv6AddrRm defines model for Ipv6AddrRm.
+type Ipv6AddrRm struct {
+       // Embedded fields due to inline allOf schema
+       // Embedded fields due to inline allOf schema
+}
+
+// Ipv6Prefix defines model for Ipv6Prefix.
+type Ipv6Prefix struct {
+       // Embedded fields due to inline allOf schema
+       // Embedded fields due to inline allOf schema
+}
+
+// Ipv6PrefixRm defines model for Ipv6PrefixRm.
+type Ipv6PrefixRm struct {
+       // Embedded fields due to inline allOf schema
+       // Embedded fields due to inline allOf schema
+}
+
+// The enumeration JobType defines Job Type in the trace. See 3GPP TS 32.422 for further  description of the values. It shall comply with the provisions defined in table 5.6.3.3-1.
+type JobType string
+
+// Possible values are:
+//   - "LOCATION_ALLOWED_WITH_NOTIFICATION": Location allowed with notification
+//   - "LOCATION_ALLOWED_WITHOUT_NOTIFICATION": Location allowed without notification
+//   - "LOCATION_ALLOWED_WITHOUT_RESPONSE": Location with notification and privacy
+//     verification; location allowed if no response
+//   - "LOCATION_RESTRICTED_WITHOUT_RESPONSE": Location with notification and privacy
+//     verification; location restricted if no response
+//   - "NOTIFICATION_ONLY": Notification only
+//   - "NOTIFICATION_AND_VERIFICATION_ONLY": Notification and privacy verification only
+type LcsServiceAuth string
+
+// Possible values are:
+// - DSL: Identifies a DSL line
+// - PON: Identifies a PON line
+type LineType string
+
+// This data type is defined in the same way as the 'LineType' data type, but with the OpenAPI 'nullable: true' property.
+type LineTypeRm interface{}
+
+// It contains the URI of the linked resource.
+type Link struct {
+       // String providing an URI formatted according to RFC 3986.
+       Href *Uri `json:"href,omitempty"`
+}
+
+// It contains the URI of the linked resource with the OpenAPI 'nullable: true' property.
+type LinkRm struct {
+       // String providing an URI formatted according to RFC 3986.
+       Href *Uri `json:"href,omitempty"`
+}
+
+// A list of mutually exclusive alternatives of 1 or more links.
+type LinksValueSchema interface{}
+
+// Contains a Location area identification as defined in 3GPP TS 23.003, clause 4.1.
+type LocationAreaId struct {
+       // Location Area Code.
+       Lac string `json:"lac"`
+
+       // When PlmnId needs to be converted to string (e.g. when used in maps as key), the string  shall be composed of three digits "mcc" followed by "-" and two or three digits "mnc".
+       PlmnId PlmnId `json:"plmnId"`
+}
+
+// The enumeration LoggingIntervalMdt defines Logging Interval for MDT in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.12-1.
+type LoggingDurationMdt string
+
+// The enumeration LoggingDurationMdt defines Logging Duration in NR for MDT in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.20-1.
+type LoggingDurationNrMdt string
+
+// The enumeration LoggingIntervalMdt defines Logging Interval for MDT in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.12-1.
+type LoggingIntervalMdt string
+
+// The enumeration LoggingIntervalNrMdt defines Logging Interval in NR for MDT in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.18-1.
+type LoggingIntervalNrMdt string
+
+// Contains LTE V2X services authorized information.
+type LteV2xAuth struct {
+       // Possible values are:
+       // - AUTHORIZED: Indicates that the UE is authorized.
+       // - NOT_AUTHORIZED: Indicates that the UE is not authorized.
+       PedestrianUeAuth *UeAuth `json:"pedestrianUeAuth,omitempty"`
+
+       // Possible values are:
+       // - AUTHORIZED: Indicates that the UE is authorized.
+       // - NOT_AUTHORIZED: Indicates that the UE is not authorized.
+       VehicleUeAuth *UeAuth `json:"vehicleUeAuth,omitempty"`
+}
+
+// String identifying a MAC address formatted in the hexadecimal notation according to clause 1.1 and clause 2.1 of RFC 7042.
+type MacAddr48 string
+
+// "String identifying a MAC address formatted in the hexadecimal notation according to clause 1.1 and clause 2.1 of RFC 7042 with the OpenAPI 'nullable: true' property."
+type MacAddr48Rm string
+
+// string with format 'bytes' as defined in OpenAPI
+type ManAssiUeRadioCapId Bytes
+
+// the matching operation.
+type MatchingOperator string
+
+// Unsigned integer indicating Maximum Data Burst Volume (see clauses 5.7.3.7 and 5.7.4 of 3GPP TS 23.501), expressed in Bytes.
+type MaxDataBurstVol int
+
+// This data type is defined in the same way as the 'MaxDataBurstVol' data type, but with the OpenAPI 'nullable: true' property.
+type MaxDataBurstVolRm int
+
+// MBS Frequency Selection Area Identifier
+type MbsFsaId string
+
+// MBS Security Key Data Structure
+type MbsKeyInfo struct {
+       // string with format 'bytes' as defined in OpenAPI
+       KeyDomainId Bytes `json:"keyDomainId"`
+
+       // string with format 'bytes' as defined in OpenAPI
+       Msk *Bytes `json:"msk,omitempty"`
+
+       // string with format 'bytes' as defined in OpenAPI
+       MskId Bytes `json:"mskId"`
+
+       // string with format 'date-time' as defined in OpenAPI.
+       MskLifetime *DateTime `json:"mskLifetime,omitempty"`
+
+       // string with format 'bytes' as defined in OpenAPI
+       Mtk *Bytes `json:"mtk,omitempty"`
+
+       // string with format 'bytes' as defined in OpenAPI
+       MtkId *Bytes `json:"mtkId,omitempty"`
+}
+
+// Represent MBS QoS requirements.
+type MbsQoSReq struct {
+       // Unsigned integer representing a 5G QoS Identifier (see clause 5.7.2.1 of 3GPP TS 23.501, within the range 0 to 255.
+       N5qi N5Qi `json:"5qi"`
+
+       // Unsigned integer indicating Averaging Window (see clause 5.7.3.6 and 5.7.4 of 3GPP TS 23.501), expressed in milliseconds.
+       AverWindow *AverWindow `json:"averWindow,omitempty"`
+
+       // String representing a bit rate; the prefixes follow the standard symbols from The International System of Units, and represent x1000 multipliers, with the exception that prefix "K" is used to represent the standard symbol "k".
+       GuarBitRate *BitRate `json:"guarBitRate,omitempty"`
+
+       // String representing a bit rate; the prefixes follow the standard symbols from The International System of Units, and represent x1000 multipliers, with the exception that prefix "K" is used to represent the standard symbol "k".
+       MaxBitRate *BitRate `json:"maxBitRate,omitempty"`
+
+       // Contains Allocation and Retention Priority information.
+       ReqMbsArp *Arp `json:"reqMbsArp,omitempty"`
+}
+
+// MbsSecurityContext defines model for MbsSecurityContext.
+type MbsSecurityContext struct {
+       // A map (list of key-value pairs) where a (unique) valid JSON string serves as key of MbsSecurityContext
+       KeyList MbsSecurityContext_KeyList `json:"keyList"`
+}
+
+// A map (list of key-value pairs) where a (unique) valid JSON string serves as key of MbsSecurityContext
+type MbsSecurityContext_KeyList struct {
+       AdditionalProperties map[string]MbsKeyInfo `json:"-"`
+}
+
+// MBS Service Area
+type MbsServiceArea struct {
+       // List of NR cell Ids
+       NcgiList *[]NcgiTai `json:"ncgiList,omitempty"`
+
+       // List of tracking area Ids
+       TaiList *[]Tai `json:"taiList,omitempty"`
+}
+
+// MBS Service Area Information for location dependent MBS session
+type MbsServiceAreaInfo struct {
+       // Integer where the allowed values correspond to the value range of an unsigned 16-bit integer.
+       AreaSessionId AreaSessionId `json:"areaSessionId"`
+
+       // MBS Service Area
+       MbsServiceArea MbsServiceArea `json:"mbsServiceArea"`
+}
+
+// Indicates the type of an MBS session
+type MbsServiceType string
+
+// Contains an MBSFN area information.
+type MbsfnArea struct {
+       // When present, this IE shall contain the Carrier Frequency (EARFCN).
+       CarrierFrequency *int `json:"carrierFrequency,omitempty"`
+
+       // This IE shall contain the MBSFN Area ID.
+       MbsfnAreaId *int `json:"mbsfnAreaId,omitempty"`
+}
+
+// Mobile Country Code part of the PLMN, comprising 3 digits, as defined in clause 9.3.3.5 of 3GPP TS 38.413.
+type Mcc string
+
+// Mobile Country Code part of the PLMN, comprising 3 digits, as defined in clause 9.3.3.5 of  3GPP TS 38.413 with the OpenAPI 'nullable: true' property.
+type MccRm string
+
+// contains contain MDT configuration data.
+type MdtConfiguration struct {
+       AddPositioningMethodList *[]PositioningMethodMdt `json:"addPositioningMethodList,omitempty"`
+
+       // Contain the area based on Cells or Tracking Areas.
+       AreaScope *AreaScope `json:"areaScope,omitempty"`
+
+       // The enumeration CollectionPeriodRmmLteMdt defines Collection period for RRM measurements LTE for MDT in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.15-1.
+       CollectionPeriodRmmLte *CollectionPeriodRmmLteMdt `json:"collectionPeriodRmmLte,omitempty"`
+
+       // The enumeration CollectionPeriodRmmNrMdt defines Collection period for RRM measurements NR for MDT in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.19-1
+       CollectionPeriodRmmNr *CollectionPeriodRmmNrMdt `json:"collectionPeriodRmmNr,omitempty"`
+       EventList             *[]EventForMdt            `json:"eventList,omitempty"`
+
+       // This IE shall be present if the report trigger parameter is configured for A2 event reporting or A2 event triggered periodic reporting and the job type parameter is configured for Immediate MDT or combined Immediate MDT and Trace in LTE. When present, this IE shall indicate the Event Threshold for RSRP, and the value shall be between 0-97.
+       EventThresholdRsrp *int `json:"eventThresholdRsrp,omitempty"`
+
+       // This IE shall be present if the report trigger parameter is configured for A2 event reporting or A2 event triggered periodic reporting and the job type parameter is configured for Immediate MDT or combined Immediate MDT and Trace in NR. When present, this IE shall indicate the Event Threshold for RSRP, and the value shall be between 0-127.
+       EventThresholdRsrpNr *int `json:"eventThresholdRsrpNr,omitempty"`
+
+       // This IE shall be present if the report trigger parameter is configured for A2 event reporting or A2 event triggered periodic reporting and the job type parameter is configured for Immediate MDT or combined Immediate MDT and Trace in LTE.When present, this IE shall indicate the Event Threshold for RSRQ, and the value shall be between 0-34.
+       EventThresholdRsrq *int `json:"eventThresholdRsrq,omitempty"`
+
+       // This IE shall be present if the report trigger parameter is configured for A2 event reporting or A2 event triggered periodic reporting and the job type parameter is configured for Immediate MDT or combined Immediate MDT and Trace in NR.When present, this IE shall indicate the Event Threshold for RSRQ, and the value shall be between 0-127.
+       EventThresholdRsrqNr *int                   `json:"eventThresholdRsrqNr,omitempty"`
+       InterFreqTargetList  *[]InterFreqTargetInfo `json:"interFreqTargetList,omitempty"`
+
+       // The enumeration JobType defines Job Type in the trace. See 3GPP TS 32.422 for further  description of the values. It shall comply with the provisions defined in table 5.6.3.3-1.
+       JobType JobType `json:"jobType"`
+
+       // The enumeration LoggingIntervalMdt defines Logging Interval for MDT in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.12-1.
+       LoggingDuration *LoggingDurationMdt `json:"loggingDuration,omitempty"`
+
+       // The enumeration LoggingDurationMdt defines Logging Duration in NR for MDT in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.20-1.
+       LoggingDurationNr *LoggingDurationNrMdt `json:"loggingDurationNr,omitempty"`
+
+       // The enumeration LoggingIntervalMdt defines Logging Interval for MDT in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.12-1.
+       LoggingInterval *LoggingIntervalMdt `json:"loggingInterval,omitempty"`
+
+       // The enumeration LoggingIntervalNrMdt defines Logging Interval in NR for MDT in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.18-1.
+       LoggingIntervalNr    *LoggingIntervalNrMdt   `json:"loggingIntervalNr,omitempty"`
+       MbsfnAreaList        *[]MbsfnArea            `json:"mbsfnAreaList,omitempty"`
+       MdtAllowedPlmnIdList *[]PlmnId               `json:"mdtAllowedPlmnIdList,omitempty"`
+       MeasurementLteList   *[]MeasurementLteForMdt `json:"measurementLteList,omitempty"`
+       MeasurementNrList    *[]MeasurementNrForMdt  `json:"measurementNrList,omitempty"`
+
+       // The enumeration MeasurementPeriodLteMdt defines Measurement period LTE for MDT in the trace.  See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.16-1.
+       MeasurementPeriodLte *MeasurementPeriodLteMdt `json:"measurementPeriodLte,omitempty"`
+
+       // The enumeration LoggingDurationMdt defines Logging Duration for MDT in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.13-1.
+       PositioningMethod *PositioningMethodMdt `json:"positioningMethod,omitempty"`
+
+       // The enumeration ReportAmountMdt defines Report Amount for MDT in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.10-1.
+       ReportAmount *ReportAmountMdt `json:"reportAmount,omitempty"`
+
+       // The enumeration ReportIntervalMdt defines Report Interval for MDT in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.9-1.
+       ReportInterval *ReportIntervalMdt `json:"reportInterval,omitempty"`
+
+       // The enumeration ReportIntervalNrMdt defines Report Interval in NR for MDT in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.17-1.
+       ReportIntervalNr *ReportIntervalNrMdt `json:"reportIntervalNr,omitempty"`
+
+       // The enumeration ReportTypeMdt defines Report Type for logged MDT in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.4-1.
+       ReportType            *ReportTypeMdt       `json:"reportType,omitempty"`
+       ReportingTriggerList  *[]ReportingTrigger  `json:"reportingTriggerList,omitempty"`
+       SensorMeasurementList *[]SensorMeasurement `json:"sensorMeasurementList,omitempty"`
+}
+
+// The enumeration MeasurementLteForMdt defines Measurements used for MDT in LTE in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.5-1.
+type MeasurementLteForMdt string
+
+// The enumeration MeasurementNrForMdt defines Measurements used for MDT in NR in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.6-1.
+type MeasurementNrForMdt string
+
+// The enumeration MeasurementPeriodLteMdt defines Measurement period LTE for MDT in the trace.  See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.16-1.
+type MeasurementPeriodLteMdt string
+
+// Mobile Network Code part of the PLMN, comprising 2 or 3 digits, as defined in clause 9.3.3.5 of 3GPP TS 38.413.
+type Mnc string
+
+// Mobile Network Code part of the PLMN, comprising 2 or 3 digits, as defined in clause 9.3.3.5 of 3GPP TS 38.413 with the OpenAPI 'nullable: true' property.
+type MncRm string
+
+// Contain the MO Exception Data Counter.
+type MoExpDataCounter struct {
+       // Unsigned integer identifying the MO Exception Data Counter, as specified in clause 5.31.14.3 of 3GPP TS 23.501.
+       Counter int `json:"counter"`
+
+       // string with format 'date-time' as defined in OpenAPI.
+       TimeStamp *DateTime `json:"timeStamp,omitempty"`
+}
+
+// String uniquely identifying MTC provider information.
+type MtcProviderInformation string
+
+// This represents the identifier of the N3IWF ID as specified in clause 9.3.1.57 of  3GPP TS 38.413 in hexadecimal representation. Each character in the string shall take a value  of "0" to "9", "a" to "f" or "A" to "F" and shall represent 4 bits. The most significant  character representing the 4 most significant bits of the N3IWF ID shall appear first in the  string, and the character representing the 4 least significant bit of the N3IWF ID shall  appear last in the string.
+type N3IwfId string
+
+// Contains the Non-3GPP access user location.
+type N3gaLocation struct {
+       // Global Cable Identifier uniquely identifying the connection between the 5G-CRG or FN-CRG to the 5GS. See clause 28.15.4 of 3GPP TS 23.003. This shall be encoded as a string per clause 28.15.4 of 3GPP TS 23.003, and compliant with the syntax specified  in clause 2.2  of IETF RFC 7542 for the username part of a NAI. The GCI value is specified in CableLabs WR-TR-5WWC-ARCH.
+       Gci *Gci `json:"gci,omitempty"`
+
+       // string with format 'bytes' as defined in OpenAPI
+       Gli *Gli `json:"gli,omitempty"`
+
+       // REpresents the HFC Node Identifer received over NGAP.
+       HfcNodeId *HfcNodeId `json:"hfcNodeId,omitempty"`
+
+       // This IE shall contain the N3IWF identifier received over NGAP and shall be encoded as a  string of hexadecimal characters. Each character in the string shall take a value of "0"  to "9", "a" to "f" or "A" to "F" and shall represent 4 bits. The most significant  character representing the 4 most significant bits of the N3IWF ID shall appear first in  the string, and the character representing the 4 least significant bit of the N3IWF ID  shall appear last in the string.
+       N3IwfId *string `json:"n3IwfId,omitempty"`
+
+       // Contains the tracking area identity as described in 3GPP 23.003
+       N3gppTai *Tai `json:"n3gppTai,omitempty"`
+
+       // Unsigned Integer, i.e. only value 0 and integers above 0 are permissible.
+       PortNumber *Uinteger `json:"portNumber,omitempty"`
+
+       // Possible values are:
+       // - UDP: User Datagram Protocol.
+       // - TCP: Transmission Control Protocol.
+       Protocol *TransportProtocol `json:"protocol,omitempty"`
+
+       // Contain the TNAP Identifier see clause5.6.2 of 3GPP TS 23.501.
+       TnapId *TnapId `json:"tnapId,omitempty"`
+
+       // Contain the TWAP Identifier as defined in clause 4.2.8.5.3 of 3GPP TS 23.501 or the WLAN location information as defined in clause 4.5.7.2.8 of 3GPP TS 23.402.
+       TwapId *TwapId `json:"twapId,omitempty"`
+
+       // String identifying a IPv4 address formatted in the 'dotted decimal' notation as defined in RFC 1166.
+       UeIpv4Addr *Ipv4Addr `json:"ueIpv4Addr,omitempty"`
+
+       // String identifying an IPv6 address formatted according to clause 4 of RFC5952. The mixed IPv4 IPv6 notation according to clause 5 of RFC5952 shall not be used.
+       UeIpv6Addr *Ipv6Addr `json:"ueIpv6Addr,omitempty"`
+
+       // Possible values are:
+       // - DSL: Identifies a DSL line
+       // - PON: Identifies a PON line
+       W5gbanLineType *LineType `json:"w5gbanLineType,omitempty"`
+}
+
+// Contains the NCGI (NR Cell Global Identity), as described in 3GPP 23.003
+type Ncgi struct {
+       // This represents the Network Identifier, which together with a PLMN ID is used to identify an SNPN (see 3GPP TS 23.003 and 3GPP TS 23.501 clause 5.30.2.1).
+       Nid *Nid `json:"nid,omitempty"`
+
+       // 36-bit string identifying an NR Cell Id as specified in clause 9.3.1.7 of 3GPP TS 38.413,  in hexadecimal representation. Each character in the string shall take a value of "0" to "9",  "a" to "f" or "A" to "F" and shall represent 4 bits. The most significant character  representing the 4 most significant bits of the Cell Id shall appear first in the string, and  the character representing the 4 least significant bit of the Cell Id shall appear last in the  string.
+       NrCellId NrCellId `json:"nrCellId"`
+
+       // When PlmnId needs to be converted to string (e.g. when used in maps as key), the string  shall be composed of three digits "mcc" followed by "-" and two or three digits "mnc".
+       PlmnId PlmnId `json:"plmnId"`
+}
+
+// This data type is defined in the same way as the 'Ncgi' data type, but with the  OpenAPI 'nullable: true' property.
+type NcgiRm interface{}
+
+// List of NR cell ids, with their pertaining TAIs
+type NcgiTai struct {
+       // List of List of NR cell ids
+       CellList []Ncgi `json:"cellList"`
+
+       // Contains the tracking area identity as described in 3GPP 23.003
+       Tai Tai `json:"tai"`
+}
+
+// contains PLMN and Network identity.
+type NetworkId struct {
+       // Mobile Country Code part of the PLMN, comprising 3 digits, as defined in clause 9.3.3.5 of 3GPP TS 38.413.
+       Mcc *Mcc `json:"mcc,omitempty"`
+
+       // Mobile Network Code part of the PLMN, comprising 2 or 3 digits, as defined in clause 9.3.3.5 of 3GPP TS 38.413.
+       Mnc *Mnc `json:"mnc,omitempty"`
+}
+
+// Identifier of a group of NFs.
+type NfGroupId string
+
+// String uniquely identifying a NF instance. The format of the NF Instance ID shall be a  Universally Unique Identifier (UUID) version 4, as described in IETF RFC 4122.
+type NfInstanceId openapi_types.UUID
+
+// NF Service Set Identifier (see clause 28.12 of 3GPP TS 23.003) formatted as the following  string "set<Set ID>.sn<Service Name>.nfi<NF Instance ID>.5gc.mnc<MNC>.mcc<MCC>", or  "set<SetID>.sn<ServiceName>.nfi<NFInstanceID>.5gc.nid<NID>.mnc<MNC>.mcc<MCC>" with  <MCC> encoded as defined in clause 5.4.2 ("Mcc" data type definition)   <MNC> encoding the Mobile Network Code part of the PLMN, comprising 3 digits.
+//
+//     If there are only 2 significant digits in the MNC, one "0" digit shall be inserted
+//     at the left side to fill the 3 digits coding of MNC.  Pattern: '^[0-9]{3}$'
+//
+// <NID> encoded as defined in clause 5.4.2 ("Nid" data type definition)  <NFInstanceId> encoded as defined in clause 5.3.2  <ServiceName> encoded as defined in 3GPP TS 29.510  <Set ID> encoded as a string of characters consisting of alphabetic
+//
+//     characters (A-Z and a-z), digits (0-9) and/or the hyphen (-) and that shall end
+//     with either an alphabetic character or a digit.
+type NfServiceSetId string
+
+// NF Set Identifier (see clause 28.12 of 3GPP TS 23.003), formatted as the following string "set<Set ID>.<nftype>set.5gc.mnc<MNC>.mcc<MCC>", or  "set<SetID>.<NFType>set.5gc.nid<NID>.mnc<MNC>.mcc<MCC>" with  <MCC> encoded as defined in clause 5.4.2 ("Mcc" data type definition)  <MNC> encoding the Mobile Network Code part of the PLMN, comprising 3 digits.
+//
+//     If there are only 2 significant digits in the MNC, one "0" digit shall be inserted
+//     at the left side to fill the 3 digits coding of MNC.  Pattern: '^[0-9]{3}$'
+//
+// <NFType> encoded as a value defined in Table 6.1.6.3.3-1 of 3GPP TS 29.510 but
+//
+//     with lower case characters <Set ID> encoded as a string of characters consisting of
+//     alphabetic characters (A-Z and a-z), digits (0-9) and/or the hyphen (-) and that
+//     shall end with either an alphabetic character or a digit.
+type NfSetId string
+
+// Represents the NGAP cause.
+type NgApCause struct {
+       // Unsigned Integer, i.e. only value 0 and integers above 0 are permissible.
+       Group Uinteger `json:"group"`
+
+       // Unsigned Integer, i.e. only value 0 and integers above 0 are permissible.
+       Value Uinteger `json:"value"`
+}
+
+// This represents the identifier of the ng-eNB ID as specified in clause 9.3.1.8 of  3GPP TS 38.413. The value of the ng-eNB ID shall be encoded in hexadecimal representation.  Each character in the string shall take a value of "0" to "9", "a" to "f" or "A" to "F" and  shall represent 4 bits. The padding 0 shall be added to make multiple nibbles, so the most  significant character representing the padding 0 if required together with the 4 most  significant bits of the ng-eNB ID shall appear first in the string, and the character  representing the 4 least significant bit of the ng-eNB ID (to form a nibble) shall appear last  in the string.
+type NgeNbId string
+
+// This represents the Network Identifier, which together with a PLMN ID is used to identify an SNPN (see 3GPP TS 23.003 and 3GPP TS 23.501 clause 5.30.2.1).
+type Nid string
+
+// This data type is defined in the same way as the 'Nid' data type, but with the OpenAPI 'nullable: true' property."
+type NidRm string
+
+// It indicates the QoS Characteristics for a standardized or pre-configured 5QI for downlink and uplink.
+type NonDynamic5Qi struct {
+       // Unsigned integer indicating Averaging Window (see clause 5.7.3.6 and 5.7.4 of 3GPP TS 23.501), expressed in milliseconds.
+       AverWindow *AverWindow `json:"averWindow,omitempty"`
+
+       // Unsigned integer indicating Packet Delay Budget (see clauses 5.7.3.4 and 5.7.4 of 3GPP TS 23.501 [8])), expressed in 0.01 milliseconds.
+       CnPacketDelayBudgetDl *ExtPacketDelBudget `json:"cnPacketDelayBudgetDl,omitempty"`
+
+       // Unsigned integer indicating Packet Delay Budget (see clauses 5.7.3.4 and 5.7.4 of 3GPP TS 23.501 [8])), expressed in 0.01 milliseconds.
+       CnPacketDelayBudgetUl *ExtPacketDelBudget `json:"cnPacketDelayBudgetUl,omitempty"`
+
+       // Unsigned integer indicating Maximum Data Burst Volume (see clauses 5.7.3.7 and 5.7.4 of 3GPP TS 23.501), expressed in Bytes.
+       ExtMaxDataBurstVol *ExtMaxDataBurstVol `json:"extMaxDataBurstVol,omitempty"`
+
+       // Unsigned integer indicating Maximum Data Burst Volume (see clauses 5.7.3.7 and 5.7.4 of 3GPP TS 23.501), expressed in Bytes.
+       MaxDataBurstVol *MaxDataBurstVol `json:"maxDataBurstVol,omitempty"`
+
+       // Unsigned integer indicating the 5QI Priority Level (see clauses 5.7.3.3 and 5.7.4 of 3GPP TS 23.501, within the range 1 to 127.Values are ordered in decreasing order of priority,  i.e. with 1 as the highest priority and 127 as the lowest priority.
+       PriorityLevel *N5QiPriorityLevel `json:"priorityLevel,omitempty"`
+}
+
+// The enumeration NotificationControl indicates whether notifications are requested from the RAN when the GFBR can no longer  (or again) be fulfilled for a QoS Flow during the lifetime of the QoS Flow (see clause 5.7.2.4 of 3GPP TS 23.501). It shall comply with the provisions defined in table 5.5.3.5-1.
+type NotificationControl string
+
+// This enumeration is defined in the same way as the 'NotificationControl' enumeration, but with the OpenAPI 'nullable: true' property.
+type NotificationControlRm interface{}
+
+// Possible values are:
+//   - ACTIVATE: The event notification is activated.
+//   - DEACTIVATE: The event notification is deactivated and shall be muted. The available
+//     event(s) shall be stored.
+//   - RETRIEVAL: The event notification shall be sent to the NF service consumer(s),
+//     after that, is muted again.
+type NotificationFlag string
+
+// Indicates changes on a resource.
+type NotifyItem struct {
+       Changes []ChangeItem `json:"changes"`
+
+       // String providing an URI formatted according to RFC 3986.
+       ResourceId Uri `json:"resourceId"`
+}
+
+// 36-bit string identifying an NR Cell Id as specified in clause 9.3.1.7 of 3GPP TS 38.413,  in hexadecimal representation. Each character in the string shall take a value of "0" to "9",  "a" to "f" or "A" to "F" and shall represent 4 bits. The most significant character  representing the 4 most significant bits of the Cell Id shall appear first in the string, and  the character representing the 4 least significant bit of the Cell Id shall appear last in the  string.
+type NrCellId string
+
+// This data type is defined in the same way as the 'NrCellId' data type, but with the OpenAPI 'nullable: true' property.
+type NrCellIdRm string
+
+// Contains the NR user location.
+type NrLocation struct {
+       // The value represents the elapsed time in minutes since the last network contact of the mobile station. Value "0" indicates that the location information was obtained after a successful paging procedure for Active Location Retrieval when the UE is in idle mode or after a successful  NG-RAN location reporting procedure with the eNB when the UE is in connected mode. Any other value than "0" indicates that the location information is the last known one. See 3GPP TS 29.002 clause 17.7.8.
+       AgeOfLocationInformation *int `json:"ageOfLocationInformation,omitempty"`
+
+       // Refers to Calling Geodetic Location. See ITU-T Recommendation Q.763 (1999) [24] clause 3.88.2. Only the description of an ellipsoid point with uncertainty circle is allowed to be used.
+       GeodeticInformation *string `json:"geodeticInformation,omitempty"`
+
+       // Refer to geographical Information. See 3GPP TS 23.032 clause 7.3.2. Only the description of an ellipsoid point with uncertainty circle is allowed to be used.
+       GeographicalInformation *string `json:"geographicalInformation,omitempty"`
+
+       // One of the six attributes n3IwfId, gNbIdm, ngeNbId, wagfId, tngfId, eNbId shall be present.
+       GlobalGnbId *GlobalRanNodeId `json:"globalGnbId,omitempty"`
+       IgnoreNcgi  *bool            `json:"ignoreNcgi,omitempty"`
+
+       // Contains the NCGI (NR Cell Global Identity), as described in 3GPP 23.003
+       Ncgi Ncgi `json:"ncgi"`
+
+       // Contains the tracking area identity as described in 3GPP 23.003
+       Tai Tai `json:"tai"`
+
+       // string with format 'date-time' as defined in OpenAPI.
+       UeLocationTimestamp *DateTime `json:"ueLocationTimestamp,omitempty"`
+}
+
+// This data type is defined in the same way as the 'NrLocation' data type, but with the OpenAPI 'nullable: true' property."
+type NrLocationRm interface{}
+
+// Contains NR V2X services authorized information.
+type NrV2xAuth struct {
+       // Possible values are:
+       // - AUTHORIZED: Indicates that the UE is authorized.
+       // - NOT_AUTHORIZED: Indicates that the UE is not authorized.
+       PedestrianUeAuth *UeAuth `json:"pedestrianUeAuth,omitempty"`
+
+       // Possible values are:
+       // - AUTHORIZED: Indicates that the UE is authorized.
+       // - NOT_AUTHORIZED: Indicates that the UE is not authorized.
+       VehicleUeAuth *UeAuth `json:"vehicleUeAuth,omitempty"`
+}
+
+// String providing a Network Slice Simultaneous Registration Group. See clause 5.15.12 of  3GPP TS 23.501
+type NsSrg string
+
+// String providing a Network Slice Simultaneous Registration Group with the OpenAPI "nullable: true" property. See clause 5.15.12 of 3GPP TS 23.501
+type NsSrgRm string
+
+// The Network Slice AS Group ID, see 3GPP TS 38.413
+type NsagId int
+
+// This data type is defined in the same way as the "NsagId" data type, but with the OpenAPI "nullable: true" property
+type NsagIdRm int
+
+// contains the Subscribed S-NSSAI subject to NSSAA procedure and the status.
+type NssaaStatus struct {
+       // When Snssai needs to be converted to string (e.g. when used in maps as key), the string shall be composed of one to three digits "sst" optionally followed by "-" and 6 hexadecimal digits "sd".
+       Snssai Snssai `json:"snssai"`
+
+       // Possible values are:
+       // - "EAP_SUCCESS": The NSSAA status is EAP-Success.
+       // - "EAP_FAILURE": The NSSAA status is EAP-Failure.
+       // - "PENDING": The NSSAA status is Pending.
+       Status AuthStatus `json:"status"`
+}
+
+// This data type is defined in the same way as the 'NssaaStatus' data type, but with the OpenAPI 'nullable: true' property.
+type NssaaStatusRm interface{}
+
+// JSON's null value.
+type NullValue interface{}
+
+// Contains information regarding operater  determined  barring.
+type OdbData struct {
+       // The enumeration RoamingOdb defines the Barring of Roaming as. See 3GPP TS 23.015 for further description. It shall comply with the provisions defined in table 5.7.3.1-1.
+       RoamingOdb *RoamingOdb `json:"roamingOdb,omitempty"`
+}
+
+// The enumeration OdbPacketServices defines the Barring of Packet Oriented Services. See 3GPP TS 23.015 for further description. It shall comply with the provisions defined in table 5.7.3.2-1
+type OdbPacketServices interface{}
+
+// Unsigned integer indicating Packet Delay Budget (see clauses 5.7.3.4 and 5.7.4 of 3GPP TS 23.501), expressed in milliseconds.
+type PacketDelBudget int
+
+// This data type is defined in the same way as the 'PacketDelBudget' data type, but with the OpenAPI 'nullable: true' property.
+type PacketDelBudgetRm int
+
+// String representing Packet Error Rate (see clause 5.7.3.5 and 5.7.4 of 3GPP TS 23.501, expressed as a "scalar x 10-k" where the scalar and the exponent k are each encoded as one decimal digit.
+type PacketErrRate string
+
+// This data type is defined in the same way as the 'PacketErrRate' data type, but with the OpenAPI 'nullable: true' property.
+type PacketErrRateRm string
+
+// Unsigned integer indicating Packet Loss Rate (see clauses 5.7.2.8 and 5.7.4 of 3GPP TS 23.501), expressed in tenth of percent.
+type PacketLossRate int
+
+// This data type is defined in the same way as the 'PacketLossRate' data type, but with the OpenAPI 'nullable: true' property.
+type PacketLossRateRm int
+
+// Possible values are:
+// - "TAC": Type Allocation Code
+// - "SUBPLMN": Subscriber PLMN ID
+// - "GEOAREA": Geographical area, i.e. list(s) of TAI(s)
+// - "SNSSAI": S-NSSAI
+// - "DNN": DNN
+type PartitioningCriteria string
+
+// This data type is defined in the same way as the ' PartitioningCriteria ' data type, but with the OpenAPI 'nullable: true' property.
+type PartitioningCriteriaRm interface{}
+
+// it contains information on data to be changed.
+type PatchItem struct {
+       // indicates the path of the source JSON element (according to JSON Pointer syntax) being moved or copied to the location indicated by the "path" attribute.
+       From *string `json:"from,omitempty"`
+
+       // Operations as defined in IETF RFC 6902.
+       Op PatchOperation `json:"op"`
+
+       // contains a JSON pointer value (as defined in IETF RFC 6901) that references a location of a resource on which the patch operation shall be performed.
+       Path  string       `json:"path"`
+       Value *interface{} `json:"value,omitempty"`
+}
+
+// Operations as defined in IETF RFC 6902.
+type PatchOperation string
+
+// The execution report result on failed modification.
+type PatchResult struct {
+       // The execution report contains an array of report items. Each report item indicates one  failed modification.
+       Report []ReportItem `json:"report"`
+}
+
+// it shall represent the PC5 Flow Bit Rates
+type Pc5FlowBitRates struct {
+       // String representing a bit rate; the prefixes follow the standard symbols from The International System of Units, and represent x1000 multipliers, with the exception that prefix "K" is used to represent the standard symbol "k".
+       GuaFbr *BitRate `json:"guaFbr,omitempty"`
+
+       // String representing a bit rate; the prefixes follow the standard symbols from The International System of Units, and represent x1000 multipliers, with the exception that prefix "K" is used to represent the standard symbol "k".
+       MaxFbr *BitRate `json:"maxFbr,omitempty"`
+}
+
+// Contains policy data on the PC5 QoS parameters.
+type Pc5QoSPara struct {
+       // String representing a bit rate; the prefixes follow the standard symbols from The International System of Units, and represent x1000 multipliers, with the exception that prefix "K" is used to represent the standard symbol "k".
+       Pc5LinkAmbr    *BitRate         `json:"pc5LinkAmbr,omitempty"`
+       Pc5QosFlowList []Pc5QosFlowItem `json:"pc5QosFlowList"`
+}
+
+// Contains a PC5 QOS flow.
+type Pc5QosFlowItem struct {
+       // it shall represent the PC5 Flow Bit Rates
+       Pc5FlowBitRates *Pc5FlowBitRates `json:"pc5FlowBitRates,omitempty"`
+
+       // Unsigned integer representing a 5G QoS Identifier (see clause 5.7.2.1 of 3GPP TS 23.501, within the range 0 to 255.
+       Pqi N5Qi `json:"pqi"`
+
+       // Unsigned Integer, i.e. only value 0 and integers above 0 are permissible.
+       Range *Uinteger `json:"range,omitempty"`
+}
+
+// Contains the PCF for the UE information necessary for the PCF for the PDU session to send  SM Policy Association Establishment and Termination events.
+type PcfUeCallbackInfo struct {
+       BindingInfo *string `json:"bindingInfo,omitempty"`
+
+       // String providing an URI formatted according to RFC 3986.
+       CallbackUri Uri `json:"callbackUri"`
+}
+
+// Unsigned integer identifying a PDU session, within the range 0 to 255, as specified in  clause 11.2.3.1b, bits 1 to 8, of 3GPP TS 24.007. If the PDU Session ID is allocated by the  Core Network for UEs not supporting N1 mode, reserved range 64 to 95 is used. PDU Session ID  within the reserved range is only visible in the Core Network.
+type PduSessionId int
+
+// indicates the DNN and S-NSSAI combination of a PDU session.
+type PduSessionInfo struct {
+       // String representing a Data Network as defined in clause 9A of 3GPP TS 23.003;  it shall contain either a DNN Network Identifier, or a full DNN with both the Network  Identifier and Operator Identifier, as specified in 3GPP TS 23.003 clause 9.1.1 and 9.1.2. It shall be coded as string in which the labels are separated by dots  (e.g. "Label1.Label2.Label3").
+       Dnn Dnn `json:"dnn"`
+
+       // When Snssai needs to be converted to string (e.g. when used in maps as key), the string shall be composed of one to three digits "sst" optionally followed by "-" and 6 hexadecimal digits "sd".
+       Snssai Snssai `json:"snssai"`
+}
+
+// PduSessionType indicates the type of a PDU session. It shall comply with the provisions defined in table 5.4.3.3-1.
+type PduSessionType string
+
+// PduSessionType indicates the type of a PDU session. It shall comply with the provisions defined in table 5.4.3.3-1 but with the OpenAPI "nullable: true" property.
+type PduSessionTypeRm interface{}
+
+// String representing a Permanent Equipment Identifier that may contain - an IMEI or IMEISV, as  specified in clause 6.2 of 3GPP TS 23.003; a MAC address for a 5G-RG or FN-RG via  wireline  access, with an indication that this address cannot be trusted for regulatory purpose if this  address cannot be used as an Equipment Identifier of the FN-RG, as specified in clause 4.7.7  of 3GPP TS23.316. Examples are imei-012345678901234 or imeisv-0123456789012345.
+type Pei string
+
+// This data type is defined in the same way as the 'Pei' data type but with the OpenAPI 'nullable: true' property.
+type PeiRm string
+
+// Integer value identifying the physical cell identity (PCI), as definition of "PhysCellId" IE  in clause 6.3.2 of 3GPP TS 38.331.
+type PhysCellId int
+
+// string with format 'bytes' as defined in OpenAPI
+type PlmnAssiUeRadioCapId Bytes
+
+// When PlmnId needs to be converted to string (e.g. when used in maps as key), the string  shall be composed of three digits "mcc" followed by "-" and two or three digits "mnc".
+type PlmnId struct {
+       // Mobile Country Code part of the PLMN, comprising 3 digits, as defined in clause 9.3.3.5 of 3GPP TS 38.413.
+       Mcc Mcc `json:"mcc"`
+
+       // Mobile Network Code part of the PLMN, comprising 2 or 3 digits, as defined in clause 9.3.3.5 of 3GPP TS 38.413.
+       Mnc Mnc `json:"mnc"`
+}
+
+// Contains the serving core network operator PLMN ID and, for an SNPN, the NID that together with the PLMN ID identifies the SNPN.
+type PlmnIdNid struct {
+       // Mobile Country Code part of the PLMN, comprising 3 digits, as defined in clause 9.3.3.5 of 3GPP TS 38.413.
+       Mcc Mcc `json:"mcc"`
+
+       // Mobile Network Code part of the PLMN, comprising 2 or 3 digits, as defined in clause 9.3.3.5 of 3GPP TS 38.413.
+       Mnc Mnc `json:"mnc"`
+
+       // This represents the Network Identifier, which together with a PLMN ID is used to identify an SNPN (see 3GPP TS 23.003 and 3GPP TS 23.501 clause 5.30.2.1).
+       Nid *Nid `json:"nid,omitempty"`
+}
+
+// This data type is defined in the same way as the 'PlmnIdNid' data type, but with the OpenAPI 'nullable: true' property.
+type PlmnIdNidRm interface{}
+
+// This data type is defined in the same way as the 'PlmnId' data type, but with the OpenAPI 'nullable: true' property.
+type PlmnIdRm interface{}
+
+// The enumeration LoggingDurationMdt defines Logging Duration for MDT in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.13-1.
+type PositioningMethodMdt string
+
+// The enumeration PreemptionCapability indicates the pre-emption capability of a request on other QoS flows. See clause 5.7.2.2 of 3GPP TS 23.501. It shall comply with the provisions defined in table 5.5.3.1-1.
+type PreemptionCapability string
+
+// This enumeration is defined in the same way as the 'PreemptionCapability' enumeration, but with the OpenAPI 'nullable: true' property.
+type PreemptionCapabilityRm interface{}
+
+// The enumeration PreemptionVulnerability indicates the pre-emption vulnerability of the QoS flow to pre-emption from other QoS flows. See clause 5.7.2.2 of 3GPP TS 23.501. It shall comply with the provisions defined in table 5.5.3.2-1
+type PreemptionVulnerability string
+
+// This enumeration is defined in the same way as the 'PreemptionVulnerability' enumeration, but with the OpenAPI 'nullable: true' property."
+type PreemptionVulnerabilityRm interface{}
+
+// If the additionalPraId IE is present, this IE shall state the presence information of the UE for the individual PRA identified by the additionalPraId IE;  If the additionalPraId IE is not present, this IE shall state the presence information of the UE for the PRA identified by the praId IE.
+type PresenceInfo struct {
+       // This IE may be present if the praId IE is present and if it contains a PRA identifier referring to a set of Core Network predefined Presence Reporting Areas. When present, this IE shall contain a PRA Identifier of an individual PRA within the Set of Core Network predefined Presence Reporting Areas indicated by the praId IE.
+       AdditionalPraId *string `json:"additionalPraId,omitempty"`
+
+       // Represents the list of EUTRAN cell Ids that constitutes the area. This IE shall be present if the Area of Interest subscribed is a list of EUTRAN cell Ids.
+       EcgiList *[]Ecgi `json:"ecgiList,omitempty"`
+
+       // Represents the list of NG RAN node identifiers that constitutes the area. This IE shall be present if the Area of Interest subscribed is a list of NG RAN node identifiers.
+       GlobalRanNodeIdList *[]GlobalRanNodeId `json:"globalRanNodeIdList,omitempty"`
+
+       // Represents the list of eNodeB identifiers that constitutes the area. This IE shall be  present if the Area of Interest subscribed is a list of eNodeB identifiers.
+       GlobaleNbIdList *[]GlobalRanNodeId `json:"globaleNbIdList,omitempty"`
+
+       // Represents the list of NR cell Ids that constitutes the area. This IE shall be present if the Area of Interest subscribed is a list of NR cell Ids.
+       NcgiList *[]Ncgi `json:"ncgiList,omitempty"`
+
+       // Represents an identifier of the Presence Reporting Area (see clause 28.10 of 3GPP  TS 23.003.  This IE shall be present  if the Area of Interest subscribed or reported is a Presence Reporting Area or a Set of Core Network predefined Presence Reporting Areas. When present, it shall be encoded as a string representing an integer in the following ranges: 0 to 8 388 607 for UE-dedicated PRA 8 388 608 to 16 777 215 for Core Network predefined PRA Examples: PRA ID 123 is encoded as "123" PRA ID 11 238 660 is encoded as "11238660"
+       PraId *string `json:"praId,omitempty"`
+
+       // Possible values are:
+       // -IN_AREA: Indicates that the UE is inside or enters the presence reporting area.
+       // -OUT_OF_AREA: Indicates that the UE is outside or leaves the presence reporting area
+       // -UNKNOW: Indicates it is unknown whether the UE is in the presence reporting area or not
+       // -INACTIVE: Indicates that the presence reporting area is inactive in the serving node.
+       PresenceState *PresenceState `json:"presenceState,omitempty"`
+
+       // Represents the list of tracking areas that constitutes the area. This IE shall be present if the subscription or  the event report is for tracking UE presence in the tracking areas. For non 3GPP access the TAI shall be the N3GPP TAI.
+       TrackingAreaList *[]Tai `json:"trackingAreaList,omitempty"`
+}
+
+// This data type is defined in the same way as the 'PresenceInfo' data type, but with the OpenAPI 'nullable: true' property.  If the additionalPraId IE is present, this IE shall state the presence information of the UE for the individual PRA identified by the additionalPraId IE;  If the additionalPraId IE is not present, this IE shall state the presence information of the UE for the PRA identified by the praId IE.
+type PresenceInfoRm struct {
+       // This IE may be present if the praId IE is present and if it contains a PRA identifier referring to a set of Core Network predefined Presence Reporting Areas. When present, this IE shall contain a PRA Identifier of an individual PRA within the Set of Core Network predefined Presence Reporting Areas indicated by the praId IE.
+       AdditionalPraId *string `json:"additionalPraId,omitempty"`
+
+       // Represents the list of EUTRAN cell Ids that constitutes the area. This IE shall be present if the Area of Interest subscribed is a list of EUTRAN cell Ids.
+       EcgiList *[]Ecgi `json:"ecgiList,omitempty"`
+
+       // Represents the list of NG RAN node identifiers that constitutes the area. This IE shall be present if the Area of Interest subscribed is a list of NG RAN node identifiers.
+       GlobalRanNodeIdList *[]GlobalRanNodeId `json:"globalRanNodeIdList,omitempty"`
+
+       // Represents the list of eNodeB identifiers that constitutes the area. This IE shall be present if the Area of Interest subscribed is a list of eNodeB identifiers.
+       GlobaleNbIdList *[]GlobalRanNodeId `json:"globaleNbIdList,omitempty"`
+
+       // Represents the list of NR cell Ids that constitutes the area. This IE shall be present if the Area of Interest subscribed is a list of NR cell Ids.
+       NcgiList *[]Ncgi `json:"ncgiList,omitempty"`
+
+       // Represents an identifier of the Presence Reporting Area (see clause 28.10 of
+       // 3GPP TS 23.003. This IE shall be present  if the Area of Interest subscribed or
+       // reported is a Presence Reporting Area or a Set of Core Network predefined Presence
+       // Reporting Areas. When present, it shall be encoded as a string representing an integer
+       // in the following ranges:
+       // - 0 to 8 388 607 for UE-dedicated PRA
+       // - 8 388 608 to 16 777 215 for Core Network predefined PRA
+       // Examples:
+       // PRA ID 123 is encoded as "123"
+       // PRA ID 11 238 660 is encoded as "11238660"
+       PraId *string `json:"praId,omitempty"`
+
+       // Possible values are:
+       // -IN_AREA: Indicates that the UE is inside or enters the presence reporting area.
+       // -OUT_OF_AREA: Indicates that the UE is outside or leaves the presence reporting area
+       // -UNKNOW: Indicates it is unknown whether the UE is in the presence reporting area or not
+       // -INACTIVE: Indicates that the presence reporting area is inactive in the serving node.
+       PresenceState *PresenceState `json:"presenceState,omitempty"`
+
+       // Represents the list of tracking areas that constitutes the area. This IE shall be present if the subscription or the event report  is for tracking UE presence in the tracking areas. For non 3GPP access the TAI shall be the N3GPP TAI.
+       TrackingAreaList *[]Tai `json:"trackingAreaList,omitempty"`
+}
+
+// Possible values are:
+// -IN_AREA: Indicates that the UE is inside or enters the presence reporting area.
+// -OUT_OF_AREA: Indicates that the UE is outside or leaves the presence reporting area
+// -UNKNOW: Indicates it is unknown whether the UE is in the presence reporting area or not
+// -INACTIVE: Indicates that the presence reporting area is inactive in the serving node.
+type PresenceState string
+
+// Provides additional information in an error response.
+type ProblemDetails struct {
+       // A machine-readable application error cause specific to this occurrence of the problem.  This IE should be present and provide application-related error information, if available.
+       Cause *string `json:"cause,omitempty"`
+
+       // A human-readable explanation specific to this occurrence of the problem.
+       Detail *string `json:"detail,omitempty"`
+
+       // String providing an URI formatted according to RFC 3986.
+       Instance      *Uri            `json:"instance,omitempty"`
+       InvalidParams *[]InvalidParam `json:"invalidParams,omitempty"`
+
+       // Fully Qualified Domain Name
+       NrfId  *Fqdn `json:"nrfId,omitempty"`
+       Status *int  `json:"status,omitempty"`
+
+       // A string used to indicate the features supported by an API that is used as defined in clause  6.6 in 3GPP TS 29.500. The string shall contain a bitmask indicating supported features in  hexadecimal representation Each character in the string shall take a value of "0" to "9",  "a" to "f" or "A" to "F" and shall represent the support of 4 features as described in  table 5.2.2-3. The most significant character representing the highest-numbered features shall  appear first in the string, and the character representing features 1 to 4 shall appear last  in the string. The list of features and their numbering (starting with 1) are defined  separately for each API. If the string contains a lower number of characters than there are  defined features for an API, all features that would be represented by characters that are not  present in the string are not supported.
+       SupportedFeatures *SupportedFeatures `json:"supportedFeatures,omitempty"`
+       Title             *string            `json:"title,omitempty"`
+
+       // String providing an URI formatted according to RFC 3986.
+       Type *Uri `json:"type,omitempty"`
+}
+
+// If the contentType attribute is set to "application/json", then this attribute describes  the attributes of the JSON object of the body.
+type Property struct {
+       // The name of the property
+       Name string `json:"name"`
+
+       // A regular expression string to be applied to the value of the property.
+       Regex *string `json:"regex,omitempty"`
+
+       // Indicates whether the property is required â€“ true= required â€“  false(default)= not required.
+       Required *bool `json:"required,omitempty"`
+
+       // The property value. When present, it shall be a valid JSON string.
+       Value *string `json:"value,omitempty"`
+}
+
+// Indicates whether the UE is authorized to use ProSe Direct Discovery, ProSe Direct Communication, or both.
+type ProseServiceAuth struct {
+       // Possible values are:
+       // - AUTHORIZED: Indicates that the UE is authorized.
+       // - NOT_AUTHORIZED: Indicates that the UE is not authorized.
+       ProseDirectCommunicationAuth *UeAuth `json:"proseDirectCommunicationAuth,omitempty"`
+
+       // Possible values are:
+       // - AUTHORIZED: Indicates that the UE is authorized.
+       // - NOT_AUTHORIZED: Indicates that the UE is not authorized.
+       ProseDirectDiscoveryAuth *UeAuth `json:"proseDirectDiscoveryAuth,omitempty"`
+}
+
+// Unsigned integer identifying a QoS flow, within the range 0 to 63.
+type Qfi int
+
+// This data type is defined in the same way as the 'Qfi' data type, but with the OpenAPI 'nullable: true' property.
+type QfiRm int
+
+// Contains QoS flows usage data information.
+type QosFlowUsageReport struct {
+       // string with format 'int64' as defined in OpenAPI.
+       DownlinkVolume Int64 `json:"downlinkVolume"`
+
+       // string with format 'date-time' as defined in OpenAPI.
+       EndTimeStamp DateTime `json:"endTimeStamp"`
+
+       // Unsigned integer identifying a QoS flow, within the range 0 to 63.
+       Qfi Qfi `json:"qfi"`
+
+       // string with format 'date-time' as defined in OpenAPI.
+       StartTimeStamp DateTime `json:"startTimeStamp"`
+
+       // string with format 'int64' as defined in OpenAPI.
+       UplinkVolume Int64 `json:"uplinkVolume"`
+}
+
+// The enumeration QosResourceType indicates whether a QoS Flow is non-GBR, delay critical GBR, or non-delay critical GBR (see clauses 5.7.3.4 and 5.7.3.5 of 3GPP TS 23.501). It shall comply with the provisions defined in table 5.5.3.6-1.
+type QosResourceType string
+
+// This enumeration is defined in the same way as the 'QosResourceType' enumeration, but with the OpenAPI 'nullable: true' property. "
+type QosResourceTypeRm interface{}
+
+// Indicates the radio access used.
+type RatType string
+
+// Provides information about the radio access but with the OpenAPI 'nullable: true' property.
+type RatTypeRm interface{}
+
+// Integer where the allowed values correspond to the value range of an unsigned 32-bit integer.
+type RatingGroup Uint32
+
+// The response shall include a Location header field containing a different URI  (pointing to a different URI of an other service instance), or the same URI if a request  is redirected to the same target resource via a different SCP.
+type RedirectResponse struct {
+       Cause *string `json:"cause,omitempty"`
+
+       // String providing an URI formatted according to RFC 3986.
+       TargetScp *Uri `json:"targetScp,omitempty"`
+
+       // String providing an URI formatted according to RFC 3986.
+       TargetSepp *Uri `json:"targetSepp,omitempty"`
+}
+
+// This parameter provides information about the referenced binary body data.
+type RefToBinaryData struct {
+       // This IE shall contain the value of the Content-ID header of the referenced binary body part.
+       ContentId string `json:"contentId"`
+}
+
+// This data type is defined in the same way as the ' RefToBinaryData ' data type, but with the OpenAPI 'nullable: true' property.
+type RefToBinaryDataRm interface{}
+
+// The enumeration ReflectiveQosAttribute indicates whether certain traffic of the QoS flow may be subject to Reflective QoS (see clause 5.7.2.3 of 3GPP TS 23.501). It shall comply with the provisions defined in table 5.5.3.3-1.
+type ReflectiveQoSAttribute string
+
+// This enumeration is defined in the same way as the 'ReflectiveQosAttribute' enumeration, but with the OpenAPI 'nullable: true' property. "
+type ReflectiveQoSAttributeRm interface{}
+
+// Relay Service Code to identify a connectivity service provided by the UE-to-Network relay.
+type RelayServiceCode int
+
+// The enumeration ReportAmountMdt defines Report Amount for MDT in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.10-1.
+type ReportAmountMdt string
+
+// The enumeration ReportIntervalMdt defines Report Interval for MDT in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.9-1.
+type ReportIntervalMdt string
+
+// The enumeration ReportIntervalNrMdt defines Report Interval in NR for MDT in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.17-1.
+type ReportIntervalNrMdt string
+
+// indicates performed modivications.
+type ReportItem struct {
+       // Contains a JSON pointer value (as defined in IETF RFC 6901) that references a  location of a resource to which the modification is subject.
+       Path string `json:"path"`
+
+       // A human-readable reason providing details on the reported modification failure.  The reason string should identify the operation that failed using the operation's  array index to assist in correlation of the invalid parameter with the failed  operation, e.g. "Replacement value invalid for attribute (failed operation index= 4)".
+       Reason *string `json:"reason,omitempty"`
+}
+
+// The enumeration ReportTypeMdt defines Report Type for logged MDT in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.4-1.
+type ReportTypeMdt string
+
+// The enumeration ReportingTrigger defines Reporting Triggers for MDT in the trace. See 3GPP TS 32.42] for further  description of the values. It shall comply with the provisions defined in table 5.6.3.8-1.
+type ReportingTrigger string
+
+// It contains the restriction type ALLOWED_AREAS or NOT_ALLOWED_AREAS.
+type RestrictionType string
+
+// It contains the restriction type ALLOWED_AREAS or NOT_ALLOWED_AREAS but with the OpenAPI 'nullable: true' property.
+type RestrictionTypeRm interface{}
+
+// Unsigned integer representing the "Subscriber Profile ID for RAT/Frequency Priority"  as specified in 3GPP TS 36.413.
+type RfspIndex int
+
+// Unsigned integer representing the 'Subscriber Profile ID for RAT/Frequency Priority'  as specified in 3GPP TS 36.413 with the OpenAPI 'nullable: true' property.
+type RfspIndexRm int
+
+// string with format 'bytes' as defined in OpenAPI
+type RgWirelineCharacteristics Bytes
+
+// This data type is defined in the same way as the 'RgWirelineCharacteristics' data type, but with the OpenAPI 'nullable: true' property.
+type RgWirelineCharacteristicsRm interface{}
+
+// The enumeration RoamingOdb defines the Barring of Roaming as. See 3GPP TS 23.015 for further description. It shall comply with the provisions defined in table 5.7.3.1-1.
+type RoamingOdb string
+
+// Indicates if access is allowed to a given serving network, e.g. a PLMN (MCC, MNC) or an  SNPN (MCC, MNC, NID).
+type RoamingRestrictions struct {
+       AccessAllowed *bool `json:"accessAllowed,omitempty"`
+}
+
+// At least one of the "ipv4Addr" attribute and the "ipv6Addr" attribute shall be included in the "RouteInformation" data type.
+type RouteInformation struct {
+       // String identifying a IPv4 address formatted in the 'dotted decimal' notation as defined in RFC 1166.
+       Ipv4Addr *Ipv4Addr `json:"ipv4Addr,omitempty"`
+
+       // String identifying an IPv6 address formatted according to clause 4 of RFC5952. The mixed IPv4 IPv6 notation according to clause 5 of RFC5952 shall not be used.
+       Ipv6Addr *Ipv6Addr `json:"ipv6Addr,omitempty"`
+
+       // Unsigned Integer, i.e. only value 0 and integers above 0 are permissible.
+       PortNumber Uinteger `json:"portNumber"`
+}
+
+// At least one of the "routeInfo" attribute and the "routeProfId" attribute shall be included in the "RouteToLocation" data type.
+type RouteToLocation interface{}
+
+// Contains a Routing Area Identification as defined in 3GPP TS 23.003, clause 4.2.
+type RoutingAreaId struct {
+       // Location Area Code
+       Lac string `json:"lac"`
+
+       // When PlmnId needs to be converted to string (e.g. when used in maps as key), the string  shall be composed of three digits "mcc" followed by "-" and two or three digits "mnc".
+       PlmnId PlmnId `json:"plmnId"`
+
+       // Routing Area Code
+       Rac string `json:"rac"`
+}
+
+// Contains the network slice status information in terms of the current number of UEs registered  with a network slice, the current number of PDU Sessions established on a network slice or both.
+type SACEventStatus struct {
+       // Represents threshold(s) to control the triggering of network slice reporting notifications or the information contained in the network slice reporting notification.
+       ReachedNumPduSess *SACInfo `json:"reachedNumPduSess,omitempty"`
+
+       // Represents threshold(s) to control the triggering of network slice reporting notifications or the information contained in the network slice reporting notification.
+       ReachedNumUes *SACInfo `json:"reachedNumUes,omitempty"`
+}
+
+// Represents threshold(s) to control the triggering of network slice reporting notifications or the information contained in the network slice reporting notification.
+type SACInfo struct {
+       NumericValNumPduSess *int `json:"numericValNumPduSess,omitempty"`
+       NumericValNumUes     *int `json:"numericValNumUes,omitempty"`
+       PercValueNumPduSess  *int `json:"percValueNumPduSess,omitempty"`
+       PercValueNumUes      *int `json:"percValueNumUes,omitempty"`
+}
+
+// Unsigned integer indicating Sampling Ratio (see clauses 4.15.1 of 3GPP TS 23.502), expressed in percent.
+type SamplingRatio int
+
+// This data type is defined in the same way as the 'SamplingRatio' data type, but with the  OpenAPI 'nullable: true' property.
+type SamplingRatioRm int
+
+// Indicates the satellite backhaul used.
+type SatelliteBackhaulCategory string
+
+// Provides information about the satellite backhaul but with the OpenAPI 'nullable: true' property.
+type SatelliteBackhaulCategoryRm interface{}
+
+// Identifies time and day of the week when the UE is available for communication.
+type ScheduledCommunicationTime struct {
+       // Identifies the day(s) of the week. If absent, it indicates every day of the week.
+       DaysOfWeek *[]DayOfWeek `json:"daysOfWeek,omitempty"`
+
+       // String with format partial-time or full-time as defined in clause 5.6 of IETF RFC 3339. Examples, 20:15:00, 20:15:00-08:00 (for 8 hours behind UTC).
+       TimeOfDayEnd *TimeOfDay `json:"timeOfDayEnd,omitempty"`
+
+       // String with format partial-time or full-time as defined in clause 5.6 of IETF RFC 3339. Examples, 20:15:00, 20:15:00-08:00 (for 8 hours behind UTC).
+       TimeOfDayStart *TimeOfDay `json:"timeOfDayStart,omitempty"`
+}
+
+// This data type is defined in the same way as the 'ScheduledCommunicationTime' data type, but with the OpenAPI 'nullable: true' property.
+type ScheduledCommunicationTimeRm interface{}
+
+// Possible values are:
+// -DOWNLINK_ONLY: Downlink only
+// -UPLINK_ONLY: Uplink only
+// -BIDIRECTIONA: Bi-directional
+type ScheduledCommunicationType string
+
+// This enumeration is defined in the same way as the 'ScheduledCommunicationTypen' enumeration, but with the OpenAPI 'nullable: true' property."
+type ScheduledCommunicationTypeRm interface{}
+
+// A range of SDs (Slice Differentiators)
+type SdRange struct {
+       // Last value identifying the end of an SD range. This string shall be formatted as specified for the sd attribute of the Snssai data type in clause 5.4.4.2.
+       End *string `json:"end,omitempty"`
+
+       // First value identifying the start of an SD range. This string shall be formatted as specified for the sd attribute of the Snssai data type in clause 5.4.4.2.
+       Start *string `json:"start,omitempty"`
+}
+
+// Secondary RAT Usage Information to report usage data for a secondary RAT for QoS flows and/or the whole PDU session.
+type SecondaryRatUsageInfo struct {
+       PduSessionUsageData *[]VolumeTimedReport  `json:"pduSessionUsageData,omitempty"`
+       QosFlowsUsageData   *[]QosFlowUsageReport `json:"qosFlowsUsageData,omitempty"`
+
+       // Indicates the radio access used.
+       SecondaryRatType RatType `json:"secondaryRatType"`
+}
+
+// Secondary RAT Usage Report to report usage data for a secondary RAT for QoS flows.
+type SecondaryRatUsageReport struct {
+       QosFlowsUsageData []QosFlowUsageReport `json:"qosFlowsUsageData"`
+
+       // Indicates the radio access used.
+       SecondaryRatType RatType `json:"secondaryRatType"`
+}
+
+// It contains the URI of the linked resource.
+type SelfLink struct {
+       // It contains the URI of the linked resource.
+       Self Link `json:"self"`
+}
+
+// The enumeration SensorMeasurement defines sensor measurement type for MDT in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.7-1.
+type SensorMeasurement string
+
+// Contains addressing information (IP addresses and/or FQDNs) of a server.
+type ServerAddressingInfo interface{}
+
+// Contains a Service Area Identifier as defined in 3GPP TS 23.003, clause 12.5.
+type ServiceAreaId struct {
+       // Location Area Code.
+       Lac string `json:"lac"`
+
+       // When PlmnId needs to be converted to string (e.g. when used in maps as key), the string  shall be composed of three digits "mcc" followed by "-" and two or three digits "mnc".
+       PlmnId PlmnId `json:"plmnId"`
+
+       // Service Area Code.
+       Sac string `json:"sac"`
+}
+
+// ServiceAreaRestriction defines model for ServiceAreaRestriction.
+type ServiceAreaRestriction struct {
+       // Embedded fields due to inline allOf schema
+       // Embedded fields due to inline allOf schema
+       // Embedded fields due to inline allOf schema
+}
+
+// Integer where the allowed values correspond to the value range of an unsigned 32-bit integer.
+type ServiceId Uint32
+
+// MBR related to slice
+type SliceMbr struct {
+       // String representing a bit rate; the prefixes follow the standard symbols from The International System of Units, and represent x1000 multipliers, with the exception that prefix "K" is used to represent the standard symbol "k".
+       Downlink BitRate `json:"downlink"`
+
+       // String representing a bit rate; the prefixes follow the standard symbols from The International System of Units, and represent x1000 multipliers, with the exception that prefix "K" is used to represent the standard symbol "k".
+       Uplink BitRate `json:"uplink"`
+}
+
+// SliceMbr with nullable: true
+type SliceMbrRm interface{}
+
+// It indicates theSmall Data Rate Control Status
+type SmallDataRateStatus struct {
+       // When present, it shall indicate number of additional exception reports the AF is allowed to send downlink  in the given time unit for the given PDU session (see clause 5.31.14.3 in 3GPP TS 23.501
+       RemainExReportsDl *int `json:"remainExReportsDl,omitempty"`
+
+       // When present, it shall indicate number of additional exception reports the UE is allowed to send uplink in the given time  unit for  the given PDU session (see clause 5.31.14.3 of 3GPP TS 23.501.
+       RemainExReportsUl *int `json:"remainExReportsUl,omitempty"`
+
+       // When present it shall contain the number of packets the AF is allowed to send downlink in the given time unit for the given PDU session (see clause 5.31.14.3 of 3GPP TS 23.501.
+       RemainPacketsDl *int `json:"remainPacketsDl,omitempty"`
+
+       // When present, it shall contain the number of packets the UE is allowed to send uplink in the given time unit for the given PDU session (see clause 5.31.14.3 of 3GPP TS 23.501.
+       RemainPacketsUl *int `json:"remainPacketsUl,omitempty"`
+
+       // string with format 'date-time' as defined in OpenAPI.
+       ValidityTime *DateTime `json:"validityTime,omitempty"`
+}
+
+// When Snssai needs to be converted to string (e.g. when used in maps as key), the string shall be composed of one to three digits "sst" optionally followed by "-" and 6 hexadecimal digits "sd".
+type Snssai struct {
+       // 3-octet string, representing the Slice Differentiator, in hexadecimal representation. Each character in the string shall take a value of "0" to "9", "a" to "f" or "A" to "F" and shall represent 4 bits. The most significant character representing the 4 most significant bits of the SD shall appear first in the string, and the character representing the 4 least significant bit of the SD shall appear last in the string. This is an optional parameter that complements the Slice/Service type(s) to allow to  differentiate amongst multiple Network Slices of the same Slice/Service type. This IE shall be absent if no SD value is associated with the SST.
+       Sd *string `json:"sd,omitempty"`
+
+       // Unsigned integer, within the range 0 to 255, representing the Slice/Service Type.  It indicates the expected Network Slice behaviour in terms of features and services. Values 0 to 127 correspond to the standardized SST range. Values 128 to 255 correspond  to the Operator-specific range. See clause 28.4.2 of 3GPP TS 23.003. Standardized values are defined in clause 5.15.2.2 of 3GPP TS 23.501.
+       Sst int `json:"sst"`
+}
+
+// Extensions to the Snssai data type, sdRanges and wildcardSd shall not be present simultaneously
+type SnssaiExtension struct {
+       // When present, it shall contain the range(s) of Slice Differentiator values supported for the Slice/Service Type value indicated in the sst attribute of the Snssai data type
+       SdRanges *[]SdRange `json:"sdRanges,omitempty"`
+
+       // When present, it shall be set to true, to indicate that all SD values are supported for the Slice/Service Type value indicated in the sst attribute of the Snssai data type.
+       WildcardSd *bool `json:"wildcardSd,omitempty"`
+}
+
+// represents the service and session continuity mode It shall comply with the provisions defined in table 5.4.3.6-1.
+type SscMode string
+
+// represents the service and session continuity mode It shall comply with the provisions defined in table 5.4.3.6-1 but with the OpenAPI 'nullable: true' property.
+type SscModeRm interface{}
+
+// Source specific IP multicast address
+type Ssm struct {
+       // Contains an IP adresse.
+       DestIpAddr IpAddr `json:"destIpAddr"`
+
+       // Contains an IP adresse.
+       SourceIpAddr IpAddr `json:"sourceIpAddr"`
+}
+
+// Possible values are:
+// - STATIONARY: Identifies the UE is stationary
+// - MOBILE: Identifies the UE is mobile
+type StationaryIndication string
+
+// This enumeration is defined in the same way as the 'StationaryIndication' enumeration, but with the OpenAPI 'nullable: true' property."
+type StationaryIndicationRm interface{}
+
+// String representing the STN-SR as defined in clause 18.6 of 3GPP TS 23.003.
+type StnSr string
+
+// String representing the STN-SR as defined in clause 18.6 of 3GPP TS 23.003 with the OpenAPI 'nullable: true' property.
+type StnSrRm string
+
+// A String with Matching Operator
+type StringMatchingCondition struct {
+       // the matching operation.
+       MatchingOperator MatchingOperator `json:"matchingOperator"`
+       MatchingString   *string          `json:"matchingString,omitempty"`
+}
+
+// A list of conditions for string matching
+type StringMatchingRule struct {
+       StringMatchingConditions *[]StringMatchingCondition `json:"stringMatchingConditions,omitempty"`
+}
+
+// Provides the subsribed 5QI and the ARP, it may contain the priority level.
+type SubscribedDefaultQos struct {
+       // Unsigned integer representing a 5G QoS Identifier (see clause 5.7.2.1 of 3GPP TS 23.501, within the range 0 to 255.
+       N5qi N5Qi `json:"5qi"`
+
+       // Contains Allocation and Retention Priority information.
+       Arp Arp `json:"arp"`
+
+       // Unsigned integer indicating the 5QI Priority Level (see clauses 5.7.3.3 and 5.7.4 of 3GPP TS 23.501, within the range 1 to 127.Values are ordered in decreasing order of priority,  i.e. with 1 as the highest priority and 127 as the lowest priority.
+       PriorityLevel *N5QiPriorityLevel `json:"priorityLevel,omitempty"`
+}
+
+// String identifying a Supi that shall contain either an IMSI, a network specific identifier,
+// a Global Cable Identifier (GCI) or a Global Line Identifier (GLI) as specified in clause
+// 2.2A of 3GPP TS 23.003. It shall be formatted as follows
+//   - for an IMSI "imsi-<imsi>", where <imsi> shall be formatted according to clause 2.2
+//     of 3GPP TS 23.003 that describes an IMSI.
+//   - for a network specific identifier "nai-<nai>, where <nai> shall be formatted
+//     according to clause 28.7.2 of 3GPP TS 23.003 that describes an NAI.
+//   - for a GCI "gci-<gci>", where <gci> shall be formatted according to clause 28.15.2
+//     of 3GPP TS 23.003.
+//   - for a GLI "gli-<gli>", where <gli> shall be formatted according to clause 28.16.2 of
+//     3GPP TS 23.003.To enable that the value is used as part of an URI, the string shall
+//     only contain characters allowed according to the "lower-with-hyphen" naming convention
+//     defined in 3GPP TS 29.501.
+type Supi string
+
+// String identifying a SUPI or a SUCI.
+type SupiOrSuci string
+
+// This data type is defined in the same way as the 'Supi' data type, but with the  OpenAPI 'nullable: true' property.
+type SupiRm string
+
+// A string used to indicate the features supported by an API that is used as defined in clause  6.6 in 3GPP TS 29.500. The string shall contain a bitmask indicating supported features in  hexadecimal representation Each character in the string shall take a value of "0" to "9",  "a" to "f" or "A" to "F" and shall represent the support of 4 features as described in  table 5.2.2-3. The most significant character representing the highest-numbered features shall  appear first in the string, and the character representing features 1 to 4 shall appear last  in the string. The list of features and their numbering (starting with 1) are defined  separately for each API. If the string contains a lower number of characters than there are  defined features for an API, all features that would be represented by characters that are not  present in the string are not supported.
+type SupportedFeatures string
+
+// 2 or 3-octet string identifying a tracking area code as specified in clause 9.3.3.10  of 3GPP TS 38.413, in hexadecimal representation. Each character in the string shall  take a value of "0" to "9", "a" to "f" or "A" to "F" and shall represent 4 bits. The most significant character representing the 4 most significant bits of the TAC shall  appear first in the string, and the character representing the 4 least significant bit  of the TAC shall appear last in the string.
+type Tac string
+
+// contains tracking area information (tracking area codes).
+type TacInfo struct {
+       TacList []Tac `json:"tacList"`
+}
+
+// This data type is defined in the same way as the 'Tac' data type, but with the OpenAPI 'nullable: true' property.
+type TacRm string
+
+// Contains the tracking area identity as described in 3GPP 23.003
+type Tai struct {
+       // This represents the Network Identifier, which together with a PLMN ID is used to identify an SNPN (see 3GPP TS 23.003 and 3GPP TS 23.501 clause 5.30.2.1).
+       Nid *Nid `json:"nid,omitempty"`
+
+       // When PlmnId needs to be converted to string (e.g. when used in maps as key), the string  shall be composed of three digits "mcc" followed by "-" and two or three digits "mnc".
+       PlmnId PlmnId `json:"plmnId"`
+
+       // 2 or 3-octet string identifying a tracking area code as specified in clause 9.3.3.10  of 3GPP TS 38.413, in hexadecimal representation. Each character in the string shall  take a value of "0" to "9", "a" to "f" or "A" to "F" and shall represent 4 bits. The most significant character representing the 4 most significant bits of the TAC shall  appear first in the string, and the character representing the 4 least significant bit  of the TAC shall appear last in the string.
+       Tac Tac `json:"tac"`
+}
+
+// This data type is defined in the same way as the 'Tai' data type, but with the OpenAPI 'nullable: true' property.
+type TaiRm interface{}
+
+// String with format partial-time or full-time as defined in clause 5.6 of IETF RFC 3339. Examples, 20:15:00, 20:15:00-08:00 (for 8 hours behind UTC).
+type TimeOfDay string
+
+// String with format "time-numoffset" optionally appended by "daylightSavingTime", where
+//   - "time-numoffset" shall represent the time zone adjusted for daylight saving time and be
+//     encoded as time-numoffset as defined in clause 5.6 of IETF RFC 3339;
+//   - "daylightSavingTime" shall represent the adjustment that has been made and shall be
+//     encoded as "+1" or "+2" for a +1 or +2 hours adjustment.
+//
+// The example is for 8 hours behind UTC, +1 hour adjustment for Daylight Saving Time.
+type TimeZone string
+
+// "String with format 'time-numoffset' optionally appended by '<daylightSavingTime>', where
+//
+//   - 'time-numoffset' shall represent the time zone adjusted for daylight saving time and be
+//     encoded as time-numoffset as defined in clause 5.6 of IETF RFC 3339;
+//
+//   - 'daylightSavingTime' shall represent the adjustment that has been made and shall be
+//     encoded as '+1' or '+2' for a +1 or +2 hours adjustment.
+//
+//     But with the OpenAPI 'nullable: true' property."
+type TimeZoneRm string
+
+// Temporary Mobile Group Identity
+type Tmgi struct {
+       // MBS Service ID
+       MbsServiceId string `json:"mbsServiceId"`
+
+       // When PlmnId needs to be converted to string (e.g. when used in maps as key), the string  shall be composed of three digits "mcc" followed by "-" and two or three digits "mnc".
+       PlmnId PlmnId `json:"plmnId"`
+}
+
+// Contain the TNAP Identifier see clause5.6.2 of 3GPP TS 23.501.
+type TnapId struct {
+       // When present, it shall contain the BSSID of the access point to which the UE is attached, that is received over NGAP, see IEEE Std 802.11-2012.
+       BssId *string `json:"bssId,omitempty"`
+
+       // string with format 'bytes' as defined in OpenAPI
+       CivicAddress *Bytes `json:"civicAddress,omitempty"`
+
+       // This IE shall be present if the UE is accessing the 5GC via a trusted WLAN access network.When present, it shall contain the SSID of the access point to which the UE is attached, that is received over NGAP,  see IEEE Std 802.11-2012.
+       SsId *string `json:"ssId,omitempty"`
+}
+
+// This data type is defined in the same way as the 'TnapId' data type, but with the OpenAPI 'nullable: true' property.
+type TnapIdRm interface{}
+
+// This represents the identifier of the TNGF ID as specified in clause 9.3.1.161 of  3GPP TS 38.413  in hexadecimal representation. Each character in the string shall take a value of "0" to "9", "a"  to "f" or "A" to "F" and shall represent 4 bits. The most significant character representing the  4 most significant bits of the TNGF ID shall appear first in the string, and the character  representing the 4 least significant bit of the TNGF ID shall appear last in the string.
+type TngfId string
+
+// contains Trace control and configuration parameters.
+type TraceData struct {
+       // String identifying a IPv4 address formatted in the 'dotted decimal' notation as defined in RFC 1166.
+       CollectionEntityIpv4Addr *Ipv4Addr `json:"collectionEntityIpv4Addr,omitempty"`
+
+       // String identifying an IPv6 address formatted according to clause 4 of RFC5952. The mixed IPv4 IPv6 notation according to clause 5 of RFC5952 shall not be used.
+       CollectionEntityIpv6Addr *Ipv6Addr `json:"collectionEntityIpv6Addr,omitempty"`
+
+       // Triggering events (see 3GPP TS 32.422).It shall be encoded as an octet string in hexadecimal representation. Each character in the string shall take a value of "0" to "9", "a" to "f" or "A" to "F" and shall represent 4 bits. The most significant character representing the 4 most significant bits shall appear first in the string, and the character representing the 4 least significant bit shall appear last in the string. Octets shall be coded according to 3GPP TS 32.422.
+       EventList string `json:"eventList"`
+
+       // List of Interfaces (see 3GPP TS 32.422).It shall be encoded as an octet string in hexadecimal representation. Each character in the string shall take a value of "0" to "9", "a" to "f" or "A" to "F" and shall represent 4 bits. The most significant character representing the 4 most significant bits shall appear first in the string, and the character representing the  4 least significant bit shall appear last in the string. Octets shall be coded according to 3GPP TS 32.422. If this attribute is not present, all the interfaces applicable to the list of NE types indicated in the neTypeList attribute should be traced.
+       InterfaceList *string `json:"interfaceList,omitempty"`
+
+       // List of NE Types (see 3GPP TS 32.422).It shall be encoded as an octet string in hexadecimal representation. Each character in the string shall take a value of "0" to "9", "a" to "f" or "A" to "F" and shall represent 4 bits. The most significant character representing the 4 most significant bits shall appear first in the string, and the character representing the 4 least significant bit shall appear last in the string.Octets shall be coded according to 3GPP TS 32.422.
+       NeTypeList string `json:"neTypeList"`
+
+       // The enumeration TraceDepth defines how detailed information should be recorded in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.1-1
+       TraceDepth TraceDepth `json:"traceDepth"`
+
+       // Trace Reference (see 3GPP TS 32.422).It shall be encoded as the concatenation of MCC, MNC and Trace ID as follows: 'MCC'<MNC'-'Trace ID'The Trace ID shall be encoded as a 3 octet string in hexadecimal representation. Each character in the Trace ID string shall take a value of "0" to "9", "a" to "f" or "A" to "F" and shall represent 4 bits. The most significant character representing the 4 most significant bits of the Trace ID shall appear first  in the string, and the character representing the 4 least significant bit of the Trace ID shall appear last in the string.
+       TraceRef string `json:"traceRef"`
+}
+
+// The enumeration TraceDepth defines how detailed information should be recorded in the trace. See 3GPP TS 32.422 for further description of the values. It shall comply with the provisions defined in table 5.6.3.1-1
+type TraceDepth string
+
+// This enumeration is defined in the same way as the 'TraceDepth' enumeration, but with the OpenAPI 'nullable: true' property.
+type TraceDepthRm interface{}
+
+// Possible values are:
+//   - SINGLE_TRANS_UL: Uplink single packet transmission.
+//   - SINGLE_TRANS_DL: Downlink single packet transmission.
+//   - DUAL_TRANS_UL_FIRST: Dual packet transmission, firstly uplink packet transmission
+//     with subsequent downlink packet transmission.
+//   - DUAL_TRANS_DL_FIRST: Dual packet transmission, firstly downlink packet transmission
+//     with subsequent uplink packet transmission.
+type TrafficProfile string
+
+// This enumeration is defined in the same way as the 'TrafficProfile' enumeration, but with the OpenAPI 'nullable: true' property.
+type TrafficProfileRm interface{}
+
+// Possible values are:
+// - UDP: User Datagram Protocol.
+// - TCP: Transmission Control Protocol.
+type TransportProtocol string
+
+// Tunnel address
+type TunnelAddress interface{}
+
+// Contain the TWAP Identifier as defined in clause 4.2.8.5.3 of 3GPP TS 23.501 or the WLAN location information as defined in clause 4.5.7.2.8 of 3GPP TS 23.402.
+type TwapId struct {
+       // When present, it shall contain the BSSID of the access point to which the UE is attached, for trusted WLAN access, see IEEE Std 802.11-2012.
+       BssId *string `json:"bssId,omitempty"`
+
+       // string with format 'bytes' as defined in OpenAPI
+       CivicAddress *Bytes `json:"civicAddress,omitempty"`
+
+       // This IE shall contain the SSID of the access point to which the UE is attached, that is received over NGAP, see IEEE Std 802.11-2012.
+       SsId string `json:"ssId"`
+}
+
+// This data type is defined in the same way as the 'TwapId' data type, but with the OpenAPI 'nullable: true' property.
+type TwapIdRm interface{}
+
+// Type Allocation Code (TAC) of the UE, comprising the initial eight-digit portion of the 15-digit IMEI and 16-digit IMEISV codes. See clause 6.2 of 3GPP TS 23.003.
+type TypeAllocationCode string
+
+// Possible values are:
+// - AUTHORIZED: Indicates that the UE is authorized.
+// - NOT_AUTHORIZED: Indicates that the UE is not authorized.
+type UeAuth string
+
+// Integer where the allowed values correspond to the value range of an unsigned 16-bit integer.
+type Uint16 int
+
+// Integer where the allowed values correspond to the value range of an unsigned  16-bit integer with the OpenAPI 'nullable: true' property.
+type Uint16Rm int
+
+// Integer where the allowed values correspond to the value range of an unsigned 32-bit integer.
+type Uint32 int
+
+// Integer where the allowed values correspond to the value range of an unsigned 32-bit integer with the OpenAPI 'nullable: true' property.
+type Uint32Rm int32
+
+// Integer where the allowed values correspond to the value range of an unsigned 64-bit integer.
+type Uint64 int
+
+// Integer where the allowed values correspond to the value range of an unsigned 16-bit integer with the OpenAPI 'nullable: true' property.
+type Uint64Rm int
+
+// Unsigned Integer, i.e. only value 0 and integers above 0 are permissible.
+type Uinteger int
+
+// Unsigned Integer, i.e. only value 0 and integers above 0 are permissible with the OpenAPI 'nullable: true' property.
+type UintegerRm int
+
+// indicates whether UP confidentiality protection is required, preferred or not needed for all the traffic on the PDU Session. It shall comply with the provisions defined in table 5.4.3.5-1.
+type UpConfidentiality string
+
+// indicates whether UP integrity protection is required, preferred or not needed for all the  traffic on the PDU Session. It shall comply with the provisions defined in table 5.4.3.4-1, but with the OpenAPI 'nullable: true' property.
+type UpConfidentialityRm interface{}
+
+// indicates whether UP integrity protection is required, preferred or not needed for all the traffic on the PDU Session. It shall comply with the provisions defined in  table 5.4.3.4-1.
+type UpIntegrity string
+
+// indicates whether UP integrity protection is required, preferred or not needed for all the traffic on the PDU Session. It shall comply with the provisions defined in table 5.4.3.4-1.
+type UpIntegrityRm interface{}
+
+// Contains Userplain security information.
+type UpSecurity struct {
+       // indicates whether UP confidentiality protection is required, preferred or not needed for all the traffic on the PDU Session. It shall comply with the provisions defined in table 5.4.3.5-1.
+       UpConfid UpConfidentiality `json:"upConfid"`
+
+       // indicates whether UP integrity protection is required, preferred or not needed for all the traffic on the PDU Session. It shall comply with the provisions defined in  table 5.4.3.4-1.
+       UpIntegr UpIntegrity `json:"upIntegr"`
+}
+
+// This data type is defined in the same way as the 'UpSecurity' data type, but with the OpenAPI 'nullable: true' property.
+type UpSecurityRm interface{}
+
+// String providing an URI formatted according to RFC 3986.
+type Uri string
+
+// String providing an URI formatted according to RFC 3986 with the OpenAPI 'nullable: true' property.
+type UriRm string
+
+// HTTP and HTTPS URI scheme.
+type UriScheme string
+
+// At least one of eutraLocation, nrLocation and n3gaLocation shall be present. Several of them may be present.
+type UserLocation struct {
+       // Contains the E-UTRA user location.
+       EutraLocation *EutraLocation `json:"eutraLocation,omitempty"`
+
+       // Exactly one of cgi, sai or lai shall be present.
+       GeraLocation *GeraLocation `json:"geraLocation,omitempty"`
+
+       // Contains the Non-3GPP access user location.
+       N3gaLocation *N3gaLocation `json:"n3gaLocation,omitempty"`
+
+       // Contains the NR user location.
+       NrLocation *NrLocation `json:"nrLocation,omitempty"`
+
+       // Exactly one of cgi, sai or lai shall be present.
+       UtraLocation *UtraLocation `json:"utraLocation,omitempty"`
+}
+
+// Exactly one of cgi, sai or lai shall be present.
+type UtraLocation interface{}
+
+// String represents the SUPI or GPSI
+type VarUeId string
+
+// String represents the SUPI or GPSI with the OpenAPI 'nullable: true' property.
+type VarUeIdRm string
+
+// Contains Usage data information.
+type VolumeTimedReport struct {
+       // string with format 'int64' as defined in OpenAPI.
+       DownlinkVolume Int64 `json:"downlinkVolume"`
+
+       // string with format 'date-time' as defined in OpenAPI.
+       EndTimeStamp DateTime `json:"endTimeStamp"`
+
+       // string with format 'date-time' as defined in OpenAPI.
+       StartTimeStamp DateTime `json:"startTimeStamp"`
+
+       // string with format 'int64' as defined in OpenAPI.
+       UplinkVolume Int64 `json:"uplinkVolume"`
+}
+
+// This represents the identifier of the W-AGF ID as specified in clause 9.3.1.162 of  3GPP TS 38.413 in hexadecimal representation. Each character in the string shall take a value  of "0" to "9", "a" to "f" or "A" to "F" and shall represent 4 bits. The most significant  character representing the 4 most significant bits of the W-AGF ID shall appear first in the  string, and the character representing the 4 least significant bit of the W-AGF ID shall  appear last in the string.
+type WAgfId string
+
+// String representing the Wildcard DNN. It shall contain the string "*".
+type WildcardDnn string
+
+// String representing the Wildcard DNN. It shall contain the string '*' but with the  OpenAPI 'nullable: true' property.
+type WildcardDnnRm string
+
+// One and only one of the "globLineIds", "hfcNIds", "areaCodeB" and "areaCodeC" attributes shall be included in a WirelineArea data structure
+type WirelineArea struct {
+       // Values are operator specific.
+       AreaCodeB *AreaCode `json:"areaCodeB,omitempty"`
+
+       // Values are operator specific.
+       AreaCodeC     *AreaCode `json:"areaCodeC,omitempty"`
+       GlobalLineIds *[]Gli    `json:"globalLineIds,omitempty"`
+       HfcNIds       *[]HfcNId `json:"hfcNIds,omitempty"`
+}
+
+// The "restrictionType" attribute and the "areas" attribute shall be either both present or absent.  The empty array of areas is used when service is allowed/restricted nowhere.
+type WirelineServiceAreaRestriction struct {
+       Areas *[]WirelineArea `json:"areas,omitempty"`
+
+       // It contains the restriction type ALLOWED_AREAS or NOT_ALLOWED_AREAS.
+       RestrictionType *RestrictionType `json:"restrictionType,omitempty"`
+}
+
+// The response shall include a Location header field containing a different URI  (pointing to a different URI of an other service instance), or the same URI if a request  is redirected to the same target resource via a different SCP.
+type N307 RedirectResponse
+
+// The response shall include a Location header field containing a different URI  (pointing to a different URI of an other service instance), or the same URI if a request  is redirected to the same target resource via a different SCP.
+type N308 RedirectResponse
+
+// Getter for additional properties for AreaScope_TacInfoPerPlmn. Returns the specified
+// element and whether it was found
+func (a AreaScope_TacInfoPerPlmn) Get(fieldName string) (value TacInfo, found bool) {
+       if a.AdditionalProperties != nil {
+               value, found = a.AdditionalProperties[fieldName]
+       }
+       return
+}
+
+// Setter for additional properties for AreaScope_TacInfoPerPlmn
+func (a *AreaScope_TacInfoPerPlmn) Set(fieldName string, value TacInfo) {
+       if a.AdditionalProperties == nil {
+               a.AdditionalProperties = make(map[string]TacInfo)
+       }
+       a.AdditionalProperties[fieldName] = value
+}
+
+// Override default JSON handling for AreaScope_TacInfoPerPlmn to handle AdditionalProperties
+func (a *AreaScope_TacInfoPerPlmn) UnmarshalJSON(b []byte) error {
+       object := make(map[string]json.RawMessage)
+       err := json.Unmarshal(b, &object)
+       if err != nil {
+               return err
+       }
+
+       if len(object) != 0 {
+               a.AdditionalProperties = make(map[string]TacInfo)
+               for fieldName, fieldBuf := range object {
+                       var fieldVal TacInfo
+                       err := json.Unmarshal(fieldBuf, &fieldVal)
+                       if err != nil {
+                               return fmt.Errorf("error unmarshaling field %s: %w", fieldName, err)
+                       }
+                       a.AdditionalProperties[fieldName] = fieldVal
+               }
+       }
+       return nil
+}
+
+// Override default JSON handling for AreaScope_TacInfoPerPlmn to handle AdditionalProperties
+func (a AreaScope_TacInfoPerPlmn) MarshalJSON() ([]byte, error) {
+       var err error
+       object := make(map[string]json.RawMessage)
+
+       for fieldName, field := range a.AdditionalProperties {
+               object[fieldName], err = json.Marshal(field)
+               if err != nil {
+                       return nil, fmt.Errorf("error marshaling '%s': %w", fieldName, err)
+               }
+       }
+       return json.Marshal(object)
+}
+
+// Getter for additional properties for MbsSecurityContext_KeyList. Returns the specified
+// element and whether it was found
+func (a MbsSecurityContext_KeyList) Get(fieldName string) (value MbsKeyInfo, found bool) {
+       if a.AdditionalProperties != nil {
+               value, found = a.AdditionalProperties[fieldName]
+       }
+       return
+}
+
+// Setter for additional properties for MbsSecurityContext_KeyList
+func (a *MbsSecurityContext_KeyList) Set(fieldName string, value MbsKeyInfo) {
+       if a.AdditionalProperties == nil {
+               a.AdditionalProperties = make(map[string]MbsKeyInfo)
+       }
+       a.AdditionalProperties[fieldName] = value
+}
+
+// Override default JSON handling for MbsSecurityContext_KeyList to handle AdditionalProperties
+func (a *MbsSecurityContext_KeyList) UnmarshalJSON(b []byte) error {
+       object := make(map[string]json.RawMessage)
+       err := json.Unmarshal(b, &object)
+       if err != nil {
+               return err
+       }
+
+       if len(object) != 0 {
+               a.AdditionalProperties = make(map[string]MbsKeyInfo)
+               for fieldName, fieldBuf := range object {
+                       var fieldVal MbsKeyInfo
+                       err := json.Unmarshal(fieldBuf, &fieldVal)
+                       if err != nil {
+                               return fmt.Errorf("error unmarshaling field %s: %w", fieldName, err)
+                       }
+                       a.AdditionalProperties[fieldName] = fieldVal
+               }
+       }
+       return nil
+}
+
+// Override default JSON handling for MbsSecurityContext_KeyList to handle AdditionalProperties
+func (a MbsSecurityContext_KeyList) MarshalJSON() ([]byte, error) {
+       var err error
+       object := make(map[string]json.RawMessage)
+
+       for fieldName, field := range a.AdditionalProperties {
+               object[fieldName], err = json.Marshal(field)
+               if err != nil {
+                       return nil, fmt.Errorf("error marshaling '%s': %w", fieldName, err)
+               }
+       }
+       return json.Marshal(object)
+}
+
+// Base64 encoded, gzipped, json marshaled Swagger object
+var swaggerSpec = []string{
+
+       "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",
+}
+
+// GetSwagger returns the content of the embedded swagger specification file
+// or error if failed to decode
+func decodeSpec() ([]byte, error) {
+       zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, ""))
+       if err != nil {
+               return nil, fmt.Errorf("error base64 decoding spec: %s", err)
+       }
+       zr, err := gzip.NewReader(bytes.NewReader(zipped))
+       if err != nil {
+               return nil, fmt.Errorf("error decompressing spec: %s", err)
+       }
+       var buf bytes.Buffer
+       _, err = buf.ReadFrom(zr)
+       if err != nil {
+               return nil, fmt.Errorf("error decompressing spec: %s", err)
+       }
+
+       return buf.Bytes(), nil
+}
+
+var rawSpec = decodeSpecCached()
+
+// a naive cached of a decoded swagger spec
+func decodeSpecCached() func() ([]byte, error) {
+       data, err := decodeSpec()
+       return func() ([]byte, error) {
+               return data, err
+       }
+}
+
+// Constructs a synthetic filesystem for resolving external references when loading openapi specifications.
+func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) {
+       var res = make(map[string]func() ([]byte, error))
+       if len(pathToFile) > 0 {
+               res[pathToFile] = rawSpec
+       }
+
+       return res
+}
+
+// GetSwagger returns the Swagger specification corresponding to the generated code
+// in this file. The external references of Swagger specification are resolved.
+// The logic of resolving external references is tightly connected to "import-mapping" feature.
+// Externally referenced files must be embedded in the corresponding golang packages.
+// Urls can be supported but this task was out of the scope.
+func GetSwagger() (swagger *openapi3.T, err error) {
+       var resolvePath = PathToRawSpec("")
+
+       loader := openapi3.NewLoader()
+       loader.IsExternalRefsAllowed = true
+       loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) {
+               var pathToFile = url.String()
+               pathToFile = path.Clean(pathToFile)
+               getSpec, ok := resolvePath[pathToFile]
+               if !ok {
+                       err1 := fmt.Errorf("path not found: %s", pathToFile)
+                       return nil, err1
+               }
+               return getSpec()
+       }
+       var specData []byte
+       specData, err = rawSpec()
+       if err != nil {
+               return
+       }
+       swagger, err = loader.LoadFromData(specData)
+       if err != nil {
+               return
+       }
+       return
+}
diff --git a/servicemanager/internal/discoverservice/discoverservice.go b/servicemanager/internal/discoverservice/discoverservice.go
new file mode 100644 (file)
index 0000000..b6a1681
--- /dev/null
@@ -0,0 +1,99 @@
+// -
+//   ========================LICENSE_START=================================
+//   O-RAN-SC
+//   %%
+//   Copyright (C) 2023-2024: OpenInfra Foundation Europe
+//   %%
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//        http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+//   ========================LICENSE_END===================================
+//
+
+package discoverservice
+
+import (
+       "context"
+       "fmt"
+       "net/http"
+
+       "oransc.org/nonrtric/servicemanager/internal/common29122"
+       discoverapi "oransc.org/nonrtric/servicemanager/internal/discoverserviceapi"
+
+       echo "github.com/labstack/echo/v4"
+       log "github.com/sirupsen/logrus"
+)
+
+type DiscoverService struct {
+       CapifProtocol string
+       CapifIPv4     common29122.Ipv4Addr
+       CapifPort     common29122.Port
+}
+
+func NewDiscoverService(capifProtocol string, capifIPv4 common29122.Ipv4Addr, capifPort common29122.Port) *DiscoverService {
+       return &DiscoverService{
+               CapifProtocol: capifProtocol,
+               CapifIPv4:     capifIPv4,
+               CapifPort:     capifPort,
+       }
+}
+
+func (ds *DiscoverService) GetAllServiceAPIs(ctx echo.Context, params discoverapi.GetAllServiceAPIsParams) error {
+       log.Trace("entering GetAllServiceAPIs")
+
+       capifcoreUrl := fmt.Sprintf("%s://%s:%d/service-apis/v1/", ds.CapifProtocol, ds.CapifIPv4, ds.CapifPort)
+       client, err := discoverapi.NewClientWithResponses(capifcoreUrl)
+       if err != nil {
+               return err
+       }
+
+       var (
+               ctxHandler context.Context
+               cancel     context.CancelFunc
+       )
+       ctxHandler, cancel = context.WithCancel(context.Background())
+       defer cancel()
+
+       var rsp *discoverapi.GetAllServiceAPIsResponse
+       rsp, err = client.GetAllServiceAPIsWithResponse(ctxHandler, &params)
+
+       if err != nil {
+               msg := err.Error()
+               log.Errorf("error on GetAllServiceAPIsWithResponse %s", msg)
+               return sendCoreError(ctx, http.StatusInternalServerError, msg)
+       }
+
+       if rsp.StatusCode() != http.StatusOK {
+               msg := string(rsp.Body)
+               log.Errorf("GetAllServiceAPIs status code %d", rsp.StatusCode())
+               log.Errorf("GetAllServiceAPIs error %s", string(rsp.Body))
+               return sendCoreError(ctx, rsp.StatusCode(), msg)
+       }
+
+       rspDiscoveredAPIs := *rsp.JSON200
+       err = ctx.JSON(http.StatusOK, rspDiscoveredAPIs)
+       if err != nil {
+               return err // tell Echo that our handler failed
+       }
+       return nil
+}
+
+
+// This function wraps sending of an error in the Error format, and
+// handling the failure to marshal that.
+func sendCoreError(ctx echo.Context, code int, message string) error {
+       pd := common29122.ProblemDetails{
+               Cause:  &message,
+               Status: &code,
+       }
+       err := ctx.JSON(code, pd)
+       return err
+}
diff --git a/servicemanager/internal/discoverservice/discoverservice_test.go b/servicemanager/internal/discoverservice/discoverservice_test.go
new file mode 100644 (file)
index 0000000..2424658
--- /dev/null
@@ -0,0 +1,743 @@
+// -
+//   ========================LICENSE_START=================================
+//   O-RAN-SC
+//   %%
+//   Copyright (C) 2024: OpenInfra Foundation Europe
+//   %%
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//        http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+//   ========================LICENSE_END===================================
+//
+
+package discoverservice
+
+import (
+       "fmt"
+       "net/http"
+       "os"
+       "reflect"
+       "sort"
+       "strings"
+       "testing"
+
+       echo "github.com/labstack/echo/v4"
+       log "github.com/sirupsen/logrus"
+
+       "oransc.org/nonrtric/servicemanager/internal/common29122"
+       "oransc.org/nonrtric/servicemanager/internal/discoverserviceapi"
+       "oransc.org/nonrtric/servicemanager/internal/invokermanagement"
+       "oransc.org/nonrtric/servicemanager/internal/invokermanagementapi"
+
+       publishapi "oransc.org/nonrtric/servicemanager/internal/publishserviceapi"
+
+       "github.com/deepmap/oapi-codegen/pkg/middleware"
+       "github.com/deepmap/oapi-codegen/pkg/testutil"
+       echomiddleware "github.com/labstack/echo/v4/middleware"
+       "github.com/stretchr/testify/assert"
+
+       "oransc.org/nonrtric/servicemanager/internal/envreader"
+       "oransc.org/nonrtric/servicemanager/internal/kongclear"
+       "oransc.org/nonrtric/servicemanager/internal/providermanagement"
+
+       provapi "oransc.org/nonrtric/servicemanager/internal/providermanagementapi"
+       "oransc.org/nonrtric/servicemanager/internal/publishservice"
+)
+
+var requestHandler *echo.Echo
+
+func TestMain(m *testing.M) {
+       err := setupTest()
+       if err != nil {
+               return
+       }
+
+       ret := m.Run()
+       if ret == 0 {
+               teardown()
+       }
+       os.Exit(ret)
+}
+
+func setupTest() error {
+       myEnv, myPorts, err := envreader.ReadDotEnv()
+       if err != nil {
+               log.Fatal("error loading environment file on setupTest")
+               return err
+       }
+
+       requestHandler, err = getEcho(myEnv, myPorts)
+       if err != nil {
+               log.Fatal("getEcho fatal error on setupTest")
+               return err
+       }
+       err = teardown()
+       if err != nil {
+               log.Fatal("getEcho fatal error on teardown")
+               return err
+       }
+
+       return err
+}
+
+func getProvider() provapi.APIProviderEnrolmentDetails {
+       var (
+               domainInfo  = "Kong"
+               funcInfoAPF = "rApp Kong as APF"
+               funcInfoAEF = "rApp Kong as AEF"
+       )
+
+       testFuncs := []provapi.APIProviderFunctionDetails{
+               {
+                       ApiProvFuncInfo: &funcInfoAPF,
+                       ApiProvFuncRole: provapi.ApiProviderFuncRoleAPF,
+                       RegInfo: provapi.RegistrationInformation{
+                               ApiProvPubKey: "APF-PublicKey",
+                       },
+               },
+               {
+                       ApiProvFuncInfo: &funcInfoAEF,
+                       ApiProvFuncRole: provapi.ApiProviderFuncRoleAEF,
+                       RegInfo: provapi.RegistrationInformation{
+                               ApiProvPubKey: "AEF-PublicKey",
+                       },
+               },
+       }
+       return provapi.APIProviderEnrolmentDetails{
+               RegSec:         "sec",
+               ApiProvDomInfo: &domainInfo,
+               ApiProvFuncs:   &testFuncs,
+       }
+}
+
+func teardown() error {
+       log.Trace("entering teardown")
+
+       t := new(testing.T) // Create a new testing.T instance for teardown
+
+       // Delete the invoker
+       invokerInfo := "invoker a"
+       invokerId := "api_invoker_id_" + strings.Replace(invokerInfo, " ", "_", 1)
+
+       result := testutil.NewRequest().Delete("/api-invoker-management/v1/onboardedInvokers/"+invokerId).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNoContent, result.Code())
+
+       // Delete the original published service
+       apfId := "APF_id_rApp_Kong_as_APF"
+       apiName := "apiName"
+       apiId := "api_id_" + apiName
+
+       result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNoContent, result.Code())
+
+       // Delete the first published service
+       apfId = "APF_id_rApp_Kong_as_APF"
+       apiName = "apiName1"
+       apiId = "api_id_" + apiName
+
+       result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNoContent, result.Code())
+
+       // Delete the second published service
+       apiName = "apiName2"
+       apiId = "api_id_" + apiName
+
+       result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNoContent, result.Code())
+
+       // Delete the provider
+       domainID := "domain_id_Kong"
+       result = testutil.NewRequest().Delete("/api-provider-management/v1/registrations/"+domainID).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNoContent, result.Code())
+
+       myEnv, myPorts, err := envreader.ReadDotEnv()
+       if err != nil {
+               log.Fatal("error loading environment file")
+               return err
+       }
+
+       err = kongclear.KongClear(myEnv, myPorts)
+       if err != nil {
+               log.Fatal("error clearing Kong on teardown")
+       }
+       return err
+}
+
+func TestRegisterValidProvider(t *testing.T) {
+       teardown()
+       newProvider := getProvider()
+
+       // Register a valid provider
+       result := testutil.NewRequest().Post("/api-provider-management/v1/registrations").WithJsonBody(newProvider).Go(t, requestHandler)
+       assert.Equal(t, http.StatusCreated, result.Code())
+
+       var resultProvider provapi.APIProviderEnrolmentDetails
+       err := result.UnmarshalBodyToObject(&resultProvider)
+       assert.NoError(t, err, "error unmarshaling response")
+}
+
+func TestPublishUnpublishService(t *testing.T) {
+       apfId := "APF_id_rApp_Kong_as_APF"
+       apiName := "apiName1"
+       apiId := "api_id_" + apiName
+
+       myEnv, myPorts, err := envreader.ReadDotEnv()
+       assert.Nil(t, err, "error reading env file")
+
+       testServiceIpv4 := common29122.Ipv4Addr(myEnv["TEST_SERVICE_IPV4"])
+       testServicePort := common29122.Port(myPorts["TEST_SERVICE_PORT"])
+
+       assert.NotEmpty(t, testServiceIpv4, "TEST_SERVICE_IPV4 is required in .env file for unit testing")
+       assert.NotZero(t, testServicePort, "TEST_SERVICE_PORT is required in .env file for unit testing")
+
+       // Check no services published
+       result := testutil.NewRequest().Get("/published-apis/v1/"+apfId+"/service-apis").Go(t, requestHandler)
+       assert.Equal(t, http.StatusOK, result.Code())
+
+       // Parse JSON from the response body
+       var resultServices []publishapi.ServiceAPIDescription
+       err = result.UnmarshalJsonToObject(&resultServices)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       // Check if the parsed array is empty
+       assert.Zero(t, len(resultServices))
+       assert.True (t, len(resultServices) == 0)
+
+       aefId := "AEF_id_rApp_Kong_as_AEF"
+       namespace := "namespace"
+       repoName := "repoName"
+       chartName := "chartName"
+       releaseName := "releaseName"
+       description := fmt.Sprintf("Description,%s,%s,%s,%s", namespace, repoName, chartName, releaseName)
+
+       apiCategory := "apiCategory"
+       apiVersion := "v1"
+       var protocolHTTP11 = publishapi.ProtocolHTTP11
+       var dataFormatJSON = publishapi.DataFormatJSON
+
+       newServiceDescription := getServiceAPIDescription(aefId, apiName, apiCategory, apiVersion, &protocolHTTP11, &dataFormatJSON, description, testServiceIpv4, testServicePort, publishapi.CommunicationTypeREQUESTRESPONSE)
+
+       // Publish a service for provider
+       result = testutil.NewRequest().Post("/published-apis/v1/"+apfId+"/service-apis").WithJsonBody(newServiceDescription).Go(t, requestHandler)
+       assert.Equal(t, http.StatusCreated, result.Code())
+
+       if result.Code() != http.StatusCreated {
+               log.Fatalf("failed to publish the service with HTTP result code %d", result.Code())
+       }
+
+       var resultService publishapi.ServiceAPIDescription
+       err = result.UnmarshalJsonToObject(&resultService)
+       assert.NoError(t, err, "error unmarshaling response")
+       assert.Equal(t, apiId, *resultService.ApiId)
+
+       assert.Equal(t, "http://example.com/published-apis/v1/"+apfId+"/service-apis/"+*resultService.ApiId, result.Recorder.Header().Get(echo.HeaderLocation))
+
+       // Check that the service is published for the provider
+       result = testutil.NewRequest().Get("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, requestHandler)
+       assert.Equal(t, http.StatusOK, result.Code())
+
+       err = result.UnmarshalJsonToObject(&resultService)
+       assert.NoError(t, err, "error unmarshaling response")
+       assert.Equal(t, apiId, *resultService.ApiId)
+
+       aefProfile := (*resultService.AefProfiles)[0]
+       interfaceDescription := (*aefProfile.InterfaceDescriptions)[0]
+
+       resultServiceIpv4 := *interfaceDescription.Ipv4Addr
+       resultServicePort := *interfaceDescription.Port
+
+       kongIPv4 := common29122.Ipv4Addr(myEnv["KONG_IPV4"])
+       kongDataPlanePort := common29122.Port(myPorts["KONG_DATA_PLANE_PORT"])
+
+       assert.NotEmpty(t, kongIPv4, "KONG_IPV4 is required in .env file for unit testing")
+       assert.NotZero(t, kongDataPlanePort, "KONG_DATA_PLANE_PORT is required in .env file for unit testing")
+
+       assert.Equal(t, kongIPv4, resultServiceIpv4)
+       assert.Equal(t, kongDataPlanePort, resultServicePort)
+
+       // Check one service published
+       result = testutil.NewRequest().Get("/published-apis/v1/"+apfId+"/service-apis").Go(t, requestHandler)
+       assert.Equal(t, http.StatusOK, result.Code())
+
+       // Parse JSON from the response body
+       err = result.UnmarshalJsonToObject(&resultServices)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       // Check if the parsed array has one item
+       assert.True (t, len(resultServices) == 1)
+
+       // Publish a second service for provider
+       apiName2 := "apiName2"
+       apiId2 := "api_id_" + apiName2
+       apiVersion = "v2"
+       apiCategory = ""
+       protocolHTTP1 := publishapi.ProtocolHTTP2
+       var dataFormatOther publishapi.DataFormat = "OTHER"
+
+       newServiceDescription2 := getServiceAPIDescription(aefId, apiName2, apiCategory, apiVersion, &protocolHTTP1, &dataFormatOther, description, testServiceIpv4, testServicePort, publishapi.CommunicationTypeSUBSCRIBENOTIFY)
+
+       result = testutil.NewRequest().Post("/published-apis/v1/"+apfId+"/service-apis").WithJsonBody(newServiceDescription2).Go(t, requestHandler)
+       assert.Equal(t, http.StatusCreated, result.Code())
+
+       if result.Code() != http.StatusCreated {
+               log.Fatalf("failed to publish the service with HTTP result code %d", result.Code())
+               return
+       }
+
+       err = result.UnmarshalJsonToObject(&resultService)
+       assert.NoError(t, err, "error unmarshaling response")
+       assert.Equal(t, apiId2, *resultService.ApiId)
+
+       // Check no services published
+       result = testutil.NewRequest().Get("/published-apis/v1/"+apfId+"/service-apis").Go(t, requestHandler)
+       assert.Equal(t, http.StatusOK, result.Code())
+
+       // Parse JSON from the response body
+       err = result.UnmarshalJsonToObject(&resultServices)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       // Check if the parsed array has two items
+       assert.True (t, len(resultServices) == 2)
+}
+
+func TestOnboardInvoker(t *testing.T) {
+       invokerInfo := "invoker a"
+       newInvoker := getInvoker(invokerInfo)
+
+       // Onboard a valid invoker
+       result := testutil.NewRequest().Post("/api-invoker-management/v1/onboardedInvokers").WithJsonBody(newInvoker).Go(t, requestHandler)
+       assert.Equal(t, http.StatusCreated, result.Code())
+
+       var resultInvoker invokermanagementapi.APIInvokerEnrolmentDetails
+
+       err := result.UnmarshalBodyToObject(&resultInvoker)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       invokerId := "api_invoker_id_" + strings.Replace(invokerInfo, " ", "_", 1)
+
+       assert.Equal(t, invokerId, *resultInvoker.ApiInvokerId)
+       assert.Equal(t, newInvoker.NotificationDestination, resultInvoker.NotificationDestination)
+       assert.Equal(t, newInvoker.OnboardingInformation.ApiInvokerPublicKey, resultInvoker.OnboardingInformation.ApiInvokerPublicKey)
+       assert.Equal(t, "http://example.com/api-invoker-management/v1/onboardedInvokers/"+*resultInvoker.ApiInvokerId, result.Recorder.Header().Get(echo.HeaderLocation))
+}
+
+func TestGetAllServiceAPIs(t *testing.T) {
+       invokerInfo := "invoker a"
+       invokerId := "api_invoker_id_" + strings.Replace(invokerInfo, " ", "_", 1)
+       apiName1 := "apiName1"
+       apiName2 := "apiName2"
+
+       // Get all APIs, without any filter
+       result := testutil.NewRequest().Get("/service-apis/v1/allServiceAPIs?api-invoker-id="+invokerId).Go(t, requestHandler)
+       assert.Equal(t, http.StatusOK, result.Code())
+
+       var resultDiscovery discoverserviceapi.DiscoveredAPIs
+       err := result.UnmarshalBodyToObject(&resultDiscovery)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       assert.NotNil(t, resultDiscovery.ServiceAPIDescriptions, "error reading ServiceAPIDescriptions")
+       if resultDiscovery.ServiceAPIDescriptions != nil {
+               assert.Equal(t, 2, len(*resultDiscovery.ServiceAPIDescriptions), "incorrect count of ServiceAPIDescriptions")
+               if len(*resultDiscovery.ServiceAPIDescriptions) == 2 {
+                       // The order of the results is inconsistent.
+                       resultApiName1 := (*resultDiscovery.ServiceAPIDescriptions)[0].ApiName
+                       resultApiName2 := (*resultDiscovery.ServiceAPIDescriptions)[1].ApiName
+                       resultApiNames := []string{resultApiName1, resultApiName2}
+                       sort.Strings(resultApiNames)
+                       expectedApiNames := []string{apiName1, apiName2}
+                       sort.Strings(expectedApiNames)
+                       assert.True(t, reflect.DeepEqual(resultApiNames, expectedApiNames))
+               }
+
+       }
+}
+
+func TestGetAllServiceAPIsWhenMissingProvider(t *testing.T) {
+       invokerId := "unregistered"
+
+       // Get all APIs, without any filter
+       result := testutil.NewRequest().Get("/service-apis/v1/allServiceAPIs?api-invoker-id="+invokerId).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNotFound, result.Code())
+
+       var problemDetails common29122.ProblemDetails
+       err := result.UnmarshalBodyToObject(&problemDetails)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       notFound := http.StatusNotFound
+       assert.Equal(t, &notFound, problemDetails.Status)
+       assert.Contains(t, *problemDetails.Cause, invokerId)
+       assert.Contains(t, *problemDetails.Cause, "not registered")
+}
+
+func TestFilterApiName(t *testing.T) {
+       apiName := "apiName1"
+       invokerInfo := "invoker a"
+       invokerId := "api_invoker_id_" + strings.Replace(invokerInfo, " ", "_", 1)
+
+       // Get APIs with filter
+       result := testutil.NewRequest().Get("/service-apis/v1/allServiceAPIs?api-invoker-id="+invokerId+"&api-name="+apiName).Go(t, requestHandler)
+       assert.Equal(t, http.StatusOK, result.Code())
+
+       var resultDiscovery discoverserviceapi.DiscoveredAPIs
+       err := result.UnmarshalBodyToObject(&resultDiscovery)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       assert.NotNil(t, resultDiscovery.ServiceAPIDescriptions, "error reading ServiceAPIDescriptions")
+       if resultDiscovery.ServiceAPIDescriptions != nil {
+               assert.Equal(t, 1, len(*resultDiscovery.ServiceAPIDescriptions))
+               if len(*resultDiscovery.ServiceAPIDescriptions) == 1 {
+                       assert.Equal(t, apiName, (*resultDiscovery.ServiceAPIDescriptions)[0].ApiName)
+               }
+       }
+}
+
+func TestFilterAefId(t *testing.T) {
+       apiName1 := "apiName1"
+       apiName2 := "apiName2"
+       invokerInfo := "invoker a"
+       invokerId := "api_invoker_id_" + strings.Replace(invokerInfo, " ", "_", 1)
+
+       aefId := "AEF_id_rApp_Kong_as_AEF"
+
+       // Get APIs with filter
+       result := testutil.NewRequest().Get("/service-apis/v1/allServiceAPIs?api-invoker-id="+invokerId+"&aef-id="+aefId).Go(t, requestHandler)
+       assert.Equal(t, http.StatusOK, result.Code())
+
+       var resultDiscovery discoverserviceapi.DiscoveredAPIs
+       err := result.UnmarshalBodyToObject(&resultDiscovery)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       assert.NotNil(t, resultDiscovery.ServiceAPIDescriptions, "error reading ServiceAPIDescriptions")
+       if resultDiscovery.ServiceAPIDescriptions != nil {
+               assert.Equal(t, 2, len(*resultDiscovery.ServiceAPIDescriptions), "incorrect count of ServiceAPIDescriptions")
+               if len(*resultDiscovery.ServiceAPIDescriptions) == 2 {
+                       // The order of the results is inconsistent.
+                       resultApiName1 := (*resultDiscovery.ServiceAPIDescriptions)[0].ApiName
+                       resultApiName2 := (*resultDiscovery.ServiceAPIDescriptions)[1].ApiName
+                       resultApiNames := []string{resultApiName1, resultApiName2}
+                       sort.Strings(resultApiNames)
+                       expectedApiNames := []string{apiName1, apiName2}
+                       sort.Strings(expectedApiNames)
+                       assert.True(t, reflect.DeepEqual(resultApiNames, expectedApiNames))
+               }
+       }
+}
+
+func TestFilterVersion(t *testing.T) {
+       apiName := "apiName1"
+       invokerInfo := "invoker a"
+       invokerId := "api_invoker_id_" + strings.Replace(invokerInfo, " ", "_", 1)
+       apiVersion := "v1"
+
+       // Get APIs with filter
+       result := testutil.NewRequest().Get("/service-apis/v1/allServiceAPIs?api-invoker-id="+invokerId+"&api-version="+apiVersion).Go(t, requestHandler)
+       assert.Equal(t, http.StatusOK, result.Code())
+
+       var resultDiscovery discoverserviceapi.DiscoveredAPIs
+       err := result.UnmarshalBodyToObject(&resultDiscovery)
+
+       assert.NoError(t, err, "error unmarshaling response")
+
+       assert.NotNil(t, resultDiscovery.ServiceAPIDescriptions, "error reading ServiceAPIDescriptions")
+       if resultDiscovery.ServiceAPIDescriptions != nil {
+               assert.Equal(t, 1, len(*resultDiscovery.ServiceAPIDescriptions))
+               if len(*resultDiscovery.ServiceAPIDescriptions) == 1 {
+                       assert.Equal(t, apiName, (*resultDiscovery.ServiceAPIDescriptions)[0].ApiName)
+               }
+       }
+}
+
+func TestFilterCommType(t *testing.T) {
+       apiName := "apiName1"
+       invokerInfo := "invoker a"
+       invokerId := "api_invoker_id_" + strings.Replace(invokerInfo, " ", "_", 1)
+
+       commType := publishapi.CommunicationTypeREQUESTRESPONSE
+
+       // Get APIs with filter
+       result := testutil.NewRequest().Get("/service-apis/v1/allServiceAPIs?api-invoker-id="+invokerId+"&comm-type="+string(commType)).Go(t, requestHandler)
+       assert.Equal(t, http.StatusOK, result.Code())
+
+       var resultDiscovery discoverserviceapi.DiscoveredAPIs
+       err := result.UnmarshalBodyToObject(&resultDiscovery)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       assert.NotNil(t, resultDiscovery.ServiceAPIDescriptions, "error reading ServiceAPIDescriptions")
+       if resultDiscovery.ServiceAPIDescriptions != nil {
+               assert.Equal(t, 1, len(*resultDiscovery.ServiceAPIDescriptions))
+               if len(*resultDiscovery.ServiceAPIDescriptions) == 1 {
+                       assert.Equal(t, apiName, (*resultDiscovery.ServiceAPIDescriptions)[0].ApiName)
+               }
+       }
+}
+
+func TestFilterVersionAndCommType(t *testing.T) {
+       apiName := "apiName1"
+       invokerInfo := "invoker a"
+       invokerId := "api_invoker_id_" + strings.Replace(invokerInfo, " ", "_", 1)
+
+       apiVersion := "v1"
+       commType := publishapi.CommunicationTypeREQUESTRESPONSE
+
+       // Get APIs with filter
+       result := testutil.NewRequest().Get("/service-apis/v1/allServiceAPIs?api-invoker-id="+invokerId+"&api-version="+apiVersion+"&comm-type="+string(commType)).Go(t, requestHandler)
+       assert.Equal(t, http.StatusOK, result.Code())
+
+       var resultDiscovery discoverserviceapi.DiscoveredAPIs
+       err := result.UnmarshalBodyToObject(&resultDiscovery)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       assert.NotNil(t, resultDiscovery.ServiceAPIDescriptions, "error reading ServiceAPIDescriptions")
+       if resultDiscovery.ServiceAPIDescriptions != nil {
+               assert.Equal(t, 1, len(*resultDiscovery.ServiceAPIDescriptions))
+               if len(*resultDiscovery.ServiceAPIDescriptions) == 1 {
+                       assert.Equal(t, apiName, (*resultDiscovery.ServiceAPIDescriptions)[0].ApiName)
+               }
+       }
+}
+
+func TestFilterAPICategory(t *testing.T) {
+       apiName := "apiName1"
+       invokerInfo := "invoker a"
+       invokerId := "api_invoker_id_" + strings.Replace(invokerInfo, " ", "_", 1)
+
+       apiCategory := "apiCategory"
+
+       // Get APIs with filter
+       result := testutil.NewRequest().Get("/service-apis/v1/allServiceAPIs?api-invoker-id="+invokerId+"&api-cat="+apiCategory).Go(t, requestHandler)
+       assert.Equal(t, http.StatusOK, result.Code())
+
+       var resultDiscovery discoverserviceapi.DiscoveredAPIs
+       err := result.UnmarshalBodyToObject(&resultDiscovery)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       assert.NotNil(t, resultDiscovery.ServiceAPIDescriptions, "error reading ServiceAPIDescriptions")
+       if resultDiscovery.ServiceAPIDescriptions != nil {
+               assert.Equal(t, 1, len(*resultDiscovery.ServiceAPIDescriptions))
+               if len(*resultDiscovery.ServiceAPIDescriptions) == 1 {
+                       assert.Equal(t, apiName, (*resultDiscovery.ServiceAPIDescriptions)[0].ApiName)
+               }
+       }
+}
+
+func TestFilterProtocol(t *testing.T) {
+       apiName := "apiName1"
+       invokerInfo := "invoker a"
+       invokerId := "api_invoker_id_" + strings.Replace(invokerInfo, " ", "_", 1)
+
+       var protocolHTTP11 = publishapi.ProtocolHTTP11
+
+       // Get APIs with filter
+       result := testutil.NewRequest().Get("/service-apis/v1/allServiceAPIs?api-invoker-id="+invokerId+"&protocol="+string(protocolHTTP11)).Go(t, requestHandler)
+       assert.Equal(t, http.StatusOK, result.Code())
+
+       var resultDiscovery discoverserviceapi.DiscoveredAPIs
+       err := result.UnmarshalBodyToObject(&resultDiscovery)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       assert.NotNil(t, resultDiscovery.ServiceAPIDescriptions, "error reading ServiceAPIDescriptions")
+
+       if resultDiscovery.ServiceAPIDescriptions != nil {
+               assert.Equal(t, 1, len(*resultDiscovery.ServiceAPIDescriptions))
+               if len(*resultDiscovery.ServiceAPIDescriptions) == 1 {
+                       assert.Equal(t, apiName, (*resultDiscovery.ServiceAPIDescriptions)[0].ApiName)
+               }
+       }
+}
+
+func TestFilterDataFormat(t *testing.T) {
+       apiName := "apiName1"
+       invokerInfo := "invoker a"
+       invokerId := "api_invoker_id_" + strings.Replace(invokerInfo, " ", "_", 1)
+
+       var dataFormatJSON = publishapi.DataFormatJSON
+
+       // Get APIs with filter
+       result := testutil.NewRequest().Get("/service-apis/v1/allServiceAPIs?api-invoker-id="+invokerId+"&data-format="+string(dataFormatJSON)).Go(t, requestHandler)
+       assert.Equal(t, http.StatusOK, result.Code())
+
+       var resultDiscovery discoverserviceapi.DiscoveredAPIs
+       err := result.UnmarshalBodyToObject(&resultDiscovery)
+
+       assert.NoError(t, err, "error unmarshaling response")
+
+       assert.NotNil(t, resultDiscovery.ServiceAPIDescriptions, "error reading ServiceAPIDescriptions")
+       if resultDiscovery.ServiceAPIDescriptions != nil {
+               assert.Equal(t, 1, len(*resultDiscovery.ServiceAPIDescriptions))
+               if len(*resultDiscovery.ServiceAPIDescriptions) == 1 {
+                       assert.Equal(t, apiName, (*resultDiscovery.ServiceAPIDescriptions)[0].ApiName)
+               }
+       }
+       teardown()
+}
+
+func getEcho(myEnv map[string]string, myPorts map[string]int) (*echo.Echo, error) {
+       capifProtocol := myEnv["CAPIF_PROTOCOL"]
+       capifIPv4 := common29122.Ipv4Addr(myEnv["CAPIF_IPV4"])
+       capifPort := common29122.Port(myPorts["CAPIF_PORT"])
+       kongDomain := myEnv["KONG_DOMAIN"]
+       kongProtocol := myEnv["KONG_PROTOCOL"]
+       kongIPv4 := common29122.Ipv4Addr(myEnv["KONG_IPV4"])
+       kongDataPlanePort := common29122.Port(myPorts["KONG_DATA_PLANE_PORT"])
+       kongControlPlanePort := common29122.Port(myPorts["KONG_CONTROL_PLANE_PORT"])
+
+       e := echo.New()
+
+       // Register ProviderManagement
+       providerManagerSwagger, err := provapi.GetSwagger()
+       if err != nil {
+               log.Fatalf("error loading ProviderManagement swagger spec\n: %s", err)
+               return nil, err
+       }
+       providerManagerSwagger.Servers = nil
+       providerManager := providermanagement.NewProviderManager(capifProtocol, capifIPv4, capifPort)
+
+       var group *echo.Group
+
+       group = e.Group("/api-provider-management/v1")
+       group.Use(middleware.OapiRequestValidator(providerManagerSwagger))
+       provapi.RegisterHandlersWithBaseURL(e, providerManager, "/api-provider-management/v1")
+
+       // Register PublishService
+       publishServiceSwagger, err := publishapi.GetSwagger()
+       if err != nil {
+               fmt.Fprintf(os.Stderr, "Error loading PublishService swagger spec\n: %s", err)
+               return nil, err
+       }
+
+       publishServiceSwagger.Servers = nil
+
+       ps := publishservice.NewPublishService(kongDomain, kongProtocol, kongIPv4, kongDataPlanePort, kongControlPlanePort, capifProtocol, capifIPv4, capifPort)
+
+       group = e.Group("/published-apis/v1")
+       group.Use(echomiddleware.Logger())
+       group.Use(middleware.OapiRequestValidator(publishServiceSwagger))
+       publishapi.RegisterHandlersWithBaseURL(e, ps, "/published-apis/v1")
+
+       // Register InvokerService
+       invokerServiceSwagger, err := invokermanagementapi.GetSwagger()
+       if err != nil {
+               fmt.Fprintf(os.Stderr, "Error loading InvokerManagement swagger spec\n: %s", err)
+               return nil, err
+       }
+
+       invokerServiceSwagger.Servers = nil
+
+       im := invokermanagement.NewInvokerManager(capifProtocol, capifIPv4, capifPort)
+
+       group = e.Group("/api-invoker-management/v1")
+       group.Use(echomiddleware.Logger())
+       group.Use(middleware.OapiRequestValidator(invokerServiceSwagger))
+       invokermanagementapi.RegisterHandlersWithBaseURL(e, im, "api-invoker-management/v1")
+
+       // Register DiscoveryService
+       discoverySeviceSwagger, err := discoverserviceapi.GetSwagger()
+       if err != nil {
+               fmt.Fprintf(os.Stderr, "Error loading swagger spec\n: %s", err)
+               os.Exit(1)
+       }
+
+       discoverySeviceSwagger.Servers = nil
+
+       ds := NewDiscoverService(capifProtocol, capifIPv4, capifPort)
+
+       group = e.Group("/service-apis/v1")
+       group.Use(echomiddleware.Logger())
+       group.Use(middleware.OapiRequestValidator(discoverySeviceSwagger))
+       discoverserviceapi.RegisterHandlersWithBaseURL(e, ds, "service-apis/v1")
+
+       return e, err
+}
+
+func getServiceAPIDescription(aefId string, apiName string, apiCategory string, apiVersion string, protocol *publishapi.Protocol, dataFormat *publishapi.DataFormat, description string, testServiceIpv4 common29122.Ipv4Addr, testServicePort common29122.Port, commType publishapi.CommunicationType) publishapi.ServiceAPIDescription {
+       domainName := "Kong"
+       otherDomainName := "otherDomain"
+
+       var otherProtocol publishapi.Protocol = "HTTP_2"
+
+       categoryPointer := &apiCategory
+       if apiCategory == "" {
+               categoryPointer = nil
+       }
+
+       var DataFormatOther publishapi.DataFormat = "OTHER"
+
+       return publishapi.ServiceAPIDescription{
+               AefProfiles: &[]publishapi.AefProfile{
+                       {
+                               AefId: aefId,
+                               InterfaceDescriptions: &[]publishapi.InterfaceDescription{
+                                       {
+                                               Ipv4Addr: &testServiceIpv4,
+                                               Port:     &testServicePort,
+                                               SecurityMethods: &[]publishapi.SecurityMethod{
+                                                       "PKI",
+                                               },
+                                       },
+                               },
+                               DomainName: &domainName,
+                               Protocol:   protocol,
+                               DataFormat: dataFormat,
+                               Versions: []publishapi.Version{
+                                       {
+                                               ApiVersion: apiVersion,
+                                               Resources: &[]publishapi.Resource{
+                                                       {
+                                                               CommType: commType,
+                                                               Operations: &[]publishapi.Operation{
+                                                                       "GET",
+                                                               },
+                                                               ResourceName: "helloworld",
+                                                               Uri:          "/helloworld",
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+                       {
+                               AefId:      aefId, // "otherAefId"
+                               DomainName: &otherDomainName,
+                               Protocol:   &otherProtocol,
+                               DataFormat: &DataFormatOther,
+                               Versions: []publishapi.Version{
+                                       {
+                                               ApiVersion: "v3",
+                                               Resources: &[]publishapi.Resource{
+                                                       {
+                                                               ResourceName: "app",
+                                                               CommType:     publishapi.CommunicationTypeSUBSCRIBENOTIFY,
+                                                               Uri:          "uri",
+                                                               Operations: &[]publishapi.Operation{
+                                                                       "POST",
+                                                               },
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+               },
+               ApiName:            apiName,
+               Description:        &description,
+               ServiceAPICategory: categoryPointer,
+       }
+}
+
+func getInvoker(invokerInfo string) invokermanagementapi.APIInvokerEnrolmentDetails {
+       newInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{
+               ApiInvokerInformation:   &invokerInfo,
+               NotificationDestination: "http://golang.cafe/",
+               OnboardingInformation: invokermanagementapi.OnboardingInformation{
+                       ApiInvokerPublicKey: "key",
+               },
+               ApiList: nil,
+       }
+       return newInvoker
+}
diff --git a/servicemanager/internal/discoverserviceapi/discoverserviceapi-client.gen.go b/servicemanager/internal/discoverserviceapi/discoverserviceapi-client.gen.go
new file mode 100644 (file)
index 0000000..2d09d8f
--- /dev/null
@@ -0,0 +1,406 @@
+// Package discoverserviceapi provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/deepmap/oapi-codegen version v1.10.1 DO NOT EDIT.
+package discoverserviceapi
+
+import (
+       "context"
+       "encoding/json"
+       "fmt"
+       "io/ioutil"
+       "net/http"
+       "net/url"
+       "strings"
+
+       "github.com/deepmap/oapi-codegen/pkg/runtime"
+)
+
+// RequestEditorFn  is the function signature for the RequestEditor callback function
+type RequestEditorFn func(ctx context.Context, req *http.Request) error
+
+// Doer performs HTTP requests.
+//
+// The standard http.Client implements this interface.
+type HttpRequestDoer interface {
+       Do(req *http.Request) (*http.Response, error)
+}
+
+// Client which conforms to the OpenAPI3 specification for this service.
+type Client struct {
+       // The endpoint of the server conforming to this interface, with scheme,
+       // https://api.deepmap.com for example. This can contain a path relative
+       // to the server, such as https://api.deepmap.com/dev-test, and all the
+       // paths in the swagger spec will be appended to the server.
+       Server string
+
+       // Doer for performing requests, typically a *http.Client with any
+       // customized settings, such as certificate chains.
+       Client HttpRequestDoer
+
+       // A list of callbacks for modifying requests which are generated before sending over
+       // the network.
+       RequestEditors []RequestEditorFn
+}
+
+// ClientOption allows setting custom parameters during construction
+type ClientOption func(*Client) error
+
+// Creates a new Client, with reasonable defaults
+func NewClient(server string, opts ...ClientOption) (*Client, error) {
+       // create a client with sane default values
+       client := Client{
+               Server: server,
+       }
+       // mutate client and add all optional params
+       for _, o := range opts {
+               if err := o(&client); err != nil {
+                       return nil, err
+               }
+       }
+       // ensure the server URL always has a trailing slash
+       if !strings.HasSuffix(client.Server, "/") {
+               client.Server += "/"
+       }
+       // create httpClient, if not already present
+       if client.Client == nil {
+               client.Client = &http.Client{}
+       }
+       return &client, nil
+}
+
+// WithHTTPClient allows overriding the default Doer, which is
+// automatically created using http.Client. This is useful for tests.
+func WithHTTPClient(doer HttpRequestDoer) ClientOption {
+       return func(c *Client) error {
+               c.Client = doer
+               return nil
+       }
+}
+
+// WithRequestEditorFn allows setting up a callback function, which will be
+// called right before sending the request. This can be used to mutate the request.
+func WithRequestEditorFn(fn RequestEditorFn) ClientOption {
+       return func(c *Client) error {
+               c.RequestEditors = append(c.RequestEditors, fn)
+               return nil
+       }
+}
+
+// The interface specification for the client above.
+type ClientInterface interface {
+       // GetAllServiceAPIs request
+       GetAllServiceAPIs(ctx context.Context, params *GetAllServiceAPIsParams, reqEditors ...RequestEditorFn) (*http.Response, error)
+}
+
+func (c *Client) GetAllServiceAPIs(ctx context.Context, params *GetAllServiceAPIsParams, reqEditors ...RequestEditorFn) (*http.Response, error) {
+       req, err := NewGetAllServiceAPIsRequest(c.Server, params)
+       if err != nil {
+               return nil, err
+       }
+       req = req.WithContext(ctx)
+       if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+               return nil, err
+       }
+       return c.Client.Do(req)
+}
+
+// NewGetAllServiceAPIsRequest generates requests for GetAllServiceAPIs
+func NewGetAllServiceAPIsRequest(server string, params *GetAllServiceAPIsParams) (*http.Request, error) {
+       var err error
+
+       serverURL, err := url.Parse(server)
+       if err != nil {
+               return nil, err
+       }
+
+       operationPath := fmt.Sprintf("/allServiceAPIs")
+       if operationPath[0] == '/' {
+               operationPath = "." + operationPath
+       }
+
+       queryURL, err := serverURL.Parse(operationPath)
+       if err != nil {
+               return nil, err
+       }
+
+       queryValues := queryURL.Query()
+
+       if queryFrag, err := runtime.StyleParamWithLocation("form", true, "api-invoker-id", runtime.ParamLocationQuery, params.ApiInvokerId); err != nil {
+               return nil, err
+       } else if parsed, err := url.ParseQuery(queryFrag); err != nil {
+               return nil, err
+       } else {
+               for k, v := range parsed {
+                       for _, v2 := range v {
+                               queryValues.Add(k, v2)
+                       }
+               }
+       }
+
+       if params.ApiName != nil {
+
+               if queryFrag, err := runtime.StyleParamWithLocation("form", true, "api-name", runtime.ParamLocationQuery, *params.ApiName); err != nil {
+                       return nil, err
+               } else if parsed, err := url.ParseQuery(queryFrag); err != nil {
+                       return nil, err
+               } else {
+                       for k, v := range parsed {
+                               for _, v2 := range v {
+                                       queryValues.Add(k, v2)
+                               }
+                       }
+               }
+
+       }
+
+       if params.ApiVersion != nil {
+
+               if queryFrag, err := runtime.StyleParamWithLocation("form", true, "api-version", runtime.ParamLocationQuery, *params.ApiVersion); err != nil {
+                       return nil, err
+               } else if parsed, err := url.ParseQuery(queryFrag); err != nil {
+                       return nil, err
+               } else {
+                       for k, v := range parsed {
+                               for _, v2 := range v {
+                                       queryValues.Add(k, v2)
+                               }
+                       }
+               }
+
+       }
+
+       if params.CommType != nil {
+
+               if queryFrag, err := runtime.StyleParamWithLocation("form", true, "comm-type", runtime.ParamLocationQuery, *params.CommType); err != nil {
+                       return nil, err
+               } else if parsed, err := url.ParseQuery(queryFrag); err != nil {
+                       return nil, err
+               } else {
+                       for k, v := range parsed {
+                               for _, v2 := range v {
+                                       queryValues.Add(k, v2)
+                               }
+                       }
+               }
+
+       }
+
+       if params.Protocol != nil {
+
+               if queryFrag, err := runtime.StyleParamWithLocation("form", true, "protocol", runtime.ParamLocationQuery, *params.Protocol); err != nil {
+                       return nil, err
+               } else if parsed, err := url.ParseQuery(queryFrag); err != nil {
+                       return nil, err
+               } else {
+                       for k, v := range parsed {
+                               for _, v2 := range v {
+                                       queryValues.Add(k, v2)
+                               }
+                       }
+               }
+
+       }
+
+       if params.AefId != nil {
+
+               if queryFrag, err := runtime.StyleParamWithLocation("form", true, "aef-id", runtime.ParamLocationQuery, *params.AefId); err != nil {
+                       return nil, err
+               } else if parsed, err := url.ParseQuery(queryFrag); err != nil {
+                       return nil, err
+               } else {
+                       for k, v := range parsed {
+                               for _, v2 := range v {
+                                       queryValues.Add(k, v2)
+                               }
+                       }
+               }
+
+       }
+
+       if params.DataFormat != nil {
+
+               if queryFrag, err := runtime.StyleParamWithLocation("form", true, "data-format", runtime.ParamLocationQuery, *params.DataFormat); err != nil {
+                       return nil, err
+               } else if parsed, err := url.ParseQuery(queryFrag); err != nil {
+                       return nil, err
+               } else {
+                       for k, v := range parsed {
+                               for _, v2 := range v {
+                                       queryValues.Add(k, v2)
+                               }
+                       }
+               }
+
+       }
+
+       if params.ApiCat != nil {
+
+               if queryFrag, err := runtime.StyleParamWithLocation("form", true, "api-cat", runtime.ParamLocationQuery, *params.ApiCat); err != nil {
+                       return nil, err
+               } else if parsed, err := url.ParseQuery(queryFrag); err != nil {
+                       return nil, err
+               } else {
+                       for k, v := range parsed {
+                               for _, v2 := range v {
+                                       queryValues.Add(k, v2)
+                               }
+                       }
+               }
+
+       }
+
+       if params.PreferredAefLoc != nil {
+
+               if queryParamBuf, err := json.Marshal(*params.PreferredAefLoc); err != nil {
+                       return nil, err
+               } else {
+                       queryValues.Add("preferred-aef-loc", string(queryParamBuf))
+               }
+
+       }
+
+       if params.SupportedFeatures != nil {
+
+               if queryFrag, err := runtime.StyleParamWithLocation("form", true, "supported-features", runtime.ParamLocationQuery, *params.SupportedFeatures); err != nil {
+                       return nil, err
+               } else if parsed, err := url.ParseQuery(queryFrag); err != nil {
+                       return nil, err
+               } else {
+                       for k, v := range parsed {
+                               for _, v2 := range v {
+                                       queryValues.Add(k, v2)
+                               }
+                       }
+               }
+
+       }
+
+       if params.ApiSupportedFeatures != nil {
+
+               if queryFrag, err := runtime.StyleParamWithLocation("form", true, "api-supported-features", runtime.ParamLocationQuery, *params.ApiSupportedFeatures); err != nil {
+                       return nil, err
+               } else if parsed, err := url.ParseQuery(queryFrag); err != nil {
+                       return nil, err
+               } else {
+                       for k, v := range parsed {
+                               for _, v2 := range v {
+                                       queryValues.Add(k, v2)
+                               }
+                       }
+               }
+
+       }
+
+       queryURL.RawQuery = queryValues.Encode()
+
+       req, err := http.NewRequest("GET", queryURL.String(), nil)
+       if err != nil {
+               return nil, err
+       }
+
+       return req, nil
+}
+
+func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error {
+       for _, r := range c.RequestEditors {
+               if err := r(ctx, req); err != nil {
+                       return err
+               }
+       }
+       for _, r := range additionalEditors {
+               if err := r(ctx, req); err != nil {
+                       return err
+               }
+       }
+       return nil
+}
+
+// ClientWithResponses builds on ClientInterface to offer response payloads
+type ClientWithResponses struct {
+       ClientInterface
+}
+
+// NewClientWithResponses creates a new ClientWithResponses, which wraps
+// Client with return type handling
+func NewClientWithResponses(server string, opts ...ClientOption) (*ClientWithResponses, error) {
+       client, err := NewClient(server, opts...)
+       if err != nil {
+               return nil, err
+       }
+       return &ClientWithResponses{client}, nil
+}
+
+// WithBaseURL overrides the baseURL.
+func WithBaseURL(baseURL string) ClientOption {
+       return func(c *Client) error {
+               newBaseURL, err := url.Parse(baseURL)
+               if err != nil {
+                       return err
+               }
+               c.Server = newBaseURL.String()
+               return nil
+       }
+}
+
+// ClientWithResponsesInterface is the interface specification for the client with responses above.
+type ClientWithResponsesInterface interface {
+       // GetAllServiceAPIs request
+       GetAllServiceAPIsWithResponse(ctx context.Context, params *GetAllServiceAPIsParams, reqEditors ...RequestEditorFn) (*GetAllServiceAPIsResponse, error)
+}
+
+type GetAllServiceAPIsResponse struct {
+       Body         []byte
+       HTTPResponse *http.Response
+       JSON200      *DiscoveredAPIs
+}
+
+// Status returns HTTPResponse.Status
+func (r GetAllServiceAPIsResponse) Status() string {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.Status
+       }
+       return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r GetAllServiceAPIsResponse) StatusCode() int {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.StatusCode
+       }
+       return 0
+}
+
+// GetAllServiceAPIsWithResponse request returning *GetAllServiceAPIsResponse
+func (c *ClientWithResponses) GetAllServiceAPIsWithResponse(ctx context.Context, params *GetAllServiceAPIsParams, reqEditors ...RequestEditorFn) (*GetAllServiceAPIsResponse, error) {
+       rsp, err := c.GetAllServiceAPIs(ctx, params, reqEditors...)
+       if err != nil {
+               return nil, err
+       }
+       return ParseGetAllServiceAPIsResponse(rsp)
+}
+
+// ParseGetAllServiceAPIsResponse parses an HTTP response from a GetAllServiceAPIsWithResponse call
+func ParseGetAllServiceAPIsResponse(rsp *http.Response) (*GetAllServiceAPIsResponse, error) {
+       bodyBytes, err := ioutil.ReadAll(rsp.Body)
+       defer func() { _ = rsp.Body.Close() }()
+       if err != nil {
+               return nil, err
+       }
+
+       response := &GetAllServiceAPIsResponse{
+               Body:         bodyBytes,
+               HTTPResponse: rsp,
+       }
+
+       switch {
+       case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
+               var dest DiscoveredAPIs
+               if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+                       return nil, err
+               }
+               response.JSON200 = &dest
+
+       }
+
+       return response, nil
+}
diff --git a/servicemanager/internal/discoverserviceapi/discoverserviceapi-server.gen.go b/servicemanager/internal/discoverserviceapi/discoverserviceapi-server.gen.go
new file mode 100644 (file)
index 0000000..48a3e19
--- /dev/null
@@ -0,0 +1,282 @@
+// Package discoverserviceapi provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/deepmap/oapi-codegen version v1.10.1 DO NOT EDIT.
+package discoverserviceapi
+
+import (
+       "bytes"
+       "compress/gzip"
+       "encoding/base64"
+       "encoding/json"
+       "fmt"
+       "net/http"
+       "net/url"
+       "path"
+       "strings"
+
+       "github.com/deepmap/oapi-codegen/pkg/runtime"
+       "github.com/getkin/kin-openapi/openapi3"
+       "github.com/labstack/echo/v4"
+       externalRef0 "oransc.org/nonrtric/servicemanager/internal/common29122"
+       externalRef1 "oransc.org/nonrtric/servicemanager/internal/common29571"
+       externalRef2 "oransc.org/nonrtric/servicemanager/internal/publishserviceapi"
+)
+
+// ServerInterface represents all server handlers.
+type ServerInterface interface {
+
+       // (GET /allServiceAPIs)
+       GetAllServiceAPIs(ctx echo.Context, params GetAllServiceAPIsParams) error
+}
+
+// ServerInterfaceWrapper converts echo contexts to parameters.
+type ServerInterfaceWrapper struct {
+       Handler ServerInterface
+}
+
+// GetAllServiceAPIs converts echo context to params.
+func (w *ServerInterfaceWrapper) GetAllServiceAPIs(ctx echo.Context) error {
+       var err error
+
+       // Parameter object where we will unmarshal all parameters from the context
+       var params GetAllServiceAPIsParams
+       // ------------- Required query parameter "api-invoker-id" -------------
+
+       err = runtime.BindQueryParameter("form", true, true, "api-invoker-id", ctx.QueryParams(), &params.ApiInvokerId)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter api-invoker-id: %s", err))
+       }
+
+       // ------------- Optional query parameter "api-name" -------------
+
+       err = runtime.BindQueryParameter("form", true, false, "api-name", ctx.QueryParams(), &params.ApiName)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter api-name: %s", err))
+       }
+
+       // ------------- Optional query parameter "api-version" -------------
+
+       err = runtime.BindQueryParameter("form", true, false, "api-version", ctx.QueryParams(), &params.ApiVersion)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter api-version: %s", err))
+       }
+
+       // ------------- Optional query parameter "comm-type" -------------
+
+       err = runtime.BindQueryParameter("form", true, false, "comm-type", ctx.QueryParams(), &params.CommType)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter comm-type: %s", err))
+       }
+
+       // ------------- Optional query parameter "protocol" -------------
+
+       err = runtime.BindQueryParameter("form", true, false, "protocol", ctx.QueryParams(), &params.Protocol)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter protocol: %s", err))
+       }
+
+       // ------------- Optional query parameter "aef-id" -------------
+
+       err = runtime.BindQueryParameter("form", true, false, "aef-id", ctx.QueryParams(), &params.AefId)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter aef-id: %s", err))
+       }
+
+       // ------------- Optional query parameter "data-format" -------------
+
+       err = runtime.BindQueryParameter("form", true, false, "data-format", ctx.QueryParams(), &params.DataFormat)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter data-format: %s", err))
+       }
+
+       // ------------- Optional query parameter "api-cat" -------------
+
+       err = runtime.BindQueryParameter("form", true, false, "api-cat", ctx.QueryParams(), &params.ApiCat)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter api-cat: %s", err))
+       }
+
+       // ------------- Optional query parameter "preferred-aef-loc" -------------
+
+       if paramValue := ctx.QueryParam("preferred-aef-loc"); paramValue != "" {
+
+               var value externalRef2.AefLocation
+               err = json.Unmarshal([]byte(paramValue), &value)
+               if err != nil {
+                       return echo.NewHTTPError(http.StatusBadRequest, "Error unmarshaling parameter 'preferred-aef-loc' as JSON")
+               }
+               params.PreferredAefLoc = &value
+
+       }
+
+       // ------------- Optional query parameter "supported-features" -------------
+
+       err = runtime.BindQueryParameter("form", true, false, "supported-features", ctx.QueryParams(), &params.SupportedFeatures)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter supported-features: %s", err))
+       }
+
+       // ------------- Optional query parameter "api-supported-features" -------------
+
+       err = runtime.BindQueryParameter("form", true, false, "api-supported-features", ctx.QueryParams(), &params.ApiSupportedFeatures)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter api-supported-features: %s", err))
+       }
+
+       // Invoke the callback with all the unmarshalled arguments
+       err = w.Handler.GetAllServiceAPIs(ctx, params)
+       return err
+}
+
+// This is a simple interface which specifies echo.Route addition functions which
+// are present on both echo.Echo and echo.Group, since we want to allow using
+// either of them for path registration
+type EchoRouter interface {
+       CONNECT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       DELETE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       GET(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       HEAD(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       OPTIONS(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       PATCH(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       POST(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       PUT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       TRACE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+}
+
+// RegisterHandlers adds each server route to the EchoRouter.
+func RegisterHandlers(router EchoRouter, si ServerInterface) {
+       RegisterHandlersWithBaseURL(router, si, "")
+}
+
+// Registers handlers, and prepends BaseURL to the paths, so that the paths
+// can be served under a prefix.
+func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL string) {
+
+       wrapper := ServerInterfaceWrapper{
+               Handler: si,
+       }
+
+       router.GET(baseURL+"/allServiceAPIs", wrapper.GetAllServiceAPIs)
+
+}
+
+// Base64 encoded, gzipped, json marshaled Swagger object
+var swaggerSpec = []string{
+
+       "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",
+       "5Hxnsc6yLCG6X5d/BgAA//+yTjhGXhEAAA==",
+}
+
+// GetSwagger returns the content of the embedded swagger specification file
+// or error if failed to decode
+func decodeSpec() ([]byte, error) {
+       zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, ""))
+       if err != nil {
+               return nil, fmt.Errorf("error base64 decoding spec: %s", err)
+       }
+       zr, err := gzip.NewReader(bytes.NewReader(zipped))
+       if err != nil {
+               return nil, fmt.Errorf("error decompressing spec: %s", err)
+       }
+       var buf bytes.Buffer
+       _, err = buf.ReadFrom(zr)
+       if err != nil {
+               return nil, fmt.Errorf("error decompressing spec: %s", err)
+       }
+
+       return buf.Bytes(), nil
+}
+
+var rawSpec = decodeSpecCached()
+
+// a naive cached of a decoded swagger spec
+func decodeSpecCached() func() ([]byte, error) {
+       data, err := decodeSpec()
+       return func() ([]byte, error) {
+               return data, err
+       }
+}
+
+// Constructs a synthetic filesystem for resolving external references when loading openapi specifications.
+func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) {
+       var res = make(map[string]func() ([]byte, error))
+       if len(pathToFile) > 0 {
+               res[pathToFile] = rawSpec
+       }
+
+       pathPrefix := path.Dir(pathToFile)
+
+       for rawPath, rawFunc := range externalRef0.PathToRawSpec(path.Join(pathPrefix, "TS29122_CommonData.yaml")) {
+               if _, ok := res[rawPath]; ok {
+                       // it is not possible to compare functions in golang, so always overwrite the old value
+               }
+               res[rawPath] = rawFunc
+       }
+       for rawPath, rawFunc := range externalRef2.PathToRawSpec(path.Join(pathPrefix, "TS29222_CAPIF_Publish_Service_API.yaml")) {
+               if _, ok := res[rawPath]; ok {
+                       // it is not possible to compare functions in golang, so always overwrite the old value
+               }
+               res[rawPath] = rawFunc
+       }
+       for rawPath, rawFunc := range externalRef1.PathToRawSpec(path.Join(pathPrefix, "TS29571_CommonData.yaml")) {
+               if _, ok := res[rawPath]; ok {
+                       // it is not possible to compare functions in golang, so always overwrite the old value
+               }
+               res[rawPath] = rawFunc
+       }
+       return res
+}
+
+// GetSwagger returns the Swagger specification corresponding to the generated code
+// in this file. The external references of Swagger specification are resolved.
+// The logic of resolving external references is tightly connected to "import-mapping" feature.
+// Externally referenced files must be embedded in the corresponding golang packages.
+// Urls can be supported but this task was out of the scope.
+func GetSwagger() (swagger *openapi3.T, err error) {
+       var resolvePath = PathToRawSpec("")
+
+       loader := openapi3.NewLoader()
+       loader.IsExternalRefsAllowed = true
+       loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) {
+               var pathToFile = url.String()
+               pathToFile = path.Clean(pathToFile)
+               getSpec, ok := resolvePath[pathToFile]
+               if !ok {
+                       err1 := fmt.Errorf("path not found: %s", pathToFile)
+                       return nil, err1
+               }
+               return getSpec()
+       }
+       var specData []byte
+       specData, err = rawSpec()
+       if err != nil {
+               return
+       }
+       swagger, err = loader.LoadFromData(specData)
+       if err != nil {
+               return
+       }
+       return
+}
diff --git a/servicemanager/internal/discoverserviceapi/discoverserviceapi-types.gen.go b/servicemanager/internal/discoverserviceapi/discoverserviceapi-types.gen.go
new file mode 100644 (file)
index 0000000..5ced0ad
--- /dev/null
@@ -0,0 +1,51 @@
+// Package discoverserviceapi provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/deepmap/oapi-codegen version v1.10.1 DO NOT EDIT.
+package discoverserviceapi
+
+import (
+       externalRef1 "oransc.org/nonrtric/servicemanager/internal/common29571"
+       externalRef2 "oransc.org/nonrtric/servicemanager/internal/publishserviceapi"
+)
+
+// Represents a list of APIs currently registered in the CAPIF core function and satisfying a number of filter criteria provided by the API consumer.
+type DiscoveredAPIs struct {
+       // Description of the service API as published by the service. Each service API description shall include AEF profiles matching the filter criteria.
+       ServiceAPIDescriptions *[]externalRef2.ServiceAPIDescription `json:"serviceAPIDescriptions,omitempty"`
+}
+
+// GetAllServiceAPIsParams defines parameters for GetAllServiceAPIs.
+type GetAllServiceAPIsParams struct {
+       // String identifying the API invoker assigned by the CAPIF core function. It also represents the CCF identifier in the CAPIF-6/6e interface.
+       ApiInvokerId string `json:"api-invoker-id"`
+
+       // API name, it is set as {apiName} part of the URI structure as defined in clause 5.2.4 of 3GPP TS 29.122.
+       ApiName *string `json:"api-name,omitempty"`
+
+       // API major version the URI (e.g. v1).
+       ApiVersion *string `json:"api-version,omitempty"`
+
+       // Communication type used by the API (e.g. REQUEST_RESPONSE).
+       CommType *externalRef2.CommunicationType `json:"comm-type,omitempty"`
+
+       // Protocol used by the API.
+       Protocol *externalRef2.Protocol `json:"protocol,omitempty"`
+
+       // AEF identifer.
+       AefId *string `json:"aef-id,omitempty"`
+
+       // Data formats used by the API (e.g. serialization protocol JSON used).
+       DataFormat *externalRef2.DataFormat `json:"data-format,omitempty"`
+
+       // The service API category to which the service API belongs to.
+       ApiCat *string `json:"api-cat,omitempty"`
+
+       // The preferred AEF location.
+       PreferredAefLoc *externalRef2.AefLocation `json:"preferred-aef-loc,omitempty"`
+
+       // Features supported by the NF consumer for the CAPIF Discover Service API.
+       SupportedFeatures *externalRef1.SupportedFeatures `json:"supported-features,omitempty"`
+
+       // Features supported by the discovered service API indicated by api-name parameter. This may only be present if api-name query parameter is present.
+       ApiSupportedFeatures *externalRef1.SupportedFeatures `json:"api-supported-features,omitempty"`
+}
diff --git a/servicemanager/internal/envreader/envreader.go b/servicemanager/internal/envreader/envreader.go
new file mode 100644 (file)
index 0000000..5d1b6de
--- /dev/null
@@ -0,0 +1,122 @@
+// -
+//   ========================LICENSE_START=================================
+//   O-RAN-SC
+//   %%
+//   Copyright (C) 2024: OpenInfra Foundation Europe
+//   %%
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//        http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+//   ========================LICENSE_END===================================
+//
+
+package envreader
+
+import (
+       "os"
+       "path/filepath"
+       "runtime"
+       "strconv"
+
+       "github.com/joho/godotenv"
+       log "github.com/sirupsen/logrus"
+)
+
+func ReadDotEnv() (map[string]string, map[string]int, error) {
+       log.SetFormatter(&log.TextFormatter{
+               FullTimestamp: true,
+       })
+
+       env := os.Getenv("SERVICE_MANAGER_ENV")
+       log.Infof("read SERVICE_MANAGER_ENV: %s", env)
+
+       if env == "" {
+               env = "development"
+       }
+
+       // Root folder of this project
+       _, file, _, _ := runtime.Caller(0)
+       basePath := filepath.Join(filepath.Dir(file), "../..")
+       basePath += "/"
+
+       var myEnv map[string]string
+       envFile := basePath + ".env." + env
+       myEnv, err := godotenv.Read(envFile)
+
+       if err != nil {
+               log.Warnf("error reading .env file: %s", err)
+
+               envFile = basePath + ".env"
+               myEnv, err = godotenv.Read(envFile)
+               if err != nil {
+                       log.Fatalf("error reading .env file: %s", err)
+                       return nil, nil, err
+               }
+       }
+       log.Infof("imported .env: %s", envFile)
+
+       loglevel, err := log.ParseLevel(myEnv["LOG_LEVEL"])
+       if err != nil {
+               log.Fatalf("error loading LOG_LEVEL from .env file: %s", err)
+               return nil, nil, err
+       }
+       log.SetLevel(loglevel)
+
+       log.Infof("KONG_DOMAIN %s", myEnv["KONG_DOMAIN"])
+       log.Infof("KONG_PROTOCOL %s", myEnv["KONG_PROTOCOL"])
+       log.Infof("KONG_IPV4 %s", myEnv["KONG_IPV4"])
+       log.Infof("KONG_DATA_PLANE_PORT %s", myEnv["KONG_DATA_PLANE_PORT"])
+       log.Infof("KONG_CONTROL_PLANE_PORT %s", myEnv["KONG_CONTROL_PLANE_PORT"])
+       log.Infof("CAPIF_PROTOCOL %s", myEnv["CAPIF_PROTOCOL"])
+       log.Infof("CAPIF_IPV4 %s", myEnv["CAPIF_IPV4"])
+       log.Infof("CAPIF_PORT %s", myEnv["CAPIF_PORT"])
+       log.Infof("LOG_LEVEL %s", myEnv["LOG_LEVEL"])
+       log.Infof("SERVICE_MANAGER_PORT %s", myEnv["SERVICE_MANAGER_PORT"])
+       log.Infof("TEST_SERVICE_IPV4 %s", myEnv["TEST_SERVICE_IPV4"])
+       log.Infof("TEST_SERVICE_PORT %s", myEnv["TEST_SERVICE_PORT"])
+
+       var myPorts = make(map[string]int)
+
+       myPorts["KONG_DATA_PLANE_PORT"], err = strconv.Atoi(myEnv["KONG_DATA_PLANE_PORT"])
+       if err != nil {
+               log.Fatalf("error loading KONG_DATA_PLANE_PORT from .env file: %s", err)
+               return nil, nil, err
+       }
+
+       myPorts["KONG_CONTROL_PLANE_PORT"], err = strconv.Atoi(myEnv["KONG_CONTROL_PLANE_PORT"])
+       if err != nil {
+               log.Fatalf("error loading KONG_CONTROL_PLANE_PORT from .env file: %s", err)
+               return nil, nil, err
+       }
+
+       myPorts["CAPIF_PORT"], err = strconv.Atoi(myEnv["CAPIF_PORT"])
+       if err != nil {
+               log.Fatalf("error loading CAPIF_PORT from .env file: %s", err)
+               return nil, nil, err
+       }
+
+       myPorts["SERVICE_MANAGER_PORT"], err = strconv.Atoi(myEnv["SERVICE_MANAGER_PORT"])
+       if err != nil {
+               log.Fatalf("error loading SERVICE_MANAGER_PORT from .env file: %s", err)
+               return nil, nil, err
+       }
+
+       // TEST_SERVICE_PORT is required for unit testing, but not required for production
+       if myEnv["TEST_SERVICE_PORT"] != "" {
+               myPorts["TEST_SERVICE_PORT"], err = strconv.Atoi(myEnv["TEST_SERVICE_PORT"])
+               if err != nil {
+                       log.Fatalf("error loading TEST_SERVICE_PORT from .env file: %s", err)
+                       return nil, nil, err
+               }
+       }
+
+       return myEnv, myPorts, err
+}
diff --git a/servicemanager/internal/invokermanagement/invokermanagement.go b/servicemanager/internal/invokermanagement/invokermanagement.go
new file mode 100644 (file)
index 0000000..6bdb820
--- /dev/null
@@ -0,0 +1,199 @@
+// -
+//   ========================LICENSE_START=================================
+//   O-RAN-SC
+//   %%
+//   Copyright (C) 2023-2024: OpenInfra Foundation Europe
+//   %%
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//        http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+//   ========================LICENSE_END===================================
+//
+
+package invokermanagement
+
+import (
+       "context"
+       "fmt"
+       "net/http"
+       "path"
+
+       "oransc.org/nonrtric/servicemanager/internal/common29122"
+       invokerapi "oransc.org/nonrtric/servicemanager/internal/invokermanagementapi"
+
+       echo "github.com/labstack/echo/v4"
+       log "github.com/sirupsen/logrus"
+)
+
+type InvokerManager struct {
+       CapifProtocol string
+       CapifIPv4     common29122.Ipv4Addr
+       CapifPort     common29122.Port
+}
+
+// Creates a manager that implements both the InvokerRegister and the invokermanagementapi.ServerInterface interfaces.
+func NewInvokerManager(capifProtocol string, capifIPv4 common29122.Ipv4Addr, capifPort common29122.Port) *InvokerManager {
+       return &InvokerManager{
+               CapifProtocol: capifProtocol,
+               CapifIPv4:     capifIPv4,
+               CapifPort:     capifPort,
+       }
+}
+
+// Creates a new individual API Invoker profile.
+func (im *InvokerManager) PostOnboardedInvokers(ctx echo.Context) error {
+       log.Trace("entering PostOnboardedInvokers")
+
+       var newInvoker invokerapi.APIInvokerEnrolmentDetails
+       errMsg := "Unable to onboard invoker due to %s"
+       if err := ctx.Bind(&newInvoker); err != nil {
+               return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, "invalid format for invoker"))
+       }
+
+       capifcoreUrl := fmt.Sprintf("%s://%s:%d/api-invoker-management/v1/", im.CapifProtocol, im.CapifIPv4, im.CapifPort)
+       client, err := invokerapi.NewClientWithResponses(capifcoreUrl)
+       if err != nil {
+               return err
+       }
+
+       var (
+               ctxHandler context.Context
+               cancel     context.CancelFunc
+       )
+       ctxHandler, cancel = context.WithCancel(context.Background())
+       defer cancel()
+
+       postRegistrationsJSONRequestBody := invokerapi.PostOnboardedInvokersJSONRequestBody(newInvoker)
+
+       var rspInvoker *invokerapi.PostOnboardedInvokersResponse
+       rspInvoker, err = client.PostOnboardedInvokersWithResponse(ctxHandler, postRegistrationsJSONRequestBody)
+
+       if err != nil {
+               msg := err.Error()
+               log.Errorf("error on PostOnboardedInvokersWithResponse %s", msg)
+               return sendCoreError(ctx, http.StatusInternalServerError, msg)
+       }
+
+       if rspInvoker.StatusCode() != http.StatusCreated {
+               msg := string(rspInvoker.Body)
+               log.Errorf("error on PostOnboardedInvokersWithResponse %s", msg)
+               return sendCoreError(ctx, rspInvoker.StatusCode(), msg)
+       }
+
+       rspAPIProviderEnrolmentDetails := *rspInvoker.JSON201
+       apiInvokerId := *rspAPIProviderEnrolmentDetails.ApiInvokerId
+
+       uri := ctx.Request().Host + ctx.Request().URL.String()
+       ctx.Response().Header().Set(echo.HeaderLocation, ctx.Scheme()+`://`+path.Join(uri, apiInvokerId))
+       err = ctx.JSON(http.StatusCreated, rspAPIProviderEnrolmentDetails)
+       if err != nil {
+               // Something really bad happened, tell Echo that our handler failed
+               return err
+       }
+
+       return nil
+}
+
+// Deletes an individual API Invoker.
+func (im *InvokerManager) DeleteOnboardedInvokersOnboardingId(ctx echo.Context, onboardingId string) error {
+       log.Tracef("entering DeleteOnboardedInvokersOnboardingId onboardingId %s", onboardingId)
+
+       capifcoreUrl := fmt.Sprintf("%s://%s:%d/api-invoker-management/v1/", im.CapifProtocol, im.CapifIPv4, im.CapifPort)
+       client, err := invokerapi.NewClientWithResponses(capifcoreUrl)
+       if err != nil {
+               return err
+       }
+
+       var (
+               ctxHandler context.Context
+               cancel     context.CancelFunc
+       )
+       ctxHandler, cancel = context.WithCancel(context.Background())
+       defer cancel()
+
+       _, err = client.DeleteOnboardedInvokersOnboardingId(ctxHandler, onboardingId)
+
+       if err != nil {
+               msg := err.Error()
+               log.Errorf("error on DeleteOnboardedInvokersOnboardingId %s", msg)
+               return sendCoreError(ctx, http.StatusInternalServerError, msg)
+       }
+
+       return ctx.NoContent(http.StatusNoContent)
+}
+
+
+// Updates an individual API invoker details.
+func (im *InvokerManager) PutOnboardedInvokersOnboardingId(ctx echo.Context, onboardingId string) error {
+       log.Tracef("entering DeleteOnboardedInvokersOnboardingId onboardingId %s", onboardingId)
+
+       var invoker invokerapi.APIInvokerEnrolmentDetails
+       errMsg := "Unable to update invoker due to %s"
+       if err := ctx.Bind(&invoker); err != nil {
+               return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, "invalid format for invoker"))
+       }
+
+       capifcoreUrl := fmt.Sprintf("%s://%s:%d/api-invoker-management/v1/", im.CapifProtocol, im.CapifIPv4, im.CapifPort)
+       client, err := invokerapi.NewClientWithResponses(capifcoreUrl)
+       if err != nil {
+               return err
+       }
+
+       var (
+               ctxHandler context.Context
+               cancel     context.CancelFunc
+       )
+       ctxHandler, cancel = context.WithCancel(context.Background())
+       defer cancel()
+
+       putRegistrationsJSONRequestBody := invokerapi.PutOnboardedInvokersOnboardingIdJSONRequestBody(invoker)
+
+       var rspInvoker *invokerapi.PutOnboardedInvokersOnboardingIdResponse
+       rspInvoker, err = client.PutOnboardedInvokersOnboardingIdWithResponse(ctxHandler, onboardingId, putRegistrationsJSONRequestBody)
+
+       if err != nil {
+               // Something really bad happened, tell Echo that our handler failed
+               return err
+       }
+
+       if rspInvoker.StatusCode() != http.StatusOK {
+               msg := string(rspInvoker.Body)
+               return sendCoreError(ctx, rspInvoker.StatusCode(), msg)
+       }
+
+       rspAPIProviderEnrolmentDetails := *rspInvoker.JSON200
+       apiInvokerId := *rspAPIProviderEnrolmentDetails.ApiInvokerId
+
+       uri := ctx.Request().Host + ctx.Request().URL.String()
+       ctx.Response().Header().Set(echo.HeaderLocation, ctx.Scheme()+`://`+path.Join(uri, apiInvokerId))
+       err = ctx.JSON(http.StatusOK, rspAPIProviderEnrolmentDetails)
+       if err != nil {
+               // Something really bad happened, tell Echo that our handler failed
+               return err
+       }
+
+       return nil
+}
+
+func (im *InvokerManager) ModifyIndApiInvokeEnrolment(ctx echo.Context, onboardingId string) error {
+       return ctx.NoContent(http.StatusNotImplemented)
+}
+
+// This function wraps sending of an error in the Error format, and
+// handling the failure to marshal that.
+func sendCoreError(ctx echo.Context, code int, message string) error {
+       pd := common29122.ProblemDetails{
+               Cause:  &message,
+               Status: &code,
+       }
+       err := ctx.JSON(code, pd)
+       return err
+}
diff --git a/servicemanager/internal/invokermanagement/invokermanagement_test.go b/servicemanager/internal/invokermanagement/invokermanagement_test.go
new file mode 100644 (file)
index 0000000..bca6c7f
--- /dev/null
@@ -0,0 +1,529 @@
+// -
+//
+//             ========================LICENSE_START=================================
+//             O-RAN-SC
+//             %%
+//       Copyright (C) 2023-2024: OpenInfra Foundation Europe
+//             %%
+//             Licensed under the Apache License, Version 2.0 (the "License");
+//             you may not use this file except in compliance with the License.
+//             You may obtain a copy of the License at
+//
+//                  http://www.apache.org/licenses/LICENSE-2.0
+//
+//             Unless required by applicable law or agreed to in writing, software
+//             distributed under the License is distributed on an "AS IS" BASIS,
+//             WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//             See the License for the specific language governing permissions and
+//             limitations under the License.
+//             ========================LICENSE_END===================================
+package invokermanagement
+
+import (
+       "fmt"
+       "net/http"
+       "os"
+       "strings"
+       "testing"
+
+       "oransc.org/nonrtric/servicemanager/internal/common29122"
+       "oransc.org/nonrtric/servicemanager/internal/envreader"
+       "oransc.org/nonrtric/servicemanager/internal/invokermanagementapi"
+       "oransc.org/nonrtric/servicemanager/internal/kongclear"
+       "oransc.org/nonrtric/servicemanager/internal/providermanagement"
+       provapi "oransc.org/nonrtric/servicemanager/internal/providermanagementapi"
+       "oransc.org/nonrtric/servicemanager/internal/publishservice"
+       publishapi "oransc.org/nonrtric/servicemanager/internal/publishserviceapi"
+
+       "github.com/deepmap/oapi-codegen/pkg/middleware"
+       "github.com/deepmap/oapi-codegen/pkg/testutil"
+       "github.com/labstack/echo/v4"
+       echomiddleware "github.com/labstack/echo/v4/middleware"
+       log "github.com/sirupsen/logrus"
+       "github.com/stretchr/testify/assert"
+)
+
+var requestHandler *echo.Echo
+
+func TestMain(m *testing.M) {
+       err := setupTest()
+       if err != nil {
+               return
+       }
+
+       ret := m.Run()
+       if ret == 0 {
+               teardown()
+       }
+       os.Exit(ret)
+}
+
+func setupTest() error {
+       myEnv, myPorts, err := envreader.ReadDotEnv()
+       if err != nil {
+               log.Fatal("error loading environment file on setupTest")
+               return err
+       }
+
+       requestHandler, err = getEcho(myEnv, myPorts)
+       if err != nil {
+               log.Fatal("getEcho fatal error on setupTest")
+               return err
+       }
+       err = teardown()
+       if err != nil {
+               log.Fatal("getEcho fatal error on teardown")
+               return err
+       }
+
+       return err
+}
+
+func getProvider() provapi.APIProviderEnrolmentDetails {
+       var (
+               domainInfo  = "Kong"
+               funcInfoAPF = "rApp Kong as APF"
+               funcInfoAEF = "rApp Kong as AEF"
+       )
+
+       testFuncs := []provapi.APIProviderFunctionDetails{
+               {
+                       ApiProvFuncInfo: &funcInfoAPF,
+                       ApiProvFuncRole: provapi.ApiProviderFuncRoleAPF,
+                       RegInfo: provapi.RegistrationInformation{
+                               ApiProvPubKey: "APF-PublicKey",
+                       },
+               },
+               {
+                       ApiProvFuncInfo: &funcInfoAEF,
+                       ApiProvFuncRole: provapi.ApiProviderFuncRoleAEF,
+                       RegInfo: provapi.RegistrationInformation{
+                               ApiProvPubKey: "AEF-PublicKey",
+                       },
+               },
+       }
+       return provapi.APIProviderEnrolmentDetails{
+               RegSec:         "sec",
+               ApiProvDomInfo: &domainInfo,
+               ApiProvFuncs:   &testFuncs,
+       }
+}
+
+func teardown() error {
+       log.Trace("entering teardown")
+
+       t := new(testing.T) // Create a new testing.T instance for teardown
+
+       // Delete the invoker
+       invokerInfo := "invoker a"
+       invokerId := "api_invoker_id_" + strings.Replace(invokerInfo, " ", "_", 1)
+
+       result := testutil.NewRequest().Delete("/api-invoker-management/v1/onboardedInvokers/"+invokerId).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNoContent, result.Code())
+
+       // Delete the original published service
+       apfId := "APF_id_rApp_Kong_as_APF"
+       apiName := "apiName"
+       apiId := "api_id_" + apiName
+
+       result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNoContent, result.Code())
+
+       // Delete the first published service
+       apfId = "APF_id_rApp_Kong_as_APF"
+       apiName = "apiName1"
+       apiId = "api_id_" + apiName
+
+       result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNoContent, result.Code())
+
+       // Delete the second published service
+       apiName = "apiName2"
+       apiId = "api_id_" + apiName
+
+       result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNoContent, result.Code())
+
+       // Delete the provider
+       domainID := "domain_id_Kong"
+       result = testutil.NewRequest().Delete("/api-provider-management/v1/registrations/"+domainID).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNoContent, result.Code())
+
+       myEnv, myPorts, err := envreader.ReadDotEnv()
+       if err != nil {
+               log.Fatal("error loading environment file")
+               return err
+       }
+
+       err = kongclear.KongClear(myEnv, myPorts)
+       if err != nil {
+               log.Fatal("error clearing Kong on teardown")
+       }
+       return err
+}
+
+func TestRegisterValidProvider(t *testing.T) {
+       teardown()
+
+       newProvider := getProvider()
+
+       // Register a valid provider
+       result := testutil.NewRequest().Post("/api-provider-management/v1/registrations").WithJsonBody(newProvider).Go(t, requestHandler)
+       assert.Equal(t, http.StatusCreated, result.Code())
+
+       var resultProvider provapi.APIProviderEnrolmentDetails
+       err := result.UnmarshalBodyToObject(&resultProvider)
+       assert.NoError(t, err, "error unmarshaling response")
+}
+
+func TestPublishUnpublishService(t *testing.T) {
+       apfId := "APF_id_rApp_Kong_as_APF"
+       apiName := "apiName"
+       newApiId := "api_id_" + apiName
+
+       myEnv, myPorts, err := envreader.ReadDotEnv()
+       assert.Nil(t, err, "error reading env file")
+
+       testServiceIpv4 := common29122.Ipv4Addr(myEnv["TEST_SERVICE_IPV4"])
+       testServicePort := common29122.Port(myPorts["TEST_SERVICE_PORT"])
+
+       assert.NotEmpty(t, testServiceIpv4, "TEST_SERVICE_IPV4 is required in .env file for unit testing")
+       assert.NotZero(t, testServicePort, "TEST_SERVICE_PORT is required in .env file for unit testing")
+
+       // Check no services published
+       result := testutil.NewRequest().Get("/published-apis/v1/"+apfId+"/service-apis").Go(t, requestHandler)
+       assert.Equal(t, http.StatusOK, result.Code())
+
+       // Parse JSON from the response body
+       var resultServices []publishapi.ServiceAPIDescription
+       err = result.UnmarshalJsonToObject(&resultServices)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       // Check if the parsed array is empty
+       assert.Zero(t, len(resultServices))
+
+       aefId := "AEF_id_rApp_Kong_as_AEF"
+       namespace := "namespace"
+       repoName := "repoName"
+       chartName := "chartName"
+       releaseName := "releaseName"
+       description := fmt.Sprintf("Description,%s,%s,%s,%s", namespace, repoName, chartName, releaseName)
+
+       newServiceDescription := getServiceAPIDescription(aefId, apiName, description, testServiceIpv4, testServicePort)
+
+       // Publish a service for provider
+       result = testutil.NewRequest().Post("/published-apis/v1/"+apfId+"/service-apis").WithJsonBody(newServiceDescription).Go(t, requestHandler)
+       assert.Equal(t, http.StatusCreated, result.Code())
+
+       if result.Code() != http.StatusCreated {
+               log.Fatalf("failed to publish the service with HTTP result code %d", result.Code())
+               return
+       }
+
+       var resultService publishapi.ServiceAPIDescription
+       err = result.UnmarshalJsonToObject(&resultService)
+       assert.NoError(t, err, "error unmarshaling response")
+       assert.Equal(t, newApiId, *resultService.ApiId)
+
+       assert.Equal(t, "http://example.com/published-apis/v1/"+apfId+"/service-apis/"+*resultService.ApiId, result.Recorder.Header().Get(echo.HeaderLocation))
+
+       // Check that the service is published for the provider
+       result = testutil.NewRequest().Get("/published-apis/v1/"+apfId+"/service-apis/"+newApiId).Go(t, requestHandler)
+       assert.Equal(t, http.StatusOK, result.Code())
+
+       err = result.UnmarshalJsonToObject(&resultService)
+       assert.NoError(t, err, "error unmarshaling response")
+       assert.Equal(t, newApiId, *resultService.ApiId)
+
+       aefProfile := (*resultService.AefProfiles)[0]
+       interfaceDescription := (*aefProfile.InterfaceDescriptions)[0]
+
+       resultServiceIpv4 := *interfaceDescription.Ipv4Addr
+       resultServicePort := *interfaceDescription.Port
+
+       kongIPv4 := common29122.Ipv4Addr(myEnv["KONG_IPV4"])
+       kongDataPlanePort := common29122.Port(myPorts["KONG_DATA_PLANE_PORT"])
+
+       assert.NotEmpty(t, kongIPv4, "KONG_IPV4 is required in .env file for unit testing")
+       assert.NotZero(t, kongDataPlanePort, "KONG_DATA_PLANE_PORT is required in .env file for unit testing")
+
+       assert.Equal(t, kongIPv4, resultServiceIpv4)
+       assert.Equal(t, kongDataPlanePort, resultServicePort)
+}
+
+func TestOnboardInvoker(t *testing.T) {
+       invokerInfo := "invoker a"
+       newInvoker := getInvoker(invokerInfo)
+
+       // Onboard a valid invoker
+       result := testutil.NewRequest().Post("/api-invoker-management/v1/onboardedInvokers").WithJsonBody(newInvoker).Go(t, requestHandler)
+       assert.Equal(t, http.StatusCreated, result.Code())
+
+       var resultInvoker invokermanagementapi.APIInvokerEnrolmentDetails
+
+       err := result.UnmarshalBodyToObject(&resultInvoker)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       wantedInvokerId := "api_invoker_id_" + strings.Replace(invokerInfo, " ", "_", 1)
+
+       assert.Equal(t, wantedInvokerId, *resultInvoker.ApiInvokerId)
+       assert.Equal(t, newInvoker.NotificationDestination, resultInvoker.NotificationDestination)
+       assert.Equal(t, newInvoker.OnboardingInformation.ApiInvokerPublicKey, resultInvoker.OnboardingInformation.ApiInvokerPublicKey)
+
+       assert.Equal(t, "http://example.com/api-invoker-management/v1/onboardedInvokers/"+*resultInvoker.ApiInvokerId, result.Recorder.Header().Get(echo.HeaderLocation))
+
+       // Onboarding the same invoker should result in Forbidden
+       result = testutil.NewRequest().Post("/api-invoker-management/v1/onboardedInvokers").WithJsonBody(newInvoker).Go(t, requestHandler)
+
+       assert.Equal(t, http.StatusForbidden, result.Code())
+
+       var problemDetails common29122.ProblemDetails
+       err = result.UnmarshalBodyToObject(&problemDetails)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       assert.Equal(t, http.StatusForbidden, *problemDetails.Status)
+       assert.Contains(t, *problemDetails.Cause, "already onboarded")
+
+       // Onboard an invoker missing required NotificationDestination, should get 400 with problem details
+       invalidInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{
+               OnboardingInformation: invokermanagementapi.OnboardingInformation{
+                       ApiInvokerPublicKey: "newKey",
+               },
+       }
+       result = testutil.NewRequest().Post("/api-invoker-management/v1/onboardedInvokers").WithJsonBody(invalidInvoker).Go(t, requestHandler)
+       assert.Equal(t, http.StatusBadRequest, result.Code())
+
+       err = result.UnmarshalBodyToObject(&problemDetails)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       assert.Equal(t, http.StatusBadRequest, *problemDetails.Status)
+       assert.Contains(t, *problemDetails.Cause, "missing")
+       assert.Contains(t, *problemDetails.Cause, "NotificationDestination")
+
+       // Onboard an invoker missing required OnboardingInformation.ApiInvokerPublicKey, should get 400 with problem details
+       invalidInvoker = invokermanagementapi.APIInvokerEnrolmentDetails{
+               NotificationDestination: "http://golang.cafe/",
+       }
+
+       result = testutil.NewRequest().Post("/api-invoker-management/v1/onboardedInvokers").WithJsonBody(invalidInvoker).Go(t, requestHandler)
+       assert.Equal(t, http.StatusBadRequest, result.Code())
+
+       err = result.UnmarshalBodyToObject(&problemDetails)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       assert.Equal(t, http.StatusBadRequest, *problemDetails.Status)
+       assert.Contains(t, *problemDetails.Cause, "missing")
+       assert.Contains(t, *problemDetails.Cause, "OnboardingInformation.ApiInvokerPublicKey")
+}
+
+func TestDeleteInvoker(t *testing.T) {
+       invokerInfo := "invoker a"
+       invokerId := "api_invoker_id_" + strings.Replace(invokerInfo, " ", "_", 1)
+
+       // Delete the invoker
+       result := testutil.NewRequest().Delete("/api-invoker-management/v1/onboardedInvokers/"+invokerId).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNoContent, result.Code())
+}
+
+func TestUpdateInvoker(t *testing.T) {
+       invokerInfo := "invoker a"
+       invoker := getInvoker(invokerInfo)
+       invokerId := "api_invoker_id_" + strings.Replace(invokerInfo, " ", "_", 1)
+
+       // Onboard a valid invoker
+       result := testutil.NewRequest().Post("/api-invoker-management/v1/onboardedInvokers").WithJsonBody(invoker).Go(t, requestHandler)
+       assert.Equal(t, http.StatusCreated, result.Code())
+
+       // Update the invoker with valid invoker, should return 200 with updated invoker details
+       newNotifURL := "http://golang.org/"
+       invoker.NotificationDestination = common29122.Uri(newNotifURL)
+       newPublicKey := "newPublicKey"
+       invoker.OnboardingInformation.ApiInvokerPublicKey = newPublicKey
+
+       invoker.ApiInvokerId = &invokerId
+
+       result = testutil.NewRequest().Put("/api-invoker-management/v1/onboardedInvokers/"+invokerId).WithJsonBody(invoker).Go(t, requestHandler)
+       assert.Equal(t, http.StatusOK, result.Code())
+
+       var resultInvoker invokermanagementapi.APIInvokerEnrolmentDetails
+
+       err := result.UnmarshalBodyToObject(&resultInvoker)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       assert.Equal(t, invokerId, *resultInvoker.ApiInvokerId)
+       assert.Equal(t, newNotifURL, string(resultInvoker.NotificationDestination))
+       assert.Equal(t, newPublicKey, resultInvoker.OnboardingInformation.ApiInvokerPublicKey)
+
+       // Update with an invoker missing required NotificationDestination, should get 400 with problem details
+       validOnboardingInfo := invokermanagementapi.OnboardingInformation{
+               ApiInvokerPublicKey: "key",
+       }
+       invalidInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{
+               ApiInvokerId:          &invokerId,
+               OnboardingInformation: validOnboardingInfo,
+       }
+       result = testutil.NewRequest().Put("/api-invoker-management/v1/onboardedInvokers/"+invokerId).WithJsonBody(invalidInvoker).Go(t, requestHandler)
+       assert.Equal(t, http.StatusBadRequest, result.Code())
+
+       var problemDetails common29122.ProblemDetails
+       err = result.UnmarshalBodyToObject(&problemDetails)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       assert.Equal(t, http.StatusBadRequest, *problemDetails.Status)
+       assert.Contains(t, *problemDetails.Cause, "missing")
+       assert.Contains(t, *problemDetails.Cause, "NotificationDestination")
+
+       // Update with an invoker missing required OnboardingInformation.ApiInvokerPublicKey, should get 400 with problem details
+       invalidInvoker.NotificationDestination = "http://golang.org/"
+       invalidInvoker.OnboardingInformation = invokermanagementapi.OnboardingInformation{}
+       result = testutil.NewRequest().Put("/api-invoker-management/v1/onboardedInvokers/"+invokerId).WithJsonBody(invalidInvoker).Go(t, requestHandler)
+       assert.Equal(t, http.StatusBadRequest, result.Code())
+
+       err = result.UnmarshalBodyToObject(&problemDetails)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       assert.Equal(t, http.StatusBadRequest, *problemDetails.Status)
+       assert.Contains(t, *problemDetails.Cause, "missing")
+       assert.Contains(t, *problemDetails.Cause, "OnboardingInformation.ApiInvokerPublicKey")
+
+       // Update with an invoker with other ApiInvokerId than the one provided in the URL, should get 400 with problem details
+       invalidId := "1"
+       invalidInvoker.ApiInvokerId = &invalidId
+       invalidInvoker.OnboardingInformation = validOnboardingInfo
+       result = testutil.NewRequest().Put("/api-invoker-management/v1/onboardedInvokers/"+invokerId).WithJsonBody(invalidInvoker).Go(t, requestHandler)
+
+       assert.Equal(t, http.StatusBadRequest, result.Code())
+
+       err = result.UnmarshalBodyToObject(&problemDetails)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       assert.Equal(t, http.StatusBadRequest, *problemDetails.Status)
+       assert.Contains(t, *problemDetails.Cause, "APIInvokerEnrolmentDetails ApiInvokerId doesn't match path parameter")
+
+       // Update an invoker that has not been onboarded, should get 404 with problem details
+       missingId := "1"
+       invoker.ApiInvokerId = &missingId
+       result = testutil.NewRequest().Put("/api-invoker-management/v1/onboardedInvokers/"+missingId).WithJsonBody(invoker).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNotFound, result.Code())
+
+       err = result.UnmarshalBodyToObject(&problemDetails)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       assert.Equal(t, http.StatusNotFound, *problemDetails.Status)
+       assert.Contains(t, *problemDetails.Cause, "not been onboarded")
+       assert.Contains(t, *problemDetails.Cause, "invoker")
+       teardown()
+}
+
+func getEcho(myEnv map[string]string, myPorts map[string]int) (*echo.Echo, error) {
+       capifProtocol := myEnv["CAPIF_PROTOCOL"]
+       capifIPv4 := common29122.Ipv4Addr(myEnv["CAPIF_IPV4"])
+       capifPort := common29122.Port(myPorts["CAPIF_PORT"])
+       kongDomain := myEnv["KONG_DOMAIN"]
+       kongProtocol := myEnv["KONG_PROTOCOL"]
+       kongIPv4 := common29122.Ipv4Addr(myEnv["KONG_IPV4"])
+       kongDataPlanePort := common29122.Port(myPorts["KONG_DATA_PLANE_PORT"])
+       kongControlPlanePort := common29122.Port(myPorts["KONG_CONTROL_PLANE_PORT"])
+
+       e := echo.New()
+
+       // Register ProviderManagement
+       providerManagerSwagger, err := provapi.GetSwagger()
+       if err != nil {
+               log.Fatalf("error loading ProviderManagement swagger spec\n: %s", err)
+               return nil, err
+       }
+       providerManagerSwagger.Servers = nil
+       providerManager := providermanagement.NewProviderManager(capifProtocol, capifIPv4, capifPort)
+
+       var group *echo.Group
+
+       group = e.Group("/api-provider-management/v1")
+       group.Use(middleware.OapiRequestValidator(providerManagerSwagger))
+       provapi.RegisterHandlersWithBaseURL(e, providerManager, "/api-provider-management/v1")
+
+       publishServiceSwagger, err := publishapi.GetSwagger()
+       if err != nil {
+               fmt.Fprintf(os.Stderr, "Error loading PublishService swagger spec\n: %s", err)
+               return nil, err
+       }
+
+       publishServiceSwagger.Servers = nil
+
+       ps := publishservice.NewPublishService(kongDomain, kongProtocol, kongIPv4, kongDataPlanePort, kongControlPlanePort, capifProtocol, capifIPv4, capifPort)
+
+       group = e.Group("/published-apis/v1")
+       group.Use(echomiddleware.Logger())
+       group.Use(middleware.OapiRequestValidator(publishServiceSwagger))
+       publishapi.RegisterHandlersWithBaseURL(e, ps, "/published-apis/v1")
+
+       invokerServiceSwagger, err := invokermanagementapi.GetSwagger()
+       if err != nil {
+               fmt.Fprintf(os.Stderr, "Error loading InvokerManagement swagger spec\n: %s", err)
+               return nil, err
+       }
+
+       invokerServiceSwagger.Servers = nil
+
+       im := NewInvokerManager(capifProtocol, capifIPv4, capifPort)
+
+       group = e.Group("/api-invoker-management/v1")
+       group.Use(echomiddleware.Logger())
+       group.Use(middleware.OapiRequestValidator(invokerServiceSwagger))
+       invokermanagementapi.RegisterHandlersWithBaseURL(e, im, "api-invoker-management/v1")
+
+       return e, err
+}
+
+func getServiceAPIDescription(aefId, apiName, description string, testServiceIpv4 common29122.Ipv4Addr, testServicePort common29122.Port) publishapi.ServiceAPIDescription {
+       domainName := "Kong"
+       var protocol publishapi.Protocol = "HTTP_1_1"
+
+       return publishapi.ServiceAPIDescription{
+               AefProfiles: &[]publishapi.AefProfile{
+                       {
+                               AefId: aefId,
+                               InterfaceDescriptions: &[]publishapi.InterfaceDescription{
+                                       {
+                                               Ipv4Addr: &testServiceIpv4,
+                                               Port:     &testServicePort,
+                                               SecurityMethods: &[]publishapi.SecurityMethod{
+                                                       "PKI",
+                                               },
+                                       },
+                               },
+                               DomainName: &domainName,
+                               Protocol:   &protocol,
+                               Versions: []publishapi.Version{
+                                       {
+                                               ApiVersion: "v1",
+                                               Resources: &[]publishapi.Resource{
+                                                       {
+                                                               CommType: "REQUEST_RESPONSE",
+                                                               Operations: &[]publishapi.Operation{
+                                                                       "GET",
+                                                               },
+                                                               ResourceName: "helloworld",
+                                                               Uri:          "/helloworld",
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+               },
+               ApiName:     apiName,
+               Description: &description,
+       }
+}
+
+func getInvoker(invokerInfo string) invokermanagementapi.APIInvokerEnrolmentDetails {
+       newInvoker := invokermanagementapi.APIInvokerEnrolmentDetails{
+               ApiInvokerInformation:   &invokerInfo,
+               NotificationDestination: "http://golang.cafe/",
+               OnboardingInformation: invokermanagementapi.OnboardingInformation{
+                       ApiInvokerPublicKey: "key",
+               },
+               ApiList: nil,
+       }
+       return newInvoker
+}
diff --git a/servicemanager/internal/invokermanagementapi/invokermanagementapi-client.gen.go b/servicemanager/internal/invokermanagementapi/invokermanagementapi-client.gen.go
new file mode 100644 (file)
index 0000000..2ccb57b
--- /dev/null
@@ -0,0 +1,630 @@
+// Package invokermanagementapi provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/deepmap/oapi-codegen version v1.10.1 DO NOT EDIT.
+package invokermanagementapi
+
+import (
+       "bytes"
+       "context"
+       "encoding/json"
+       "fmt"
+       "io"
+       "io/ioutil"
+       "net/http"
+       "net/url"
+       "strings"
+
+       "github.com/deepmap/oapi-codegen/pkg/runtime"
+)
+
+// RequestEditorFn  is the function signature for the RequestEditor callback function
+type RequestEditorFn func(ctx context.Context, req *http.Request) error
+
+// Doer performs HTTP requests.
+//
+// The standard http.Client implements this interface.
+type HttpRequestDoer interface {
+       Do(req *http.Request) (*http.Response, error)
+}
+
+// Client which conforms to the OpenAPI3 specification for this service.
+type Client struct {
+       // The endpoint of the server conforming to this interface, with scheme,
+       // https://api.deepmap.com for example. This can contain a path relative
+       // to the server, such as https://api.deepmap.com/dev-test, and all the
+       // paths in the swagger spec will be appended to the server.
+       Server string
+
+       // Doer for performing requests, typically a *http.Client with any
+       // customized settings, such as certificate chains.
+       Client HttpRequestDoer
+
+       // A list of callbacks for modifying requests which are generated before sending over
+       // the network.
+       RequestEditors []RequestEditorFn
+}
+
+// ClientOption allows setting custom parameters during construction
+type ClientOption func(*Client) error
+
+// Creates a new Client, with reasonable defaults
+func NewClient(server string, opts ...ClientOption) (*Client, error) {
+       // create a client with sane default values
+       client := Client{
+               Server: server,
+       }
+       // mutate client and add all optional params
+       for _, o := range opts {
+               if err := o(&client); err != nil {
+                       return nil, err
+               }
+       }
+       // ensure the server URL always has a trailing slash
+       if !strings.HasSuffix(client.Server, "/") {
+               client.Server += "/"
+       }
+       // create httpClient, if not already present
+       if client.Client == nil {
+               client.Client = &http.Client{}
+       }
+       return &client, nil
+}
+
+// WithHTTPClient allows overriding the default Doer, which is
+// automatically created using http.Client. This is useful for tests.
+func WithHTTPClient(doer HttpRequestDoer) ClientOption {
+       return func(c *Client) error {
+               c.Client = doer
+               return nil
+       }
+}
+
+// WithRequestEditorFn allows setting up a callback function, which will be
+// called right before sending the request. This can be used to mutate the request.
+func WithRequestEditorFn(fn RequestEditorFn) ClientOption {
+       return func(c *Client) error {
+               c.RequestEditors = append(c.RequestEditors, fn)
+               return nil
+       }
+}
+
+// The interface specification for the client above.
+type ClientInterface interface {
+       // PostOnboardedInvokers request with any body
+       PostOnboardedInvokersWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+       PostOnboardedInvokers(ctx context.Context, body PostOnboardedInvokersJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+       // DeleteOnboardedInvokersOnboardingId request
+       DeleteOnboardedInvokersOnboardingId(ctx context.Context, onboardingId string, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+       // ModifyIndApiInvokeEnrolment request with any body
+       ModifyIndApiInvokeEnrolmentWithBody(ctx context.Context, onboardingId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+       // PutOnboardedInvokersOnboardingId request with any body
+       PutOnboardedInvokersOnboardingIdWithBody(ctx context.Context, onboardingId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+       PutOnboardedInvokersOnboardingId(ctx context.Context, onboardingId string, body PutOnboardedInvokersOnboardingIdJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error)
+}
+
+func (c *Client) PostOnboardedInvokersWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) {
+       req, err := NewPostOnboardedInvokersRequestWithBody(c.Server, contentType, body)
+       if err != nil {
+               return nil, err
+       }
+       req = req.WithContext(ctx)
+       if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+               return nil, err
+       }
+       return c.Client.Do(req)
+}
+
+func (c *Client) PostOnboardedInvokers(ctx context.Context, body PostOnboardedInvokersJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) {
+       req, err := NewPostOnboardedInvokersRequest(c.Server, body)
+       if err != nil {
+               return nil, err
+       }
+       req = req.WithContext(ctx)
+       if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+               return nil, err
+       }
+       return c.Client.Do(req)
+}
+
+func (c *Client) DeleteOnboardedInvokersOnboardingId(ctx context.Context, onboardingId string, reqEditors ...RequestEditorFn) (*http.Response, error) {
+       req, err := NewDeleteOnboardedInvokersOnboardingIdRequest(c.Server, onboardingId)
+       if err != nil {
+               return nil, err
+       }
+       req = req.WithContext(ctx)
+       if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+               return nil, err
+       }
+       return c.Client.Do(req)
+}
+
+func (c *Client) ModifyIndApiInvokeEnrolmentWithBody(ctx context.Context, onboardingId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) {
+       req, err := NewModifyIndApiInvokeEnrolmentRequestWithBody(c.Server, onboardingId, contentType, body)
+       if err != nil {
+               return nil, err
+       }
+       req = req.WithContext(ctx)
+       if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+               return nil, err
+       }
+       return c.Client.Do(req)
+}
+
+func (c *Client) PutOnboardedInvokersOnboardingIdWithBody(ctx context.Context, onboardingId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) {
+       req, err := NewPutOnboardedInvokersOnboardingIdRequestWithBody(c.Server, onboardingId, contentType, body)
+       if err != nil {
+               return nil, err
+       }
+       req = req.WithContext(ctx)
+       if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+               return nil, err
+       }
+       return c.Client.Do(req)
+}
+
+func (c *Client) PutOnboardedInvokersOnboardingId(ctx context.Context, onboardingId string, body PutOnboardedInvokersOnboardingIdJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) {
+       req, err := NewPutOnboardedInvokersOnboardingIdRequest(c.Server, onboardingId, body)
+       if err != nil {
+               return nil, err
+       }
+       req = req.WithContext(ctx)
+       if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+               return nil, err
+       }
+       return c.Client.Do(req)
+}
+
+// NewPostOnboardedInvokersRequest calls the generic PostOnboardedInvokers builder with application/json body
+func NewPostOnboardedInvokersRequest(server string, body PostOnboardedInvokersJSONRequestBody) (*http.Request, error) {
+       var bodyReader io.Reader
+       buf, err := json.Marshal(body)
+       if err != nil {
+               return nil, err
+       }
+       bodyReader = bytes.NewReader(buf)
+       return NewPostOnboardedInvokersRequestWithBody(server, "application/json", bodyReader)
+}
+
+// NewPostOnboardedInvokersRequestWithBody generates requests for PostOnboardedInvokers with any type of body
+func NewPostOnboardedInvokersRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) {
+       var err error
+
+       serverURL, err := url.Parse(server)
+       if err != nil {
+               return nil, err
+       }
+
+       operationPath := fmt.Sprintf("/onboardedInvokers")
+       if operationPath[0] == '/' {
+               operationPath = "." + operationPath
+       }
+
+       queryURL, err := serverURL.Parse(operationPath)
+       if err != nil {
+               return nil, err
+       }
+
+       req, err := http.NewRequest("POST", queryURL.String(), body)
+       if err != nil {
+               return nil, err
+       }
+
+       req.Header.Add("Content-Type", contentType)
+
+       return req, nil
+}
+
+// NewDeleteOnboardedInvokersOnboardingIdRequest generates requests for DeleteOnboardedInvokersOnboardingId
+func NewDeleteOnboardedInvokersOnboardingIdRequest(server string, onboardingId string) (*http.Request, error) {
+       var err error
+
+       var pathParam0 string
+
+       pathParam0, err = runtime.StyleParamWithLocation("simple", false, "onboardingId", runtime.ParamLocationPath, onboardingId)
+       if err != nil {
+               return nil, err
+       }
+
+       serverURL, err := url.Parse(server)
+       if err != nil {
+               return nil, err
+       }
+
+       operationPath := fmt.Sprintf("/onboardedInvokers/%s", pathParam0)
+       if operationPath[0] == '/' {
+               operationPath = "." + operationPath
+       }
+
+       queryURL, err := serverURL.Parse(operationPath)
+       if err != nil {
+               return nil, err
+       }
+
+       req, err := http.NewRequest("DELETE", queryURL.String(), nil)
+       if err != nil {
+               return nil, err
+       }
+
+       return req, nil
+}
+
+// NewModifyIndApiInvokeEnrolmentRequestWithBody generates requests for ModifyIndApiInvokeEnrolment with any type of body
+func NewModifyIndApiInvokeEnrolmentRequestWithBody(server string, onboardingId string, contentType string, body io.Reader) (*http.Request, error) {
+       var err error
+
+       var pathParam0 string
+
+       pathParam0, err = runtime.StyleParamWithLocation("simple", false, "onboardingId", runtime.ParamLocationPath, onboardingId)
+       if err != nil {
+               return nil, err
+       }
+
+       serverURL, err := url.Parse(server)
+       if err != nil {
+               return nil, err
+       }
+
+       operationPath := fmt.Sprintf("/onboardedInvokers/%s", pathParam0)
+       if operationPath[0] == '/' {
+               operationPath = "." + operationPath
+       }
+
+       queryURL, err := serverURL.Parse(operationPath)
+       if err != nil {
+               return nil, err
+       }
+
+       req, err := http.NewRequest("PATCH", queryURL.String(), body)
+       if err != nil {
+               return nil, err
+       }
+
+       req.Header.Add("Content-Type", contentType)
+
+       return req, nil
+}
+
+// NewPutOnboardedInvokersOnboardingIdRequest calls the generic PutOnboardedInvokersOnboardingId builder with application/json body
+func NewPutOnboardedInvokersOnboardingIdRequest(server string, onboardingId string, body PutOnboardedInvokersOnboardingIdJSONRequestBody) (*http.Request, error) {
+       var bodyReader io.Reader
+       buf, err := json.Marshal(body)
+       if err != nil {
+               return nil, err
+       }
+       bodyReader = bytes.NewReader(buf)
+       return NewPutOnboardedInvokersOnboardingIdRequestWithBody(server, onboardingId, "application/json", bodyReader)
+}
+
+// NewPutOnboardedInvokersOnboardingIdRequestWithBody generates requests for PutOnboardedInvokersOnboardingId with any type of body
+func NewPutOnboardedInvokersOnboardingIdRequestWithBody(server string, onboardingId string, contentType string, body io.Reader) (*http.Request, error) {
+       var err error
+
+       var pathParam0 string
+
+       pathParam0, err = runtime.StyleParamWithLocation("simple", false, "onboardingId", runtime.ParamLocationPath, onboardingId)
+       if err != nil {
+               return nil, err
+       }
+
+       serverURL, err := url.Parse(server)
+       if err != nil {
+               return nil, err
+       }
+
+       operationPath := fmt.Sprintf("/onboardedInvokers/%s", pathParam0)
+       if operationPath[0] == '/' {
+               operationPath = "." + operationPath
+       }
+
+       queryURL, err := serverURL.Parse(operationPath)
+       if err != nil {
+               return nil, err
+       }
+
+       req, err := http.NewRequest("PUT", queryURL.String(), body)
+       if err != nil {
+               return nil, err
+       }
+
+       req.Header.Add("Content-Type", contentType)
+
+       return req, nil
+}
+
+func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error {
+       for _, r := range c.RequestEditors {
+               if err := r(ctx, req); err != nil {
+                       return err
+               }
+       }
+       for _, r := range additionalEditors {
+               if err := r(ctx, req); err != nil {
+                       return err
+               }
+       }
+       return nil
+}
+
+// ClientWithResponses builds on ClientInterface to offer response payloads
+type ClientWithResponses struct {
+       ClientInterface
+}
+
+// NewClientWithResponses creates a new ClientWithResponses, which wraps
+// Client with return type handling
+func NewClientWithResponses(server string, opts ...ClientOption) (*ClientWithResponses, error) {
+       client, err := NewClient(server, opts...)
+       if err != nil {
+               return nil, err
+       }
+       return &ClientWithResponses{client}, nil
+}
+
+// WithBaseURL overrides the baseURL.
+func WithBaseURL(baseURL string) ClientOption {
+       return func(c *Client) error {
+               newBaseURL, err := url.Parse(baseURL)
+               if err != nil {
+                       return err
+               }
+               c.Server = newBaseURL.String()
+               return nil
+       }
+}
+
+// ClientWithResponsesInterface is the interface specification for the client with responses above.
+type ClientWithResponsesInterface interface {
+       // PostOnboardedInvokers request with any body
+       PostOnboardedInvokersWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostOnboardedInvokersResponse, error)
+
+       PostOnboardedInvokersWithResponse(ctx context.Context, body PostOnboardedInvokersJSONRequestBody, reqEditors ...RequestEditorFn) (*PostOnboardedInvokersResponse, error)
+
+       // DeleteOnboardedInvokersOnboardingId request
+       DeleteOnboardedInvokersOnboardingIdWithResponse(ctx context.Context, onboardingId string, reqEditors ...RequestEditorFn) (*DeleteOnboardedInvokersOnboardingIdResponse, error)
+
+       // ModifyIndApiInvokeEnrolment request with any body
+       ModifyIndApiInvokeEnrolmentWithBodyWithResponse(ctx context.Context, onboardingId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*ModifyIndApiInvokeEnrolmentResponse, error)
+
+       // PutOnboardedInvokersOnboardingId request with any body
+       PutOnboardedInvokersOnboardingIdWithBodyWithResponse(ctx context.Context, onboardingId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PutOnboardedInvokersOnboardingIdResponse, error)
+
+       PutOnboardedInvokersOnboardingIdWithResponse(ctx context.Context, onboardingId string, body PutOnboardedInvokersOnboardingIdJSONRequestBody, reqEditors ...RequestEditorFn) (*PutOnboardedInvokersOnboardingIdResponse, error)
+}
+
+type PostOnboardedInvokersResponse struct {
+       Body         []byte
+       HTTPResponse *http.Response
+       JSON201      *APIInvokerEnrolmentDetails
+}
+
+// Status returns HTTPResponse.Status
+func (r PostOnboardedInvokersResponse) Status() string {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.Status
+       }
+       return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r PostOnboardedInvokersResponse) StatusCode() int {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.StatusCode
+       }
+       return 0
+}
+
+type DeleteOnboardedInvokersOnboardingIdResponse struct {
+       Body         []byte
+       HTTPResponse *http.Response
+}
+
+// Status returns HTTPResponse.Status
+func (r DeleteOnboardedInvokersOnboardingIdResponse) Status() string {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.Status
+       }
+       return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r DeleteOnboardedInvokersOnboardingIdResponse) StatusCode() int {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.StatusCode
+       }
+       return 0
+}
+
+type ModifyIndApiInvokeEnrolmentResponse struct {
+       Body         []byte
+       HTTPResponse *http.Response
+       JSON200      *APIInvokerEnrolmentDetails
+}
+
+// Status returns HTTPResponse.Status
+func (r ModifyIndApiInvokeEnrolmentResponse) Status() string {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.Status
+       }
+       return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r ModifyIndApiInvokeEnrolmentResponse) StatusCode() int {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.StatusCode
+       }
+       return 0
+}
+
+type PutOnboardedInvokersOnboardingIdResponse struct {
+       Body         []byte
+       HTTPResponse *http.Response
+       JSON200      *APIInvokerEnrolmentDetails
+}
+
+// Status returns HTTPResponse.Status
+func (r PutOnboardedInvokersOnboardingIdResponse) Status() string {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.Status
+       }
+       return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r PutOnboardedInvokersOnboardingIdResponse) StatusCode() int {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.StatusCode
+       }
+       return 0
+}
+
+// PostOnboardedInvokersWithBodyWithResponse request with arbitrary body returning *PostOnboardedInvokersResponse
+func (c *ClientWithResponses) PostOnboardedInvokersWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostOnboardedInvokersResponse, error) {
+       rsp, err := c.PostOnboardedInvokersWithBody(ctx, contentType, body, reqEditors...)
+       if err != nil {
+               return nil, err
+       }
+       return ParsePostOnboardedInvokersResponse(rsp)
+}
+
+func (c *ClientWithResponses) PostOnboardedInvokersWithResponse(ctx context.Context, body PostOnboardedInvokersJSONRequestBody, reqEditors ...RequestEditorFn) (*PostOnboardedInvokersResponse, error) {
+       rsp, err := c.PostOnboardedInvokers(ctx, body, reqEditors...)
+       if err != nil {
+               return nil, err
+       }
+       return ParsePostOnboardedInvokersResponse(rsp)
+}
+
+// DeleteOnboardedInvokersOnboardingIdWithResponse request returning *DeleteOnboardedInvokersOnboardingIdResponse
+func (c *ClientWithResponses) DeleteOnboardedInvokersOnboardingIdWithResponse(ctx context.Context, onboardingId string, reqEditors ...RequestEditorFn) (*DeleteOnboardedInvokersOnboardingIdResponse, error) {
+       rsp, err := c.DeleteOnboardedInvokersOnboardingId(ctx, onboardingId, reqEditors...)
+       if err != nil {
+               return nil, err
+       }
+       return ParseDeleteOnboardedInvokersOnboardingIdResponse(rsp)
+}
+
+// ModifyIndApiInvokeEnrolmentWithBodyWithResponse request with arbitrary body returning *ModifyIndApiInvokeEnrolmentResponse
+func (c *ClientWithResponses) ModifyIndApiInvokeEnrolmentWithBodyWithResponse(ctx context.Context, onboardingId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*ModifyIndApiInvokeEnrolmentResponse, error) {
+       rsp, err := c.ModifyIndApiInvokeEnrolmentWithBody(ctx, onboardingId, contentType, body, reqEditors...)
+       if err != nil {
+               return nil, err
+       }
+       return ParseModifyIndApiInvokeEnrolmentResponse(rsp)
+}
+
+// PutOnboardedInvokersOnboardingIdWithBodyWithResponse request with arbitrary body returning *PutOnboardedInvokersOnboardingIdResponse
+func (c *ClientWithResponses) PutOnboardedInvokersOnboardingIdWithBodyWithResponse(ctx context.Context, onboardingId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PutOnboardedInvokersOnboardingIdResponse, error) {
+       rsp, err := c.PutOnboardedInvokersOnboardingIdWithBody(ctx, onboardingId, contentType, body, reqEditors...)
+       if err != nil {
+               return nil, err
+       }
+       return ParsePutOnboardedInvokersOnboardingIdResponse(rsp)
+}
+
+func (c *ClientWithResponses) PutOnboardedInvokersOnboardingIdWithResponse(ctx context.Context, onboardingId string, body PutOnboardedInvokersOnboardingIdJSONRequestBody, reqEditors ...RequestEditorFn) (*PutOnboardedInvokersOnboardingIdResponse, error) {
+       rsp, err := c.PutOnboardedInvokersOnboardingId(ctx, onboardingId, body, reqEditors...)
+       if err != nil {
+               return nil, err
+       }
+       return ParsePutOnboardedInvokersOnboardingIdResponse(rsp)
+}
+
+// ParsePostOnboardedInvokersResponse parses an HTTP response from a PostOnboardedInvokersWithResponse call
+func ParsePostOnboardedInvokersResponse(rsp *http.Response) (*PostOnboardedInvokersResponse, error) {
+       bodyBytes, err := ioutil.ReadAll(rsp.Body)
+       defer func() { _ = rsp.Body.Close() }()
+       if err != nil {
+               return nil, err
+       }
+
+       response := &PostOnboardedInvokersResponse{
+               Body:         bodyBytes,
+               HTTPResponse: rsp,
+       }
+
+       switch {
+       case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 201:
+               var dest APIInvokerEnrolmentDetails
+               if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+                       return nil, err
+               }
+               response.JSON201 = &dest
+
+       }
+
+       return response, nil
+}
+
+// ParseDeleteOnboardedInvokersOnboardingIdResponse parses an HTTP response from a DeleteOnboardedInvokersOnboardingIdWithResponse call
+func ParseDeleteOnboardedInvokersOnboardingIdResponse(rsp *http.Response) (*DeleteOnboardedInvokersOnboardingIdResponse, error) {
+       bodyBytes, err := ioutil.ReadAll(rsp.Body)
+       defer func() { _ = rsp.Body.Close() }()
+       if err != nil {
+               return nil, err
+       }
+
+       response := &DeleteOnboardedInvokersOnboardingIdResponse{
+               Body:         bodyBytes,
+               HTTPResponse: rsp,
+       }
+
+       return response, nil
+}
+
+// ParseModifyIndApiInvokeEnrolmentResponse parses an HTTP response from a ModifyIndApiInvokeEnrolmentWithResponse call
+func ParseModifyIndApiInvokeEnrolmentResponse(rsp *http.Response) (*ModifyIndApiInvokeEnrolmentResponse, error) {
+       bodyBytes, err := ioutil.ReadAll(rsp.Body)
+       defer func() { _ = rsp.Body.Close() }()
+       if err != nil {
+               return nil, err
+       }
+
+       response := &ModifyIndApiInvokeEnrolmentResponse{
+               Body:         bodyBytes,
+               HTTPResponse: rsp,
+       }
+
+       switch {
+       case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
+               var dest APIInvokerEnrolmentDetails
+               if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+                       return nil, err
+               }
+               response.JSON200 = &dest
+
+       }
+
+       return response, nil
+}
+
+// ParsePutOnboardedInvokersOnboardingIdResponse parses an HTTP response from a PutOnboardedInvokersOnboardingIdWithResponse call
+func ParsePutOnboardedInvokersOnboardingIdResponse(rsp *http.Response) (*PutOnboardedInvokersOnboardingIdResponse, error) {
+       bodyBytes, err := ioutil.ReadAll(rsp.Body)
+       defer func() { _ = rsp.Body.Close() }()
+       if err != nil {
+               return nil, err
+       }
+
+       response := &PutOnboardedInvokersOnboardingIdResponse{
+               Body:         bodyBytes,
+               HTTPResponse: rsp,
+       }
+
+       switch {
+       case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
+               var dest APIInvokerEnrolmentDetails
+               if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+                       return nil, err
+               }
+               response.JSON200 = &dest
+
+       }
+
+       return response, nil
+}
diff --git a/servicemanager/internal/invokermanagementapi/invokermanagementapi-server.gen.go b/servicemanager/internal/invokermanagementapi/invokermanagementapi-server.gen.go
new file mode 100644 (file)
index 0000000..baa1355
--- /dev/null
@@ -0,0 +1,266 @@
+// Package invokermanagementapi provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/deepmap/oapi-codegen version v1.10.1 DO NOT EDIT.
+package invokermanagementapi
+
+import (
+       "bytes"
+       "compress/gzip"
+       "encoding/base64"
+       "fmt"
+       "net/http"
+       "net/url"
+       "path"
+       "strings"
+
+       "github.com/deepmap/oapi-codegen/pkg/runtime"
+       "github.com/getkin/kin-openapi/openapi3"
+       "github.com/labstack/echo/v4"
+       externalRef0 "oransc.org/nonrtric/servicemanager/internal/common29122"
+       externalRef1 "oransc.org/nonrtric/servicemanager/internal/common29571"
+       externalRef2 "oransc.org/nonrtric/servicemanager/internal/publishserviceapi"
+)
+
+// ServerInterface represents all server handlers.
+type ServerInterface interface {
+
+       // (POST /onboardedInvokers)
+       PostOnboardedInvokers(ctx echo.Context) error
+
+       // (DELETE /onboardedInvokers/{onboardingId})
+       DeleteOnboardedInvokersOnboardingId(ctx echo.Context, onboardingId string) error
+
+       // (PATCH /onboardedInvokers/{onboardingId})
+       ModifyIndApiInvokeEnrolment(ctx echo.Context, onboardingId string) error
+
+       // (PUT /onboardedInvokers/{onboardingId})
+       PutOnboardedInvokersOnboardingId(ctx echo.Context, onboardingId string) error
+}
+
+// ServerInterfaceWrapper converts echo contexts to parameters.
+type ServerInterfaceWrapper struct {
+       Handler ServerInterface
+}
+
+// PostOnboardedInvokers converts echo context to params.
+func (w *ServerInterfaceWrapper) PostOnboardedInvokers(ctx echo.Context) error {
+       var err error
+
+       // Invoke the callback with all the unmarshalled arguments
+       err = w.Handler.PostOnboardedInvokers(ctx)
+       return err
+}
+
+// DeleteOnboardedInvokersOnboardingId converts echo context to params.
+func (w *ServerInterfaceWrapper) DeleteOnboardedInvokersOnboardingId(ctx echo.Context) error {
+       var err error
+       // ------------- Path parameter "onboardingId" -------------
+       var onboardingId string
+
+       err = runtime.BindStyledParameterWithLocation("simple", false, "onboardingId", runtime.ParamLocationPath, ctx.Param("onboardingId"), &onboardingId)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter onboardingId: %s", err))
+       }
+
+       // Invoke the callback with all the unmarshalled arguments
+       err = w.Handler.DeleteOnboardedInvokersOnboardingId(ctx, onboardingId)
+       return err
+}
+
+// ModifyIndApiInvokeEnrolment converts echo context to params.
+func (w *ServerInterfaceWrapper) ModifyIndApiInvokeEnrolment(ctx echo.Context) error {
+       var err error
+       // ------------- Path parameter "onboardingId" -------------
+       var onboardingId string
+
+       err = runtime.BindStyledParameterWithLocation("simple", false, "onboardingId", runtime.ParamLocationPath, ctx.Param("onboardingId"), &onboardingId)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter onboardingId: %s", err))
+       }
+
+       // Invoke the callback with all the unmarshalled arguments
+       err = w.Handler.ModifyIndApiInvokeEnrolment(ctx, onboardingId)
+       return err
+}
+
+// PutOnboardedInvokersOnboardingId converts echo context to params.
+func (w *ServerInterfaceWrapper) PutOnboardedInvokersOnboardingId(ctx echo.Context) error {
+       var err error
+       // ------------- Path parameter "onboardingId" -------------
+       var onboardingId string
+
+       err = runtime.BindStyledParameterWithLocation("simple", false, "onboardingId", runtime.ParamLocationPath, ctx.Param("onboardingId"), &onboardingId)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter onboardingId: %s", err))
+       }
+
+       // Invoke the callback with all the unmarshalled arguments
+       err = w.Handler.PutOnboardedInvokersOnboardingId(ctx, onboardingId)
+       return err
+}
+
+// This is a simple interface which specifies echo.Route addition functions which
+// are present on both echo.Echo and echo.Group, since we want to allow using
+// either of them for path registration
+type EchoRouter interface {
+       CONNECT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       DELETE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       GET(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       HEAD(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       OPTIONS(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       PATCH(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       POST(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       PUT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       TRACE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+}
+
+// RegisterHandlers adds each server route to the EchoRouter.
+func RegisterHandlers(router EchoRouter, si ServerInterface) {
+       RegisterHandlersWithBaseURL(router, si, "")
+}
+
+// Registers handlers, and prepends BaseURL to the paths, so that the paths
+// can be served under a prefix.
+func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL string) {
+
+       wrapper := ServerInterfaceWrapper{
+               Handler: si,
+       }
+
+       router.POST(baseURL+"/onboardedInvokers", wrapper.PostOnboardedInvokers)
+       router.DELETE(baseURL+"/onboardedInvokers/:onboardingId", wrapper.DeleteOnboardedInvokersOnboardingId)
+       router.PATCH(baseURL+"/onboardedInvokers/:onboardingId", wrapper.ModifyIndApiInvokeEnrolment)
+       router.PUT(baseURL+"/onboardedInvokers/:onboardingId", wrapper.PutOnboardedInvokersOnboardingId)
+
+}
+
+// Base64 encoded, gzipped, json marshaled Swagger object
+var swaggerSpec = []string{
+
+       "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",
+}
+
+// GetSwagger returns the content of the embedded swagger specification file
+// or error if failed to decode
+func decodeSpec() ([]byte, error) {
+       zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, ""))
+       if err != nil {
+               return nil, fmt.Errorf("error base64 decoding spec: %s", err)
+       }
+       zr, err := gzip.NewReader(bytes.NewReader(zipped))
+       if err != nil {
+               return nil, fmt.Errorf("error decompressing spec: %s", err)
+       }
+       var buf bytes.Buffer
+       _, err = buf.ReadFrom(zr)
+       if err != nil {
+               return nil, fmt.Errorf("error decompressing spec: %s", err)
+       }
+
+       return buf.Bytes(), nil
+}
+
+var rawSpec = decodeSpecCached()
+
+// a naive cached of a decoded swagger spec
+func decodeSpecCached() func() ([]byte, error) {
+       data, err := decodeSpec()
+       return func() ([]byte, error) {
+               return data, err
+       }
+}
+
+// Constructs a synthetic filesystem for resolving external references when loading openapi specifications.
+func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) {
+       var res = make(map[string]func() ([]byte, error))
+       if len(pathToFile) > 0 {
+               res[pathToFile] = rawSpec
+       }
+
+       pathPrefix := path.Dir(pathToFile)
+
+       for rawPath, rawFunc := range externalRef0.PathToRawSpec(path.Join(pathPrefix, "TS29122_CommonData.yaml")) {
+               if _, ok := res[rawPath]; ok {
+                       // it is not possible to compare functions in golang, so always overwrite the old value
+               }
+               res[rawPath] = rawFunc
+       }
+       for rawPath, rawFunc := range externalRef2.PathToRawSpec(path.Join(pathPrefix, "TS29222_CAPIF_Publish_Service_API.yaml")) {
+               if _, ok := res[rawPath]; ok {
+                       // it is not possible to compare functions in golang, so always overwrite the old value
+               }
+               res[rawPath] = rawFunc
+       }
+       for rawPath, rawFunc := range externalRef1.PathToRawSpec(path.Join(pathPrefix, "TS29571_CommonData.yaml")) {
+               if _, ok := res[rawPath]; ok {
+                       // it is not possible to compare functions in golang, so always overwrite the old value
+               }
+               res[rawPath] = rawFunc
+       }
+       return res
+}
+
+// GetSwagger returns the Swagger specification corresponding to the generated code
+// in this file. The external references of Swagger specification are resolved.
+// The logic of resolving external references is tightly connected to "import-mapping" feature.
+// Externally referenced files must be embedded in the corresponding golang packages.
+// Urls can be supported but this task was out of the scope.
+func GetSwagger() (swagger *openapi3.T, err error) {
+       var resolvePath = PathToRawSpec("")
+
+       loader := openapi3.NewLoader()
+       loader.IsExternalRefsAllowed = true
+       loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) {
+               var pathToFile = url.String()
+               pathToFile = path.Clean(pathToFile)
+               getSpec, ok := resolvePath[pathToFile]
+               if !ok {
+                       err1 := fmt.Errorf("path not found: %s", pathToFile)
+                       return nil, err1
+               }
+               return getSpec()
+       }
+       var specData []byte
+       specData, err = rawSpec()
+       if err != nil {
+               return
+       }
+       swagger, err = loader.LoadFromData(specData)
+       if err != nil {
+               return
+       }
+       return
+}
diff --git a/servicemanager/internal/invokermanagementapi/invokermanagementapi-types.gen.go b/servicemanager/internal/invokermanagementapi/invokermanagementapi-types.gen.go
new file mode 100644 (file)
index 0000000..1ce5807
--- /dev/null
@@ -0,0 +1,94 @@
+// Package invokermanagementapi provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/deepmap/oapi-codegen version v1.10.1 DO NOT EDIT.
+package invokermanagementapi
+
+import (
+       externalRef0 "oransc.org/nonrtric/servicemanager/internal/common29122"
+       externalRef1 "oransc.org/nonrtric/servicemanager/internal/common29571"
+       externalRef2 "oransc.org/nonrtric/servicemanager/internal/publishserviceapi"
+)
+
+// Information about the API Invoker that requested to onboard
+type APIInvokerEnrolmentDetails struct {
+       // API invoker ID assigned by the CAPIF core function to the API invoker while on-boarding the API invoker. Shall not be present in the HTTP POST request from the API invoker to the CAPIF core function, to on-board itself. Shall be present in all other HTTP requests and responses.
+       ApiInvokerId *string `json:"apiInvokerId,omitempty"`
+
+       // Generic information related to the API invoker such as details of the device or the application.
+       ApiInvokerInformation *string `json:"apiInvokerInformation,omitempty"`
+
+       // The list of service APIs that the API Invoker is allowed to invoke
+       ApiList *APIList `json:"apiList,omitempty"`
+
+       // string providing an URI formatted according to IETF RFC 3986.
+       NotificationDestination externalRef0.Uri `json:"notificationDestination"`
+
+       // Represents on-boarding information of the API invoker.
+       OnboardingInformation OnboardingInformation `json:"onboardingInformation"`
+
+       // Set to true by Subscriber to request the CAPIF core function to send a test notification as defined in in clause 7.6. Set to false or omitted otherwise.
+       RequestTestNotification *bool `json:"requestTestNotification,omitempty"`
+
+       // A string used to indicate the features supported by an API that is used as defined in clause  6.6 in 3GPP TS 29.500. The string shall contain a bitmask indicating supported features in  hexadecimal representation Each character in the string shall take a value of "0" to "9",  "a" to "f" or "A" to "F" and shall represent the support of 4 features as described in  table 5.2.2-3. The most significant character representing the highest-numbered features shall  appear first in the string, and the character representing features 1 to 4 shall appear last  in the string. The list of features and their numbering (starting with 1) are defined  separately for each API. If the string contains a lower number of characters than there are  defined features for an API, all features that would be represented by characters that are not  present in the string are not supported.
+       SupportedFeatures *externalRef1.SupportedFeatures `json:"supportedFeatures,omitempty"`
+
+       // Represents the configuration information for the delivery of notifications over Websockets.
+       WebsockNotifConfig *externalRef0.WebsockNotifConfig `json:"websockNotifConfig,omitempty"`
+}
+
+// Represents an API Invoker's enrolment details to be updated.
+type APIInvokerEnrolmentDetailsPatch struct {
+       // Generic information related to the API invoker such as details of the device or the application.
+       ApiInvokerInformation *string `json:"apiInvokerInformation,omitempty"`
+
+       // The list of service APIs that the API Invoker is allowed to invoke
+       ApiList *APIList `json:"apiList,omitempty"`
+
+       // string providing an URI formatted according to IETF RFC 3986.
+       NotificationDestination *externalRef0.Uri `json:"notificationDestination,omitempty"`
+
+       // Represents on-boarding information of the API invoker.
+       OnboardingInformation *OnboardingInformation `json:"onboardingInformation,omitempty"`
+}
+
+// The list of service APIs that the API Invoker is allowed to invoke
+type APIList []externalRef2.ServiceAPIDescription
+
+// Represents on-boarding information of the API invoker.
+type OnboardingInformation struct {
+       // The API Invoker's generic client certificate, provided by the CAPIF core function.
+       ApiInvokerCertificate *string `json:"apiInvokerCertificate,omitempty"`
+
+       // The API Invoker's public key
+       ApiInvokerPublicKey string `json:"apiInvokerPublicKey"`
+
+       // The API Invoker's onboarding secret, provided by the CAPIF core function.
+       OnboardingSecret *string `json:"onboardingSecret,omitempty"`
+}
+
+// Represents a notification of on-boarding or update result.
+type OnboardingNotification struct {
+       // Information about the API Invoker that requested to onboard
+       ApiInvokerEnrolmentDetails *APIInvokerEnrolmentDetails `json:"apiInvokerEnrolmentDetails,omitempty"`
+
+       // The list of service APIs that the API Invoker is allowed to invoke
+       ApiList *APIList `json:"apiList,omitempty"`
+
+       // string providing an URI formatted according to IETF RFC 3986.
+       ResourceLocation *externalRef0.Uri `json:"resourceLocation,omitempty"`
+
+       // Set to "true" indicate successful on-boarding. Otherwise set to "false"
+       Result bool `json:"result"`
+}
+
+// PostOnboardedInvokersJSONBody defines parameters for PostOnboardedInvokers.
+type PostOnboardedInvokersJSONBody APIInvokerEnrolmentDetails
+
+// PutOnboardedInvokersOnboardingIdJSONBody defines parameters for PutOnboardedInvokersOnboardingId.
+type PutOnboardedInvokersOnboardingIdJSONBody APIInvokerEnrolmentDetails
+
+// PostOnboardedInvokersJSONRequestBody defines body for PostOnboardedInvokers for application/json ContentType.
+type PostOnboardedInvokersJSONRequestBody PostOnboardedInvokersJSONBody
+
+// PutOnboardedInvokersOnboardingIdJSONRequestBody defines body for PutOnboardedInvokersOnboardingId for application/json ContentType.
+type PutOnboardedInvokersOnboardingIdJSONRequestBody PutOnboardedInvokersOnboardingIdJSONBody
diff --git a/servicemanager/internal/kongclear/kongclear.go b/servicemanager/internal/kongclear/kongclear.go
new file mode 100644 (file)
index 0000000..068cd7d
--- /dev/null
@@ -0,0 +1,194 @@
+// -\r
+//   ========================LICENSE_START=================================\r
+//   O-RAN-SC\r
+//   %%\r
+//   Copyright (C) 2024: OpenInfra Foundation Europe\r
+//   %%\r
+//   Licensed under the Apache License, Version 2.0 (the "License");\r
+//   you may not use this file except in compliance with the License.\r
+//   You may obtain a copy of the License at\r
+//\r
+//        http://www.apache.org/licenses/LICENSE-2.0\r
+//\r
+//   Unless required by applicable law or agreed to in writing, software\r
+//   distributed under the License is distributed on an "AS IS" BASIS,\r
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+//   See the License for the specific language governing permissions and\r
+//   limitations under the License.\r
+//   ========================LICENSE_END===================================\r
+//\r
+\r
+package kongclear\r
+\r
+import (\r
+       "encoding/json"\r
+       "fmt"\r
+       "net/http"\r
+\r
+       log "github.com/sirupsen/logrus"\r
+       resty "github.com/go-resty/resty/v2"\r
+)\r
+\r
+// Service represents the structure for Kong service creation\r
+type KongService struct {\r
+       ID   string `json:"id"`\r
+       Name string `json:"name"`\r
+       URL  string `json:"url"`\r
+}\r
+\r
+type KongServiceResponse struct {\r
+       ID string `json:"id"`\r
+}\r
+\r
+type ServiceResponse struct {\r
+       Data []KongService `json:"data"`\r
+}\r
+\r
+type KongRoute struct {\r
+       ID        string   `json:"id"`\r
+       Name      string   `json:"name"`\r
+       Paths     []string `json:"paths"`\r
+       Service   Service  `json:"service"`\r
+       StripPath bool     `json:"strip_path"`\r
+}\r
+\r
+type RouteResponse struct {\r
+       Data []KongRoute `json:"data"`\r
+}\r
+\r
+type Service struct {\r
+       ID string `json:"id"`\r
+}\r
+\r
+func KongClear(myEnv map[string]string, myPorts map[string]int) error {\r
+       log.Info("attempting to delete all Kong routes and services")\r
+\r
+       kongAdminApiUrl := fmt.Sprintf("%s://%s:%d/", myEnv["KONG_PROTOCOL"], myEnv["KONG_IPV4"], myPorts["KONG_CONTROL_PLANE_PORT"])\r
+\r
+       err := deleteAllRoutes(kongAdminApiUrl)\r
+       if err != nil {\r
+               log.Fatalf("error deleting routes %v", err)\r
+               return err\r
+       }\r
+\r
+       err = deleteAllServices(kongAdminApiUrl)\r
+       if err != nil {\r
+               log.Fatalf("error deleting services %v", err)\r
+               return err\r
+       }\r
+\r
+       log.Info("all Kong routes and services deleted successfully")\r
+       return err\r
+}\r
+\r
+\r
+func deleteAllRoutes(kongAdminApiUrl string) error {\r
+       routes, err := listRoutes(kongAdminApiUrl)\r
+       if err != nil {\r
+               return err\r
+       }\r
+\r
+       for _, route := range routes {\r
+               if err := deleteRoute(kongAdminApiUrl, route.ID); err != nil {\r
+                       return err\r
+               }\r
+       }\r
+\r
+       return nil\r
+}\r
+\r
+func deleteAllServices(kongAdminApiUrl string) error {\r
+       services, err := listServices(kongAdminApiUrl)\r
+       if err != nil {\r
+               return err\r
+       }\r
+\r
+       for _, service := range services {\r
+               if err := deleteService(kongAdminApiUrl, service.ID); err != nil {\r
+                       return err\r
+               }\r
+       }\r
+\r
+       return nil\r
+}\r
+\r
+func listServices(kongAdminApiUrl string) ([]KongService, error) {\r
+       client := resty.New()\r
+       resp, err := client.R().Get(kongAdminApiUrl + "services")\r
+\r
+       if err != nil {\r
+               return nil, err\r
+       }\r
+\r
+       if resp.StatusCode() != http.StatusOK {\r
+               err := fmt.Errorf("failed to list services, status code %d", resp.StatusCode())\r
+               return nil, err\r
+       }\r
+\r
+       var serviceResponse ServiceResponse\r
+       err = json.Unmarshal(resp.Body(), &serviceResponse)\r
+       if err != nil {\r
+               return nil, err\r
+       }\r
+\r
+       log.Infof("kong services %v", serviceResponse.Data)\r
+       return serviceResponse.Data, nil\r
+}\r
+\r
+func listRoutes(kongAdminApiUrl string) ([]KongRoute, error) {\r
+       client := resty.New()\r
+       resp, err := client.R().\r
+               Get(kongAdminApiUrl + "routes")\r
+\r
+       if err != nil {\r
+               return nil, err\r
+       }\r
+\r
+       if resp.StatusCode() != http.StatusOK {\r
+               err := fmt.Errorf("failed to list routes, status code %d", resp.StatusCode())\r
+               return nil, err\r
+       }\r
+\r
+       var routeResponse RouteResponse\r
+       err = json.Unmarshal(resp.Body(), &routeResponse)\r
+       if err != nil {\r
+               return nil, err\r
+       }\r
+\r
+       log.Infof("kong routes %v", routeResponse.Data)\r
+       return routeResponse.Data, nil\r
+}\r
+\r
+func deleteService(kongAdminApiUrl string, serviceID string) error {\r
+       log.Tracef("entering deleteService service ID %v", serviceID)\r
+       client := resty.New()\r
+       resp, err := client.R().Delete(kongAdminApiUrl + "services/" + serviceID)\r
+\r
+       if err != nil {\r
+               return err\r
+       }\r
+\r
+       if resp.StatusCode() != http.StatusNoContent {\r
+               err := fmt.Errorf("failed to delete service %s, status code %d", serviceID, resp.StatusCode())\r
+               return err\r
+       }\r
+\r
+       return nil\r
+}\r
+\r
+func deleteRoute(kongAdminApiUrl string, routeID string) error {\r
+       log.Infof("kong route id %v", routeID)\r
+       client := resty.New()\r
+       resp, err := client.R().Delete(kongAdminApiUrl + "routes/" + routeID)\r
+\r
+       if err != nil {\r
+               return err\r
+       }\r
+\r
+       if resp.StatusCode() != http.StatusNoContent {\r
+               err := fmt.Errorf("failed to delete route %s, status code %d", routeID, resp.StatusCode())\r
+               return err\r
+       }\r
+\r
+       return nil\r
+}
\ No newline at end of file
diff --git a/servicemanager/internal/kongclearup.go b/servicemanager/internal/kongclearup.go
new file mode 100644 (file)
index 0000000..c4bd2a2
--- /dev/null
@@ -0,0 +1,40 @@
+// -
+//   ========================LICENSE_START=================================
+//   O-RAN-SC
+//   %%
+//   Copyright (C) 2024: OpenInfra Foundation Europe
+//   %%
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//        http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+//   ========================LICENSE_END===================================
+//
+
+package main
+
+import (
+       "log"
+
+       "oransc.org/nonrtric/servicemanager/internal/envreader"
+       "oransc.org/nonrtric/servicemanager/internal/kongclear"
+)
+
+func main() {
+       myEnv, myPorts, err := envreader.ReadDotEnv()
+       if err != nil {
+               log.Fatal("error loading environment file")
+       }
+
+       err = kongclear.KongClear(myEnv, myPorts)
+       if err != nil {
+               log.Fatal("error clearing Kong")
+       }
+}
diff --git a/servicemanager/internal/providermanagement/providermanagement.go b/servicemanager/internal/providermanagement/providermanagement.go
new file mode 100644 (file)
index 0000000..9202b1a
--- /dev/null
@@ -0,0 +1,198 @@
+// -
+//   ========================LICENSE_START=================================
+//   O-RAN-SC
+//   %%
+//   Copyright (C) 2023: OpenInfra Foundation Europe
+//   %%
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//        http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+//   ========================LICENSE_END===================================
+//
+
+package providermanagement
+
+import (
+       "context"
+       "fmt"
+       "net/http"
+       "path"
+
+       echo "github.com/labstack/echo/v4"
+       log "github.com/sirupsen/logrus"
+
+       "oransc.org/nonrtric/servicemanager/internal/common29122"
+       provapi "oransc.org/nonrtric/servicemanager/internal/providermanagementapi"
+)
+
+type ProviderManager struct {
+       registeredProviders map[string]provapi.APIProviderEnrolmentDetails
+       CapifProtocol       string
+       CapifIPv4           common29122.Ipv4Addr
+       CapifPort           common29122.Port
+}
+
+func NewProviderManager(capifProtocol string, capifIPv4 common29122.Ipv4Addr, capifPort common29122.Port) *ProviderManager {
+       return &ProviderManager{
+               registeredProviders: make(map[string]provapi.APIProviderEnrolmentDetails),
+               CapifProtocol:       capifProtocol,
+               CapifIPv4:           capifIPv4,
+               CapifPort:           capifPort,
+       }
+}
+
+func (pm *ProviderManager) PostRegistrations(ctx echo.Context) error {
+       log.Trace("entering PostRegistrations")
+
+       newProvider, err := getProviderFromRequest(ctx)
+       if err != nil {
+               errMsg := "Unable to register provider due to %s"
+               return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, err))
+       }
+
+       capifcoreUrl := fmt.Sprintf("%s://%s:%d/api-provider-management/v1/", pm.CapifProtocol, pm.CapifIPv4, pm.CapifPort)
+       client, err := provapi.NewClientWithResponses(capifcoreUrl)
+       if err != nil {
+               return err
+       }
+
+       var (
+               ctxHandler context.Context
+               cancel     context.CancelFunc
+       )
+       ctxHandler, cancel = context.WithCancel(context.Background())
+       defer cancel()
+
+       postRegistrationsJSONRequestBody := provapi.PostRegistrationsJSONRequestBody(newProvider)
+
+       var rspProvider *provapi.PostRegistrationsResponse
+       rspProvider, err = client.PostRegistrationsWithResponse(ctxHandler, postRegistrationsJSONRequestBody)
+
+       if (err != nil) || (rspProvider.StatusCode() != http.StatusCreated) {
+               msg := string(rspProvider.Body)
+               log.Errorf("error on PostRegistrationsWithResponse %s", msg)
+               return sendCoreError(ctx, rspProvider.StatusCode(), msg)
+       }
+
+       rspAPIProviderEnrolmentDetails := *rspProvider.JSON201
+       apiProvDomId := *rspAPIProviderEnrolmentDetails.ApiProvDomId
+
+       uri := ctx.Request().Host + ctx.Request().URL.String()
+       ctx.Response().Header().Set(echo.HeaderLocation, ctx.Scheme()+`://` + path.Join(uri, apiProvDomId))
+       if err := ctx.JSON(http.StatusCreated, rspAPIProviderEnrolmentDetails); err != nil {
+               // Something really bad happened, tell Echo that our handler failed
+               return err
+       }
+       return nil
+}
+
+func (pm *ProviderManager) DeleteRegistrationsRegistrationId(ctx echo.Context, registrationId string) error {
+       log.Tracef("entering DeleteRegistrationsRegistrationId registrationId %s", registrationId)
+
+       capifcoreUrl := fmt.Sprintf("%s://%s:%d/api-provider-management/v1/", pm.CapifProtocol, pm.CapifIPv4, pm.CapifPort)
+       client, err := provapi.NewClientWithResponses(capifcoreUrl)
+       if err != nil {
+               return err
+       }
+
+       var (
+               ctxHandler context.Context
+               cancel     context.CancelFunc
+       )
+       ctxHandler, cancel = context.WithCancel(context.Background())
+       defer cancel()
+
+       var rspProvider *provapi.DeleteRegistrationsRegistrationIdResponse
+       rspProvider, err = client.DeleteRegistrationsRegistrationIdWithResponse(ctxHandler, registrationId)
+
+       if (err != nil) || (rspProvider.StatusCode() != http.StatusNoContent) {
+               msg := string(rspProvider.Body)
+               log.Errorf("error on DeleteRegistrationsRegistrationIdWithResponse %s", msg)
+               return sendCoreError(ctx, rspProvider.StatusCode(), msg)
+       }
+       return ctx.NoContent(http.StatusNoContent)
+}
+
+func (pm *ProviderManager) PutRegistrationsRegistrationId(ctx echo.Context, registrationId string) error {
+       log.Trace("entering PutRegistrationsRegistrationId")
+
+       updatedProvider, err := getProviderFromRequest(ctx)
+       if err != nil {
+               msg := "Unable to register provider due to %s"
+               log.Errorf("error on getProviderFromRequest %s", msg)
+               return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(msg, err))
+       }
+
+       capifcoreUrl := fmt.Sprintf("%s://%s:%d/api-provider-management/v1/", pm.CapifProtocol, pm.CapifIPv4, pm.CapifPort)
+       client, err := provapi.NewClientWithResponses(capifcoreUrl)
+       if err != nil {
+               return err
+       }
+
+       var (
+               ctxHandler context.Context
+               cancel     context.CancelFunc
+       )
+       ctxHandler, cancel = context.WithCancel(context.Background())
+       defer cancel()
+
+       putRegistrationsRegistrationIdJSONRequestBody := provapi.PutRegistrationsRegistrationIdJSONRequestBody(updatedProvider)
+
+       var rspProvider *provapi.PutRegistrationsRegistrationIdResponse
+       rspProvider, err = client.PutRegistrationsRegistrationIdWithResponse(ctxHandler, registrationId, putRegistrationsRegistrationIdJSONRequestBody)
+
+       if err != nil {
+               msg := err.Error()
+               log.Errorf("error on PutRegistrationsRegistrationIdWithResponse %s", msg)
+               return sendCoreError(ctx, http.StatusInternalServerError, msg)
+       }
+
+       if rspProvider.StatusCode() != http.StatusOK {
+               msg := string(rspProvider.Body)
+               log.Errorf("error on PutRegistrationsRegistrationIdWithResponse %s", msg)
+               return sendCoreError(ctx, rspProvider.StatusCode(), msg)
+       }
+
+       rspAPIProviderEnrolmentDetails := *rspProvider.JSON200
+       apiProvDomId := *rspAPIProviderEnrolmentDetails.ApiProvDomId
+
+       uri := ctx.Request().Host + ctx.Request().URL.String()
+       ctx.Response().Header().Set(echo.HeaderLocation, ctx.Scheme()+`://` + path.Join(uri, apiProvDomId))
+       if err := ctx.JSON(http.StatusOK, rspAPIProviderEnrolmentDetails); err != nil {
+               // Something really bad happened, tell Echo that our handler failed
+               return err
+       }
+       return nil
+}
+
+func (pm *ProviderManager) ModifyIndApiProviderEnrolment(ctx echo.Context, registrationId string) error {
+       return ctx.NoContent(http.StatusNotImplemented)
+}
+
+func getProviderFromRequest(ctx echo.Context) (provapi.APIProviderEnrolmentDetails, error) {
+       var updatedProvider provapi.APIProviderEnrolmentDetails
+       err := ctx.Bind(&updatedProvider)
+       if err != nil {
+               return provapi.APIProviderEnrolmentDetails{}, fmt.Errorf("invalid format for provider")
+       }
+       return updatedProvider, nil
+}
+
+// This function wraps sending of an error in the Error format, and
+// handling the failure to marshal that.
+func sendCoreError(ctx echo.Context, code int, message string) error {
+       pd := common29122.ProblemDetails{
+               Cause:  &message,
+               Status: &code,
+       }
+       err := ctx.JSON(code, pd)
+       return err
+}
diff --git a/servicemanager/internal/providermanagement/providermanagement_test.go b/servicemanager/internal/providermanagement/providermanagement_test.go
new file mode 100644 (file)
index 0000000..f00afd0
--- /dev/null
@@ -0,0 +1,290 @@
+// -
+//   ========================LICENSE_START=================================
+//   O-RAN-SC
+//   %%
+//   Copyright (C) 2024: OpenInfra Foundation Europe
+//   %%
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//        http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+//   ========================LICENSE_END===================================
+//
+
+package providermanagement
+
+import (
+       "fmt"
+       "net/http"
+       "os"
+       "strings"
+       "testing"
+
+       echo "github.com/labstack/echo/v4"
+
+       "oransc.org/nonrtric/servicemanager/internal/common29122"
+       "oransc.org/nonrtric/servicemanager/internal/envreader"
+       "oransc.org/nonrtric/servicemanager/internal/kongclear"
+       provapi "oransc.org/nonrtric/servicemanager/internal/providermanagementapi"
+       "oransc.org/nonrtric/servicemanager/internal/publishservice"
+       publishapi "oransc.org/nonrtric/servicemanager/internal/publishserviceapi"
+
+       "github.com/deepmap/oapi-codegen/pkg/middleware"
+       "github.com/deepmap/oapi-codegen/pkg/testutil"
+       echomiddleware "github.com/labstack/echo/v4/middleware"
+       log "github.com/sirupsen/logrus"
+       "github.com/stretchr/testify/assert"
+)
+
+var (
+       domainID = "domain_id_Kong"
+       domainInfo  = "Kong"
+       funcInfoAPF = "rApp Kong as APF"
+       funcIdAPF   = "APF_id_rApp_Kong_as_APF"
+       funcInfoAEF = "rApp Kong as AEF"
+       funcIdAEF   = "AEF_id_rApp_Kong_as_AEF"
+)
+
+var requestHandler *echo.Echo
+
+func TestMain(m *testing.M) {
+       err := setupTest()
+       if err != nil {
+               return
+       }
+
+       ret := m.Run()
+       if ret == 0 {
+               teardown()
+       }
+       os.Exit(ret)
+}
+
+func setupTest() error {
+       myEnv, myPorts, err := envreader.ReadDotEnv()
+       if err != nil {
+               log.Fatal("error loading environment file on setupTest")
+               return err
+       }
+
+       requestHandler, err = getEcho(myEnv, myPorts)
+       if err != nil {
+               log.Fatal("getEcho fatal error on setupTest")
+               return err
+       }
+       return err
+}
+
+func teardown() error {
+       log.Trace("entering teardown")
+
+       t := new(testing.T) // Create a new testing.T instance for teardown
+
+       // Delete the invoker
+       invokerInfo := "invoker a"
+       invokerId := "api_invoker_id_" + strings.Replace(invokerInfo, " ", "_", 1)
+
+       result := testutil.NewRequest().Delete("/api-invoker-management/v1/onboardedInvokers/"+invokerId).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNoContent, result.Code())
+
+       // Delete the original published service
+       apfId := "APF_id_rApp_Kong_as_APF"
+       apiName := "apiName"
+       apiId := "api_id_" + apiName
+
+       result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNoContent, result.Code())
+
+       // Delete the first published service
+       apfId = "APF_id_rApp_Kong_as_APF"
+       apiName = "apiName1"
+       apiId = "api_id_" + apiName
+
+       result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNoContent, result.Code())
+
+       // Delete the second published service
+       apiName = "apiName2"
+       apiId = "api_id_" + apiName
+
+       result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNoContent, result.Code())
+
+       // Delete the provider
+       result = testutil.NewRequest().Delete("/api-provider-management/v1/registrations/"+domainID).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNoContent, result.Code())
+
+       myEnv, myPorts, err := envreader.ReadDotEnv()
+       if err != nil {
+               log.Fatal("error loading environment file")
+               return err
+       }
+
+       err = kongclear.KongClear(myEnv, myPorts)
+       if err != nil {
+               log.Fatal("error clearing Kong on teardown")
+       }
+       return err
+}
+
+func TestRegisterValidProvider(t *testing.T) {
+       teardown()
+
+       // Register a valid provider
+       newProvider := getProvider()
+       result := testutil.NewRequest().Post("/api-provider-management/v1/registrations").WithJsonBody(newProvider).Go(t, requestHandler)
+       assert.Equal(t, http.StatusCreated, result.Code())
+
+       var resultProvider provapi.APIProviderEnrolmentDetails
+       err := result.UnmarshalBodyToObject(&resultProvider)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       assert.NotNil(t, resultProvider.ApiProvDomId, "error reading resultProvider")
+
+       if resultProvider.ApiProvDomId != nil {
+               assert.Equal(t, *resultProvider.ApiProvDomId, domainID)
+
+               apiProvFuncAPF := (*resultProvider.ApiProvFuncs)[0]
+               apiProvFuncIdAPF := *apiProvFuncAPF.ApiProvFuncId
+               assert.Equal(t, apiProvFuncIdAPF, funcIdAPF)
+
+               // We don't handle AMF
+               apiProvFuncAEF := (*resultProvider.ApiProvFuncs)[1]
+               apiProvFuncIdAEF := *apiProvFuncAEF.ApiProvFuncId
+               assert.Equal(t, apiProvFuncIdAEF, funcIdAEF)
+
+               assert.Empty(t, resultProvider.FailReason)
+               assert.Equal(t, "http://example.com/api-provider-management/v1/registrations/"+*resultProvider.ApiProvDomId, result.Recorder.Header().Get(echo.HeaderLocation))
+
+               // Register same provider again should result in Forbidden
+               result = testutil.NewRequest().Post("/api-provider-management/v1/registrations").WithJsonBody(newProvider).Go(t, requestHandler)
+
+               var errorObj common29122.ProblemDetails
+               assert.Equal(t, http.StatusForbidden, result.Code())
+
+               err = result.UnmarshalBodyToObject(&errorObj)
+               assert.NoError(t, err, "error unmarshaling response")
+               assert.Equal(t, http.StatusForbidden, *errorObj.Status)
+               assert.Contains(t, *errorObj.Cause, "already registered")
+       }
+}
+
+func TestUpdateValidProviderWithNewFunction(t *testing.T) {
+       // Modify the provider
+       updatedProvider := getProvider()
+       updatedProvider.ApiProvDomId = &domainID
+
+       newDomainInfo := "New domain info"
+       updatedProvider.ApiProvDomInfo = &newDomainInfo
+       newFunctionInfo := "New function info"
+       (*updatedProvider.ApiProvFuncs)[0].ApiProvFuncInfo = &newFunctionInfo
+       newFuncInfoAEF := "new func as AEF"
+
+       testFuncs := append(*updatedProvider.ApiProvFuncs, provapi.APIProviderFunctionDetails{
+               ApiProvFuncInfo: &newFuncInfoAEF,
+               ApiProvFuncRole: provapi.ApiProviderFuncRoleAEF,
+               RegInfo: provapi.RegistrationInformation{
+                       ApiProvPubKey: "key",
+               },
+       })
+       updatedProvider.ApiProvFuncs = &testFuncs
+
+       result := testutil.NewRequest().Put("/api-provider-management/v1/registrations/"+domainID).WithJsonBody(updatedProvider).Go(t, requestHandler)
+
+       var resultProvider provapi.APIProviderEnrolmentDetails
+       assert.Equal(t, http.StatusOK, result.Code())
+
+       err := result.UnmarshalBodyToObject(&resultProvider)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       assert.Equal(t, newDomainInfo, *resultProvider.ApiProvDomInfo)
+       assert.Equal(t, newFunctionInfo, *(*resultProvider.ApiProvFuncs)[0].ApiProvFuncInfo)
+       assert.Equal(t, *(*resultProvider.ApiProvFuncs)[2].ApiProvFuncId, "AEF_id_new_func_as_AEF")
+       assert.Empty(t, resultProvider.FailReason)
+}
+
+func TestDeleteProvider(t *testing.T) {
+       provider := getProvider()
+       provider.ApiProvDomId = &domainID
+       (*provider.ApiProvFuncs)[0].ApiProvFuncId = &funcIdAPF
+       result := testutil.NewRequest().Delete("/api-provider-management/v1/registrations/"+domainID).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNoContent, result.Code())
+       teardown()
+}
+
+func getProvider() provapi.APIProviderEnrolmentDetails {
+       testFuncs := []provapi.APIProviderFunctionDetails{
+               {
+                       ApiProvFuncInfo: &funcInfoAPF,
+                       ApiProvFuncRole: provapi.ApiProviderFuncRoleAPF,
+                       RegInfo: provapi.RegistrationInformation{
+                               ApiProvPubKey: "APF-PublicKey",
+                       },
+               },
+               {
+                       ApiProvFuncInfo: &funcInfoAEF,
+                       ApiProvFuncRole: provapi.ApiProviderFuncRoleAEF,
+                       RegInfo: provapi.RegistrationInformation{
+                               ApiProvPubKey: "AEF-PublicKey",
+                       },
+               },
+       }
+       return provapi.APIProviderEnrolmentDetails{
+               RegSec:         "sec",
+               ApiProvDomInfo: &domainInfo,
+               ApiProvFuncs:   &testFuncs,
+       }
+}
+
+func getEcho(myEnv map[string]string, myPorts map[string]int) (*echo.Echo, error) {
+       capifProtocol := myEnv["CAPIF_PROTOCOL"]
+       capifIPv4 := common29122.Ipv4Addr(myEnv["CAPIF_IPV4"])
+       capifPort := common29122.Port(myPorts["CAPIF_PORT"])
+       kongDomain := myEnv["KONG_DOMAIN"]
+       kongProtocol := myEnv["KONG_PROTOCOL"]
+       kongIPv4 := common29122.Ipv4Addr(myEnv["KONG_IPV4"])
+       kongDataPlanePort := common29122.Port(myPorts["KONG_DATA_PLANE_PORT"])
+       kongControlPlanePort := common29122.Port(myPorts["KONG_CONTROL_PLANE_PORT"])
+
+       e := echo.New()
+
+       // Register ProviderManagement
+       providerManagerSwagger, err := provapi.GetSwagger()
+       if err != nil {
+               log.Fatalf("Error loading ProviderManagement swagger spec\n: %s", err)
+               return nil, err
+       }
+       providerManagerSwagger.Servers = nil
+       providerManager := NewProviderManager(capifProtocol, capifIPv4, capifPort)
+
+       var group *echo.Group
+
+       group = e.Group("/api-provider-management/v1")
+       group.Use(middleware.OapiRequestValidator(providerManagerSwagger))
+       provapi.RegisterHandlersWithBaseURL(e, providerManager, "/api-provider-management/v1")
+
+       publishServiceSwagger, err := publishapi.GetSwagger()
+       if err != nil {
+               fmt.Fprintf(os.Stderr, "Error loading PublishService swagger spec\n: %s", err)
+               return nil, err
+       }
+
+       publishServiceSwagger.Servers = nil
+
+       ps := publishservice.NewPublishService(kongDomain, kongProtocol, kongIPv4, kongDataPlanePort, kongControlPlanePort, capifProtocol, capifIPv4, capifPort)
+
+       group = e.Group("/published-apis/v1")
+       group.Use(echomiddleware.Logger())
+       group.Use(middleware.OapiRequestValidator(publishServiceSwagger))
+       publishapi.RegisterHandlersWithBaseURL(e, ps, "/published-apis/v1")
+
+       // return ps, eventChannel, e
+       return e, err
+}
diff --git a/servicemanager/internal/providermanagementapi/providermanagementapi-client.gen.go b/servicemanager/internal/providermanagementapi/providermanagementapi-client.gen.go
new file mode 100644 (file)
index 0000000..97e369b
--- /dev/null
@@ -0,0 +1,630 @@
+// Package providermanagementapi provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/deepmap/oapi-codegen version v1.10.1 DO NOT EDIT.
+package providermanagementapi
+
+import (
+       "bytes"
+       "context"
+       "encoding/json"
+       "fmt"
+       "io"
+       "io/ioutil"
+       "net/http"
+       "net/url"
+       "strings"
+
+       "github.com/deepmap/oapi-codegen/pkg/runtime"
+)
+
+// RequestEditorFn  is the function signature for the RequestEditor callback function
+type RequestEditorFn func(ctx context.Context, req *http.Request) error
+
+// Doer performs HTTP requests.
+//
+// The standard http.Client implements this interface.
+type HttpRequestDoer interface {
+       Do(req *http.Request) (*http.Response, error)
+}
+
+// Client which conforms to the OpenAPI3 specification for this service.
+type Client struct {
+       // The endpoint of the server conforming to this interface, with scheme,
+       // https://api.deepmap.com for example. This can contain a path relative
+       // to the server, such as https://api.deepmap.com/dev-test, and all the
+       // paths in the swagger spec will be appended to the server.
+       Server string
+
+       // Doer for performing requests, typically a *http.Client with any
+       // customized settings, such as certificate chains.
+       Client HttpRequestDoer
+
+       // A list of callbacks for modifying requests which are generated before sending over
+       // the network.
+       RequestEditors []RequestEditorFn
+}
+
+// ClientOption allows setting custom parameters during construction
+type ClientOption func(*Client) error
+
+// Creates a new Client, with reasonable defaults
+func NewClient(server string, opts ...ClientOption) (*Client, error) {
+       // create a client with sane default values
+       client := Client{
+               Server: server,
+       }
+       // mutate client and add all optional params
+       for _, o := range opts {
+               if err := o(&client); err != nil {
+                       return nil, err
+               }
+       }
+       // ensure the server URL always has a trailing slash
+       if !strings.HasSuffix(client.Server, "/") {
+               client.Server += "/"
+       }
+       // create httpClient, if not already present
+       if client.Client == nil {
+               client.Client = &http.Client{}
+       }
+       return &client, nil
+}
+
+// WithHTTPClient allows overriding the default Doer, which is
+// automatically created using http.Client. This is useful for tests.
+func WithHTTPClient(doer HttpRequestDoer) ClientOption {
+       return func(c *Client) error {
+               c.Client = doer
+               return nil
+       }
+}
+
+// WithRequestEditorFn allows setting up a callback function, which will be
+// called right before sending the request. This can be used to mutate the request.
+func WithRequestEditorFn(fn RequestEditorFn) ClientOption {
+       return func(c *Client) error {
+               c.RequestEditors = append(c.RequestEditors, fn)
+               return nil
+       }
+}
+
+// The interface specification for the client above.
+type ClientInterface interface {
+       // PostRegistrations request with any body
+       PostRegistrationsWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+       PostRegistrations(ctx context.Context, body PostRegistrationsJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+       // DeleteRegistrationsRegistrationId request
+       DeleteRegistrationsRegistrationId(ctx context.Context, registrationId string, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+       // ModifyIndApiProviderEnrolment request with any body
+       ModifyIndApiProviderEnrolmentWithBody(ctx context.Context, registrationId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+       // PutRegistrationsRegistrationId request with any body
+       PutRegistrationsRegistrationIdWithBody(ctx context.Context, registrationId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+       PutRegistrationsRegistrationId(ctx context.Context, registrationId string, body PutRegistrationsRegistrationIdJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error)
+}
+
+func (c *Client) PostRegistrationsWithBody(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) {
+       req, err := NewPostRegistrationsRequestWithBody(c.Server, contentType, body)
+       if err != nil {
+               return nil, err
+       }
+       req = req.WithContext(ctx)
+       if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+               return nil, err
+       }
+       return c.Client.Do(req)
+}
+
+func (c *Client) PostRegistrations(ctx context.Context, body PostRegistrationsJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) {
+       req, err := NewPostRegistrationsRequest(c.Server, body)
+       if err != nil {
+               return nil, err
+       }
+       req = req.WithContext(ctx)
+       if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+               return nil, err
+       }
+       return c.Client.Do(req)
+}
+
+func (c *Client) DeleteRegistrationsRegistrationId(ctx context.Context, registrationId string, reqEditors ...RequestEditorFn) (*http.Response, error) {
+       req, err := NewDeleteRegistrationsRegistrationIdRequest(c.Server, registrationId)
+       if err != nil {
+               return nil, err
+       }
+       req = req.WithContext(ctx)
+       if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+               return nil, err
+       }
+       return c.Client.Do(req)
+}
+
+func (c *Client) ModifyIndApiProviderEnrolmentWithBody(ctx context.Context, registrationId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) {
+       req, err := NewModifyIndApiProviderEnrolmentRequestWithBody(c.Server, registrationId, contentType, body)
+       if err != nil {
+               return nil, err
+       }
+       req = req.WithContext(ctx)
+       if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+               return nil, err
+       }
+       return c.Client.Do(req)
+}
+
+func (c *Client) PutRegistrationsRegistrationIdWithBody(ctx context.Context, registrationId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) {
+       req, err := NewPutRegistrationsRegistrationIdRequestWithBody(c.Server, registrationId, contentType, body)
+       if err != nil {
+               return nil, err
+       }
+       req = req.WithContext(ctx)
+       if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+               return nil, err
+       }
+       return c.Client.Do(req)
+}
+
+func (c *Client) PutRegistrationsRegistrationId(ctx context.Context, registrationId string, body PutRegistrationsRegistrationIdJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) {
+       req, err := NewPutRegistrationsRegistrationIdRequest(c.Server, registrationId, body)
+       if err != nil {
+               return nil, err
+       }
+       req = req.WithContext(ctx)
+       if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+               return nil, err
+       }
+       return c.Client.Do(req)
+}
+
+// NewPostRegistrationsRequest calls the generic PostRegistrations builder with application/json body
+func NewPostRegistrationsRequest(server string, body PostRegistrationsJSONRequestBody) (*http.Request, error) {
+       var bodyReader io.Reader
+       buf, err := json.Marshal(body)
+       if err != nil {
+               return nil, err
+       }
+       bodyReader = bytes.NewReader(buf)
+       return NewPostRegistrationsRequestWithBody(server, "application/json", bodyReader)
+}
+
+// NewPostRegistrationsRequestWithBody generates requests for PostRegistrations with any type of body
+func NewPostRegistrationsRequestWithBody(server string, contentType string, body io.Reader) (*http.Request, error) {
+       var err error
+
+       serverURL, err := url.Parse(server)
+       if err != nil {
+               return nil, err
+       }
+
+       operationPath := fmt.Sprintf("/registrations")
+       if operationPath[0] == '/' {
+               operationPath = "." + operationPath
+       }
+
+       queryURL, err := serverURL.Parse(operationPath)
+       if err != nil {
+               return nil, err
+       }
+
+       req, err := http.NewRequest("POST", queryURL.String(), body)
+       if err != nil {
+               return nil, err
+       }
+
+       req.Header.Add("Content-Type", contentType)
+
+       return req, nil
+}
+
+// NewDeleteRegistrationsRegistrationIdRequest generates requests for DeleteRegistrationsRegistrationId
+func NewDeleteRegistrationsRegistrationIdRequest(server string, registrationId string) (*http.Request, error) {
+       var err error
+
+       var pathParam0 string
+
+       pathParam0, err = runtime.StyleParamWithLocation("simple", false, "registrationId", runtime.ParamLocationPath, registrationId)
+       if err != nil {
+               return nil, err
+       }
+
+       serverURL, err := url.Parse(server)
+       if err != nil {
+               return nil, err
+       }
+
+       operationPath := fmt.Sprintf("/registrations/%s", pathParam0)
+       if operationPath[0] == '/' {
+               operationPath = "." + operationPath
+       }
+
+       queryURL, err := serverURL.Parse(operationPath)
+       if err != nil {
+               return nil, err
+       }
+
+       req, err := http.NewRequest("DELETE", queryURL.String(), nil)
+       if err != nil {
+               return nil, err
+       }
+
+       return req, nil
+}
+
+// NewModifyIndApiProviderEnrolmentRequestWithBody generates requests for ModifyIndApiProviderEnrolment with any type of body
+func NewModifyIndApiProviderEnrolmentRequestWithBody(server string, registrationId string, contentType string, body io.Reader) (*http.Request, error) {
+       var err error
+
+       var pathParam0 string
+
+       pathParam0, err = runtime.StyleParamWithLocation("simple", false, "registrationId", runtime.ParamLocationPath, registrationId)
+       if err != nil {
+               return nil, err
+       }
+
+       serverURL, err := url.Parse(server)
+       if err != nil {
+               return nil, err
+       }
+
+       operationPath := fmt.Sprintf("/registrations/%s", pathParam0)
+       if operationPath[0] == '/' {
+               operationPath = "." + operationPath
+       }
+
+       queryURL, err := serverURL.Parse(operationPath)
+       if err != nil {
+               return nil, err
+       }
+
+       req, err := http.NewRequest("PATCH", queryURL.String(), body)
+       if err != nil {
+               return nil, err
+       }
+
+       req.Header.Add("Content-Type", contentType)
+
+       return req, nil
+}
+
+// NewPutRegistrationsRegistrationIdRequest calls the generic PutRegistrationsRegistrationId builder with application/json body
+func NewPutRegistrationsRegistrationIdRequest(server string, registrationId string, body PutRegistrationsRegistrationIdJSONRequestBody) (*http.Request, error) {
+       var bodyReader io.Reader
+       buf, err := json.Marshal(body)
+       if err != nil {
+               return nil, err
+       }
+       bodyReader = bytes.NewReader(buf)
+       return NewPutRegistrationsRegistrationIdRequestWithBody(server, registrationId, "application/json", bodyReader)
+}
+
+// NewPutRegistrationsRegistrationIdRequestWithBody generates requests for PutRegistrationsRegistrationId with any type of body
+func NewPutRegistrationsRegistrationIdRequestWithBody(server string, registrationId string, contentType string, body io.Reader) (*http.Request, error) {
+       var err error
+
+       var pathParam0 string
+
+       pathParam0, err = runtime.StyleParamWithLocation("simple", false, "registrationId", runtime.ParamLocationPath, registrationId)
+       if err != nil {
+               return nil, err
+       }
+
+       serverURL, err := url.Parse(server)
+       if err != nil {
+               return nil, err
+       }
+
+       operationPath := fmt.Sprintf("/registrations/%s", pathParam0)
+       if operationPath[0] == '/' {
+               operationPath = "." + operationPath
+       }
+
+       queryURL, err := serverURL.Parse(operationPath)
+       if err != nil {
+               return nil, err
+       }
+
+       req, err := http.NewRequest("PUT", queryURL.String(), body)
+       if err != nil {
+               return nil, err
+       }
+
+       req.Header.Add("Content-Type", contentType)
+
+       return req, nil
+}
+
+func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error {
+       for _, r := range c.RequestEditors {
+               if err := r(ctx, req); err != nil {
+                       return err
+               }
+       }
+       for _, r := range additionalEditors {
+               if err := r(ctx, req); err != nil {
+                       return err
+               }
+       }
+       return nil
+}
+
+// ClientWithResponses builds on ClientInterface to offer response payloads
+type ClientWithResponses struct {
+       ClientInterface
+}
+
+// NewClientWithResponses creates a new ClientWithResponses, which wraps
+// Client with return type handling
+func NewClientWithResponses(server string, opts ...ClientOption) (*ClientWithResponses, error) {
+       client, err := NewClient(server, opts...)
+       if err != nil {
+               return nil, err
+       }
+       return &ClientWithResponses{client}, nil
+}
+
+// WithBaseURL overrides the baseURL.
+func WithBaseURL(baseURL string) ClientOption {
+       return func(c *Client) error {
+               newBaseURL, err := url.Parse(baseURL)
+               if err != nil {
+                       return err
+               }
+               c.Server = newBaseURL.String()
+               return nil
+       }
+}
+
+// ClientWithResponsesInterface is the interface specification for the client with responses above.
+type ClientWithResponsesInterface interface {
+       // PostRegistrations request with any body
+       PostRegistrationsWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostRegistrationsResponse, error)
+
+       PostRegistrationsWithResponse(ctx context.Context, body PostRegistrationsJSONRequestBody, reqEditors ...RequestEditorFn) (*PostRegistrationsResponse, error)
+
+       // DeleteRegistrationsRegistrationId request
+       DeleteRegistrationsRegistrationIdWithResponse(ctx context.Context, registrationId string, reqEditors ...RequestEditorFn) (*DeleteRegistrationsRegistrationIdResponse, error)
+
+       // ModifyIndApiProviderEnrolment request with any body
+       ModifyIndApiProviderEnrolmentWithBodyWithResponse(ctx context.Context, registrationId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*ModifyIndApiProviderEnrolmentResponse, error)
+
+       // PutRegistrationsRegistrationId request with any body
+       PutRegistrationsRegistrationIdWithBodyWithResponse(ctx context.Context, registrationId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PutRegistrationsRegistrationIdResponse, error)
+
+       PutRegistrationsRegistrationIdWithResponse(ctx context.Context, registrationId string, body PutRegistrationsRegistrationIdJSONRequestBody, reqEditors ...RequestEditorFn) (*PutRegistrationsRegistrationIdResponse, error)
+}
+
+type PostRegistrationsResponse struct {
+       Body         []byte
+       HTTPResponse *http.Response
+       JSON201      *APIProviderEnrolmentDetails
+}
+
+// Status returns HTTPResponse.Status
+func (r PostRegistrationsResponse) Status() string {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.Status
+       }
+       return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r PostRegistrationsResponse) StatusCode() int {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.StatusCode
+       }
+       return 0
+}
+
+type DeleteRegistrationsRegistrationIdResponse struct {
+       Body         []byte
+       HTTPResponse *http.Response
+}
+
+// Status returns HTTPResponse.Status
+func (r DeleteRegistrationsRegistrationIdResponse) Status() string {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.Status
+       }
+       return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r DeleteRegistrationsRegistrationIdResponse) StatusCode() int {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.StatusCode
+       }
+       return 0
+}
+
+type ModifyIndApiProviderEnrolmentResponse struct {
+       Body         []byte
+       HTTPResponse *http.Response
+       JSON200      *APIProviderEnrolmentDetails
+}
+
+// Status returns HTTPResponse.Status
+func (r ModifyIndApiProviderEnrolmentResponse) Status() string {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.Status
+       }
+       return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r ModifyIndApiProviderEnrolmentResponse) StatusCode() int {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.StatusCode
+       }
+       return 0
+}
+
+type PutRegistrationsRegistrationIdResponse struct {
+       Body         []byte
+       HTTPResponse *http.Response
+       JSON200      *APIProviderEnrolmentDetails
+}
+
+// Status returns HTTPResponse.Status
+func (r PutRegistrationsRegistrationIdResponse) Status() string {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.Status
+       }
+       return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r PutRegistrationsRegistrationIdResponse) StatusCode() int {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.StatusCode
+       }
+       return 0
+}
+
+// PostRegistrationsWithBodyWithResponse request with arbitrary body returning *PostRegistrationsResponse
+func (c *ClientWithResponses) PostRegistrationsWithBodyWithResponse(ctx context.Context, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostRegistrationsResponse, error) {
+       rsp, err := c.PostRegistrationsWithBody(ctx, contentType, body, reqEditors...)
+       if err != nil {
+               return nil, err
+       }
+       return ParsePostRegistrationsResponse(rsp)
+}
+
+func (c *ClientWithResponses) PostRegistrationsWithResponse(ctx context.Context, body PostRegistrationsJSONRequestBody, reqEditors ...RequestEditorFn) (*PostRegistrationsResponse, error) {
+       rsp, err := c.PostRegistrations(ctx, body, reqEditors...)
+       if err != nil {
+               return nil, err
+       }
+       return ParsePostRegistrationsResponse(rsp)
+}
+
+// DeleteRegistrationsRegistrationIdWithResponse request returning *DeleteRegistrationsRegistrationIdResponse
+func (c *ClientWithResponses) DeleteRegistrationsRegistrationIdWithResponse(ctx context.Context, registrationId string, reqEditors ...RequestEditorFn) (*DeleteRegistrationsRegistrationIdResponse, error) {
+       rsp, err := c.DeleteRegistrationsRegistrationId(ctx, registrationId, reqEditors...)
+       if err != nil {
+               return nil, err
+       }
+       return ParseDeleteRegistrationsRegistrationIdResponse(rsp)
+}
+
+// ModifyIndApiProviderEnrolmentWithBodyWithResponse request with arbitrary body returning *ModifyIndApiProviderEnrolmentResponse
+func (c *ClientWithResponses) ModifyIndApiProviderEnrolmentWithBodyWithResponse(ctx context.Context, registrationId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*ModifyIndApiProviderEnrolmentResponse, error) {
+       rsp, err := c.ModifyIndApiProviderEnrolmentWithBody(ctx, registrationId, contentType, body, reqEditors...)
+       if err != nil {
+               return nil, err
+       }
+       return ParseModifyIndApiProviderEnrolmentResponse(rsp)
+}
+
+// PutRegistrationsRegistrationIdWithBodyWithResponse request with arbitrary body returning *PutRegistrationsRegistrationIdResponse
+func (c *ClientWithResponses) PutRegistrationsRegistrationIdWithBodyWithResponse(ctx context.Context, registrationId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PutRegistrationsRegistrationIdResponse, error) {
+       rsp, err := c.PutRegistrationsRegistrationIdWithBody(ctx, registrationId, contentType, body, reqEditors...)
+       if err != nil {
+               return nil, err
+       }
+       return ParsePutRegistrationsRegistrationIdResponse(rsp)
+}
+
+func (c *ClientWithResponses) PutRegistrationsRegistrationIdWithResponse(ctx context.Context, registrationId string, body PutRegistrationsRegistrationIdJSONRequestBody, reqEditors ...RequestEditorFn) (*PutRegistrationsRegistrationIdResponse, error) {
+       rsp, err := c.PutRegistrationsRegistrationId(ctx, registrationId, body, reqEditors...)
+       if err != nil {
+               return nil, err
+       }
+       return ParsePutRegistrationsRegistrationIdResponse(rsp)
+}
+
+// ParsePostRegistrationsResponse parses an HTTP response from a PostRegistrationsWithResponse call
+func ParsePostRegistrationsResponse(rsp *http.Response) (*PostRegistrationsResponse, error) {
+       bodyBytes, err := ioutil.ReadAll(rsp.Body)
+       defer func() { _ = rsp.Body.Close() }()
+       if err != nil {
+               return nil, err
+       }
+
+       response := &PostRegistrationsResponse{
+               Body:         bodyBytes,
+               HTTPResponse: rsp,
+       }
+
+       switch {
+       case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 201:
+               var dest APIProviderEnrolmentDetails
+               if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+                       return nil, err
+               }
+               response.JSON201 = &dest
+
+       }
+
+       return response, nil
+}
+
+// ParseDeleteRegistrationsRegistrationIdResponse parses an HTTP response from a DeleteRegistrationsRegistrationIdWithResponse call
+func ParseDeleteRegistrationsRegistrationIdResponse(rsp *http.Response) (*DeleteRegistrationsRegistrationIdResponse, error) {
+       bodyBytes, err := ioutil.ReadAll(rsp.Body)
+       defer func() { _ = rsp.Body.Close() }()
+       if err != nil {
+               return nil, err
+       }
+
+       response := &DeleteRegistrationsRegistrationIdResponse{
+               Body:         bodyBytes,
+               HTTPResponse: rsp,
+       }
+
+       return response, nil
+}
+
+// ParseModifyIndApiProviderEnrolmentResponse parses an HTTP response from a ModifyIndApiProviderEnrolmentWithResponse call
+func ParseModifyIndApiProviderEnrolmentResponse(rsp *http.Response) (*ModifyIndApiProviderEnrolmentResponse, error) {
+       bodyBytes, err := ioutil.ReadAll(rsp.Body)
+       defer func() { _ = rsp.Body.Close() }()
+       if err != nil {
+               return nil, err
+       }
+
+       response := &ModifyIndApiProviderEnrolmentResponse{
+               Body:         bodyBytes,
+               HTTPResponse: rsp,
+       }
+
+       switch {
+       case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
+               var dest APIProviderEnrolmentDetails
+               if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+                       return nil, err
+               }
+               response.JSON200 = &dest
+
+       }
+
+       return response, nil
+}
+
+// ParsePutRegistrationsRegistrationIdResponse parses an HTTP response from a PutRegistrationsRegistrationIdWithResponse call
+func ParsePutRegistrationsRegistrationIdResponse(rsp *http.Response) (*PutRegistrationsRegistrationIdResponse, error) {
+       bodyBytes, err := ioutil.ReadAll(rsp.Body)
+       defer func() { _ = rsp.Body.Close() }()
+       if err != nil {
+               return nil, err
+       }
+
+       response := &PutRegistrationsRegistrationIdResponse{
+               Body:         bodyBytes,
+               HTTPResponse: rsp,
+       }
+
+       switch {
+       case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
+               var dest APIProviderEnrolmentDetails
+               if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+                       return nil, err
+               }
+               response.JSON200 = &dest
+
+       }
+
+       return response, nil
+}
diff --git a/servicemanager/internal/providermanagementapi/providermanagementapi-server.gen.go b/servicemanager/internal/providermanagementapi/providermanagementapi-server.gen.go
new file mode 100644 (file)
index 0000000..c1f55aa
--- /dev/null
@@ -0,0 +1,258 @@
+// Package providermanagementapi provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/deepmap/oapi-codegen version v1.10.1 DO NOT EDIT.
+package providermanagementapi
+
+import (
+       "bytes"
+       "compress/gzip"
+       "encoding/base64"
+       "fmt"
+       "net/http"
+       "net/url"
+       "path"
+       "strings"
+
+       "github.com/deepmap/oapi-codegen/pkg/runtime"
+       "github.com/getkin/kin-openapi/openapi3"
+       "github.com/labstack/echo/v4"
+       externalRef0 "oransc.org/nonrtric/servicemanager/internal/common29122"
+       externalRef1 "oransc.org/nonrtric/servicemanager/internal/common29571"
+)
+
+// ServerInterface represents all server handlers.
+type ServerInterface interface {
+
+       // (POST /registrations)
+       PostRegistrations(ctx echo.Context) error
+
+       // (DELETE /registrations/{registrationId})
+       DeleteRegistrationsRegistrationId(ctx echo.Context, registrationId string) error
+
+       // (PATCH /registrations/{registrationId})
+       ModifyIndApiProviderEnrolment(ctx echo.Context, registrationId string) error
+
+       // (PUT /registrations/{registrationId})
+       PutRegistrationsRegistrationId(ctx echo.Context, registrationId string) error
+}
+
+// ServerInterfaceWrapper converts echo contexts to parameters.
+type ServerInterfaceWrapper struct {
+       Handler ServerInterface
+}
+
+// PostRegistrations converts echo context to params.
+func (w *ServerInterfaceWrapper) PostRegistrations(ctx echo.Context) error {
+       var err error
+
+       // Invoke the callback with all the unmarshalled arguments
+       err = w.Handler.PostRegistrations(ctx)
+       return err
+}
+
+// DeleteRegistrationsRegistrationId converts echo context to params.
+func (w *ServerInterfaceWrapper) DeleteRegistrationsRegistrationId(ctx echo.Context) error {
+       var err error
+       // ------------- Path parameter "registrationId" -------------
+       var registrationId string
+
+       err = runtime.BindStyledParameterWithLocation("simple", false, "registrationId", runtime.ParamLocationPath, ctx.Param("registrationId"), &registrationId)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter registrationId: %s", err))
+       }
+
+       // Invoke the callback with all the unmarshalled arguments
+       err = w.Handler.DeleteRegistrationsRegistrationId(ctx, registrationId)
+       return err
+}
+
+// ModifyIndApiProviderEnrolment converts echo context to params.
+func (w *ServerInterfaceWrapper) ModifyIndApiProviderEnrolment(ctx echo.Context) error {
+       var err error
+       // ------------- Path parameter "registrationId" -------------
+       var registrationId string
+
+       err = runtime.BindStyledParameterWithLocation("simple", false, "registrationId", runtime.ParamLocationPath, ctx.Param("registrationId"), &registrationId)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter registrationId: %s", err))
+       }
+
+       // Invoke the callback with all the unmarshalled arguments
+       err = w.Handler.ModifyIndApiProviderEnrolment(ctx, registrationId)
+       return err
+}
+
+// PutRegistrationsRegistrationId converts echo context to params.
+func (w *ServerInterfaceWrapper) PutRegistrationsRegistrationId(ctx echo.Context) error {
+       var err error
+       // ------------- Path parameter "registrationId" -------------
+       var registrationId string
+
+       err = runtime.BindStyledParameterWithLocation("simple", false, "registrationId", runtime.ParamLocationPath, ctx.Param("registrationId"), &registrationId)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter registrationId: %s", err))
+       }
+
+       // Invoke the callback with all the unmarshalled arguments
+       err = w.Handler.PutRegistrationsRegistrationId(ctx, registrationId)
+       return err
+}
+
+// This is a simple interface which specifies echo.Route addition functions which
+// are present on both echo.Echo and echo.Group, since we want to allow using
+// either of them for path registration
+type EchoRouter interface {
+       CONNECT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       DELETE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       GET(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       HEAD(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       OPTIONS(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       PATCH(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       POST(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       PUT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       TRACE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+}
+
+// RegisterHandlers adds each server route to the EchoRouter.
+func RegisterHandlers(router EchoRouter, si ServerInterface) {
+       RegisterHandlersWithBaseURL(router, si, "")
+}
+
+// Registers handlers, and prepends BaseURL to the paths, so that the paths
+// can be served under a prefix.
+func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL string) {
+
+       wrapper := ServerInterfaceWrapper{
+               Handler: si,
+       }
+
+       router.POST(baseURL+"/registrations", wrapper.PostRegistrations)
+       router.DELETE(baseURL+"/registrations/:registrationId", wrapper.DeleteRegistrationsRegistrationId)
+       router.PATCH(baseURL+"/registrations/:registrationId", wrapper.ModifyIndApiProviderEnrolment)
+       router.PUT(baseURL+"/registrations/:registrationId", wrapper.PutRegistrationsRegistrationId)
+
+}
+
+// Base64 encoded, gzipped, json marshaled Swagger object
+var swaggerSpec = []string{
+
+       "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",
+}
+
+// GetSwagger returns the content of the embedded swagger specification file
+// or error if failed to decode
+func decodeSpec() ([]byte, error) {
+       zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, ""))
+       if err != nil {
+               return nil, fmt.Errorf("error base64 decoding spec: %s", err)
+       }
+       zr, err := gzip.NewReader(bytes.NewReader(zipped))
+       if err != nil {
+               return nil, fmt.Errorf("error decompressing spec: %s", err)
+       }
+       var buf bytes.Buffer
+       _, err = buf.ReadFrom(zr)
+       if err != nil {
+               return nil, fmt.Errorf("error decompressing spec: %s", err)
+       }
+
+       return buf.Bytes(), nil
+}
+
+var rawSpec = decodeSpecCached()
+
+// a naive cached of a decoded swagger spec
+func decodeSpecCached() func() ([]byte, error) {
+       data, err := decodeSpec()
+       return func() ([]byte, error) {
+               return data, err
+       }
+}
+
+// Constructs a synthetic filesystem for resolving external references when loading openapi specifications.
+func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) {
+       var res = make(map[string]func() ([]byte, error))
+       if len(pathToFile) > 0 {
+               res[pathToFile] = rawSpec
+       }
+
+       pathPrefix := path.Dir(pathToFile)
+
+       for rawPath, rawFunc := range externalRef0.PathToRawSpec(path.Join(pathPrefix, "TS29122_CommonData.yaml")) {
+               if _, ok := res[rawPath]; ok {
+                       // it is not possible to compare functions in golang, so always overwrite the old value
+               }
+               res[rawPath] = rawFunc
+       }
+       for rawPath, rawFunc := range externalRef1.PathToRawSpec(path.Join(pathPrefix, "TS29571_CommonData.yaml")) {
+               if _, ok := res[rawPath]; ok {
+                       // it is not possible to compare functions in golang, so always overwrite the old value
+               }
+               res[rawPath] = rawFunc
+       }
+       return res
+}
+
+// GetSwagger returns the Swagger specification corresponding to the generated code
+// in this file. The external references of Swagger specification are resolved.
+// The logic of resolving external references is tightly connected to "import-mapping" feature.
+// Externally referenced files must be embedded in the corresponding golang packages.
+// Urls can be supported but this task was out of the scope.
+func GetSwagger() (swagger *openapi3.T, err error) {
+       var resolvePath = PathToRawSpec("")
+
+       loader := openapi3.NewLoader()
+       loader.IsExternalRefsAllowed = true
+       loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) {
+               var pathToFile = url.String()
+               pathToFile = path.Clean(pathToFile)
+               getSpec, ok := resolvePath[pathToFile]
+               if !ok {
+                       err1 := fmt.Errorf("path not found: %s", pathToFile)
+                       return nil, err1
+               }
+               return getSpec()
+       }
+       var specData []byte
+       specData, err = rawSpec()
+       if err != nil {
+               return
+       }
+       swagger, err = loader.LoadFromData(specData)
+       if err != nil {
+               return
+       }
+       return
+}
diff --git a/servicemanager/internal/providermanagementapi/providermanagementapi-types.gen.go b/servicemanager/internal/providermanagementapi/providermanagementapi-types.gen.go
new file mode 100644 (file)
index 0000000..976d3e7
--- /dev/null
@@ -0,0 +1,92 @@
+// Package providermanagementapi provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/deepmap/oapi-codegen version v1.10.1 DO NOT EDIT.
+package providermanagementapi
+
+import (
+       externalRef1 "oransc.org/nonrtric/servicemanager/internal/common29571"
+)
+
+// Defines values for ApiProviderFuncRole.
+const (
+       ApiProviderFuncRoleAEF ApiProviderFuncRole = "AEF"
+
+       ApiProviderFuncRoleAMF ApiProviderFuncRole = "AMF"
+
+       ApiProviderFuncRoleAPF ApiProviderFuncRole = "APF"
+)
+
+// Represents an API provider domain's enrolment details.
+type APIProviderEnrolmentDetails struct {
+       // API provider domain ID assigned by the CAPIF core function to the API management function while registering the API provider domain. Shall not be present in the HTTP POST request from the API Management function to the CAPIF core function, to on-board itself. Shall be present in all other HTTP requests and responses.
+       ApiProvDomId *string `json:"apiProvDomId,omitempty"`
+
+       // Generic information related to the API provider domain such as details of the API provider applications.
+       ApiProvDomInfo *string `json:"apiProvDomInfo,omitempty"`
+
+       // A list of individual API provider domain functions details. When included by the API management function in the HTTP request message, it lists the API provider domain functions that the API management function intends to register/update in registration or update registration procedure. When included by the CAPIF core function in the HTTP response message, it lists the API domain functions details that are registered or updated successfully.
+       ApiProvFuncs *[]APIProviderFunctionDetails `json:"apiProvFuncs,omitempty"`
+
+       // Registration or update specific failure information of failed API provider domain function registrations.Shall be present in the HTTP response body if atleast one of the API provider domain function registration or update registration fails.
+       FailReason *string `json:"failReason,omitempty"`
+
+       // Security information necessary for the CAPIF core function to validate the registration of the API provider domain. Shall be present in HTTP POST request from API management function to CAPIF core function for API provider domain registration.
+       RegSec string `json:"regSec"`
+
+       // A string used to indicate the features supported by an API that is used as defined in clause  6.6 in 3GPP TS 29.500. The string shall contain a bitmask indicating supported features in  hexadecimal representation Each character in the string shall take a value of "0" to "9",  "a" to "f" or "A" to "F" and shall represent the support of 4 features as described in  table 5.2.2-3. The most significant character representing the highest-numbered features shall  appear first in the string, and the character representing features 1 to 4 shall appear last  in the string. The list of features and their numbering (starting with 1) are defined  separately for each API. If the string contains a lower number of characters than there are  defined features for an API, all features that would be represented by characters that are not  present in the string are not supported.
+       SuppFeat *externalRef1.SupportedFeatures `json:"suppFeat,omitempty"`
+}
+
+// Represents an API provider domain's enrolment details.
+type APIProviderEnrolmentDetailsPatch struct {
+       // Generic information related to the API provider domain such as details of the API provider applications.
+       ApiProvDomInfo *string `json:"apiProvDomInfo,omitempty"`
+
+       // A list of individual API provider domain functions details. When included by the API management function in the HTTP request message, it lists the API provider domain functions that the API management function intends to register/update in registration or update registration procedure.
+       ApiProvFuncs *[]APIProviderFunctionDetails `json:"apiProvFuncs,omitempty"`
+}
+
+// Represents API provider domain function's details.
+type APIProviderFunctionDetails struct {
+       // API provider domain functionID assigned by the CAPIF core function to the API provider domain function while registering/updating the API provider domain. Shall not be present in the HTTP POST request from the API management function to the CAPIF core function, to register itself. Shall be present in all other HTTP requests and responses.
+       ApiProvFuncId *string `json:"apiProvFuncId,omitempty"`
+
+       // Generic information related to the API provider domain function such as details of the API provider applications.
+       ApiProvFuncInfo *string `json:"apiProvFuncInfo,omitempty"`
+
+       // Possible values are:
+       // - AEF: API provider function is API Exposing Function.
+       // - APF: API provider function is API Publishing Function.
+       // - AMF: API Provider function is API Management Function.
+       ApiProvFuncRole ApiProviderFuncRole `json:"apiProvFuncRole"`
+
+       // Represents registration information of an individual API provider domain function.
+       RegInfo RegistrationInformation `json:"regInfo"`
+}
+
+// Possible values are:
+// - AEF: API provider function is API Exposing Function.
+// - APF: API provider function is API Publishing Function.
+// - AMF: API Provider function is API Management Function.
+type ApiProviderFuncRole string
+
+// Represents registration information of an individual API provider domain function.
+type RegistrationInformation struct {
+       // API provider domain function's client certificate
+       ApiProvCert *string `json:"apiProvCert,omitempty"`
+
+       // Public Key of API Provider domain function.
+       ApiProvPubKey string `json:"apiProvPubKey"`
+}
+
+// PostRegistrationsJSONBody defines parameters for PostRegistrations.
+type PostRegistrationsJSONBody APIProviderEnrolmentDetails
+
+// PutRegistrationsRegistrationIdJSONBody defines parameters for PutRegistrationsRegistrationId.
+type PutRegistrationsRegistrationIdJSONBody APIProviderEnrolmentDetails
+
+// PostRegistrationsJSONRequestBody defines body for PostRegistrations for application/json ContentType.
+type PostRegistrationsJSONRequestBody PostRegistrationsJSONBody
+
+// PutRegistrationsRegistrationIdJSONRequestBody defines body for PutRegistrationsRegistrationId for application/json ContentType.
+type PutRegistrationsRegistrationIdJSONRequestBody PutRegistrationsRegistrationIdJSONBody
diff --git a/servicemanager/internal/publishservice/publishservice.go b/servicemanager/internal/publishservice/publishservice.go
new file mode 100644 (file)
index 0000000..e678860
--- /dev/null
@@ -0,0 +1,343 @@
+// -
+//   ========================LICENSE_START=================================
+//   O-RAN-SC
+//   %%
+//   Copyright (C) 2023-2024: OpenInfra Foundation Europe
+//   %%
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//        http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+//   ========================LICENSE_END===================================
+//
+
+package publishservice
+
+import (
+       "context"
+       "fmt"
+       "net/http"
+       "path"
+
+       echo "github.com/labstack/echo/v4"
+       log "github.com/sirupsen/logrus"
+
+       "oransc.org/nonrtric/servicemanager/internal/common29122"
+       publishapi "oransc.org/nonrtric/servicemanager/internal/publishserviceapi"
+)
+
+type PublishService struct {
+       KongDomain                              string;
+       KongProtocol                    string;
+       KongIPv4                        common29122.Ipv4Addr;
+       KongDataPlanePort               common29122.Port;
+       KongControlPlanePort    common29122.Port;
+       CapifProtocol                   string;
+       CapifIPv4                       common29122.Ipv4Addr;
+       CapifPort                               common29122.Port;
+}
+
+// Creates a service that implements both the PublishRegister and the publishserviceapi.ServerInterface interfaces.
+func NewPublishService(kongDomain string, kongProtocol string, kongIPv4 common29122.Ipv4Addr, kongDataPlanePort common29122.Port, kongControlPlanePort common29122.Port, capifProtocol string, capifIPv4 common29122.Ipv4Addr, capifPort common29122.Port) *PublishService {
+       return &PublishService{
+               KongDomain                              : kongDomain,
+               KongProtocol                    : kongProtocol,
+               KongIPv4                                : kongIPv4,
+               KongDataPlanePort               : kongDataPlanePort,
+               KongControlPlanePort    : kongControlPlanePort,
+               CapifProtocol                   : capifProtocol,
+               CapifIPv4                               : capifIPv4,
+               CapifPort                               : capifPort,
+       }
+}
+
+// Publish a new API.
+func (ps *PublishService) PostApfIdServiceApis(ctx echo.Context, apfId string) error {
+       log.Tracef("entering PostApfIdServiceApis apfId %s", apfId)
+
+       capifcoreUrl := fmt.Sprintf("%s://%s:%d/published-apis/v1/", ps.CapifProtocol, ps.CapifIPv4, ps.CapifPort)
+       client, err := publishapi.NewClientWithResponses(capifcoreUrl)
+       if err != nil {
+               return err
+       }
+
+       var (
+               ctxHandler context.Context
+               cancel     context.CancelFunc
+       )
+       ctxHandler, cancel = context.WithCancel(context.Background())
+       defer cancel()
+
+       newServiceAPIDescription, err := getServiceFromRequest(ctx)
+       if err != nil {
+               return err
+       }
+
+       newServiceAPIDescription.PrepareNewService()
+
+       statusCode, err := newServiceAPIDescription.RegisterKong(ps.KongDomain, ps.KongProtocol, ps.KongIPv4, ps.KongDataPlanePort, ps.KongControlPlanePort)
+       if (err != nil) || (statusCode != http.StatusCreated) {
+               // We can return with http.StatusForbidden if there is a http.StatusConflict detected by Kong
+               msg := err.Error()
+               log.Errorf("error on RegisterKong %s", msg)
+               return sendCoreError(ctx, statusCode, msg)
+       }
+
+       bodyServiceAPIDescription := publishapi.PostApfIdServiceApisJSONRequestBody(newServiceAPIDescription)
+       var rsp *publishapi.PostApfIdServiceApisResponse
+
+       log.Trace("calling PostApfIdServiceApisWithResponse")
+       rsp, err = client.PostApfIdServiceApisWithResponse(ctxHandler, apfId, bodyServiceAPIDescription)
+
+       if err != nil {
+               msg := err.Error()
+               log.Errorf("error on PostApfIdServiceApisWithResponse %s", msg)
+               return sendCoreError(ctx, http.StatusInternalServerError, msg)
+       }
+
+       if rsp.StatusCode() != http.StatusCreated {
+               msg := string(rsp.Body)
+               log.Debugf("PostApfIdServiceApisWithResponse status code %d", rsp.StatusCode())
+               log.Debugf("PostApfIdServiceApisWithResponse error %s", msg)
+               if rsp.StatusCode() == http.StatusForbidden || rsp.StatusCode() == http.StatusBadRequest {
+                       newServiceAPIDescription.UnregisterKong(ps.KongDomain, ps.KongProtocol, ps.KongIPv4, ps.KongDataPlanePort, ps.KongControlPlanePort)
+               }
+               return sendCoreError(ctx, rsp.StatusCode(), msg)
+       }
+
+       rspServiceAPIDescription := *rsp.JSON201
+       apiId := *rspServiceAPIDescription.ApiId
+
+       uri := ctx.Request().Host + ctx.Request().URL.String()
+       ctx.Response().Header().Set(echo.HeaderLocation, ctx.Scheme()+`://`+path.Join(uri, apiId))
+
+       err = ctx.JSON(http.StatusCreated, rspServiceAPIDescription)
+       if err != nil {
+               return err // Tell Echo that our handler failed
+       }
+
+       return nil
+}
+
+
+// Unpublish a published service API.
+func (ps *PublishService) DeleteApfIdServiceApisServiceApiId(ctx echo.Context, apfId string, serviceApiId string) error {
+       log.Tracef("entering DeleteApfIdServiceApisServiceApiId apfId %s serviceApiId %s", apfId, serviceApiId)
+
+       capifcoreUrl := fmt.Sprintf("%s://%s:%d/published-apis/v1/", ps.CapifProtocol, ps.CapifIPv4, ps.CapifPort)
+       client, err := publishapi.NewClientWithResponses(capifcoreUrl)
+       if err != nil {
+               return err
+       }
+
+       var (
+               ctxHandler context.Context
+               cancel     context.CancelFunc
+       )
+       ctxHandler, cancel = context.WithCancel(context.Background())
+       defer cancel()
+
+       log.Debugf("call GetApfIdServiceApisServiceApiIdWithResponse before delete apfId %s serviceApiId %s", apfId, serviceApiId)
+       var rsp *publishapi.GetApfIdServiceApisServiceApiIdResponse
+       rsp, err = client.GetApfIdServiceApisServiceApiIdWithResponse(ctxHandler, apfId, serviceApiId)
+
+       if err != nil {
+               msg := err.Error()
+               log.Errorf("error on GetApfIdServiceApisServiceApiIdWithResponse %s", msg)
+               return sendCoreError(ctx, http.StatusInternalServerError, msg)
+       }
+
+       statusCode := rsp.StatusCode()
+       if statusCode != http.StatusOK {
+               log.Debugf("GetApfIdServiceApisServiceApiIdWithResponse status %d", statusCode)
+               return ctx.NoContent(statusCode)
+       }
+
+       rspServiceAPIDescription := *rsp.JSON200
+       statusCode, err = rspServiceAPIDescription.UnregisterKong(ps.KongDomain, ps.KongProtocol, ps.KongIPv4, ps.KongDataPlanePort, ps.KongControlPlanePort)
+       if (err != nil) || (statusCode != http.StatusNoContent) {
+               msg := err.Error()
+               log.Errorf("error on UnregisterKong %s", msg)
+               return sendCoreError(ctx, statusCode, msg)
+       }
+
+       log.Trace("call DeleteApfIdServiceApisServiceApiIdWithResponse")
+       _, err = client.DeleteApfIdServiceApisServiceApiIdWithResponse(ctxHandler, apfId, serviceApiId)
+
+       if err != nil {
+               msg := err.Error()
+               log.Errorf("error on DeleteApfIdServiceApisServiceApiIdWithResponse %s", msg)
+               return sendCoreError(ctx, http.StatusInternalServerError, msg)
+       }
+
+       return ctx.NoContent(http.StatusNoContent)
+}
+
+// Retrieve all published APIs.
+func (ps *PublishService) GetApfIdServiceApis(ctx echo.Context, apfId string) error {
+       log.Tracef("entering GetApfIdServiceApis apfId %s", apfId)
+
+       capifcoreUrl := fmt.Sprintf("%s://%s:%d/published-apis/v1/", ps.CapifProtocol, ps.CapifIPv4, ps.CapifPort)
+       client, err := publishapi.NewClientWithResponses(capifcoreUrl)
+       if err != nil {
+               return err
+       }
+
+       var (
+               ctxHandler context.Context
+               cancel     context.CancelFunc
+       )
+       ctxHandler, cancel = context.WithCancel(context.Background())
+       defer cancel()
+
+       var rsp *publishapi.GetApfIdServiceApisResponse
+       rsp, err = client.GetApfIdServiceApisWithResponse(ctxHandler, apfId)
+
+       if err != nil {
+               msg := err.Error()
+               log.Errorf("error on GetApfIdServiceApisWithResponse %s", msg)
+               return sendCoreError(ctx, http.StatusInternalServerError, msg)
+       }
+
+       if rsp.StatusCode() != http.StatusOK {
+               msg := string(rsp.Body)
+               log.Errorf("GetApfIdServiceApisWithResponse status %d", rsp.StatusCode())
+               log.Errorf("GetApfIdServiceApisWithResponse error %s", msg)
+               return sendCoreError(ctx, rsp.StatusCode(), msg)
+       }
+
+       rspServiceAPIDescriptions := *rsp.JSON200
+       err = ctx.JSON(rsp.StatusCode(), rspServiceAPIDescriptions)
+       if err != nil {
+               return err // tell Echo that our handler failed
+       }
+       return nil
+}
+
+// Retrieve a published service API.
+func (ps *PublishService) GetApfIdServiceApisServiceApiId(ctx echo.Context, apfId string, serviceApiId string) error {
+       log.Tracef("entering GetApfIdServiceApisServiceApiId apfId %s", apfId)
+
+       capifcoreUrl := fmt.Sprintf("%s://%s:%d/published-apis/v1/", ps.CapifProtocol, ps.CapifIPv4, ps.CapifPort)
+       client, err := publishapi.NewClientWithResponses(capifcoreUrl)
+       if err != nil {
+               return err
+       }
+
+       var (
+               ctxHandler context.Context
+               cancel     context.CancelFunc
+       )
+       ctxHandler, cancel = context.WithCancel(context.Background())
+       defer cancel()
+
+       var rsp *publishapi.GetApfIdServiceApisServiceApiIdResponse
+       rsp, err = client.GetApfIdServiceApisServiceApiIdWithResponse(ctxHandler, apfId, serviceApiId)
+
+       if err != nil {
+               msg := err.Error()
+               log.Errorf("error on GetApfIdServiceApisServiceApiIdWithResponse %s", msg)
+               return sendCoreError(ctx, http.StatusInternalServerError, msg)
+       }
+
+       statusCode := rsp.StatusCode()
+       if statusCode != http.StatusOK {
+               return ctx.NoContent(statusCode)
+       }
+
+       rspServiceAPIDescription := *rsp.JSON200
+
+       err = ctx.JSON(http.StatusOK, rspServiceAPIDescription)
+       if err != nil {
+               return err // tell Echo that our handler failed
+       }
+       return nil
+}
+
+// Modify an existing published service API.
+func (ps *PublishService) ModifyIndAPFPubAPI(ctx echo.Context, apfId string, serviceApiId string) error {
+       return ctx.NoContent(http.StatusNotImplemented)
+}
+
+// Update a published service API.
+func (ps *PublishService) PutApfIdServiceApisServiceApiId(ctx echo.Context, apfId string, serviceApiId string) error {
+       log.Tracef("entering PutApfIdServiceApisServiceApiId apfId %s", apfId)
+
+       capifcoreUrl := fmt.Sprintf("%s://%s:%d/published-apis/v1/", ps.CapifProtocol, ps.CapifIPv4, ps.CapifPort)
+       client, err := publishapi.NewClientWithResponses(capifcoreUrl)
+       if err != nil {
+               return err
+       }
+
+       var (
+               ctxHandler context.Context
+               cancel     context.CancelFunc
+       )
+       ctxHandler, cancel = context.WithCancel(context.Background())
+       defer cancel()
+
+       updatedServiceDescription, err := getServiceFromRequest(ctx)
+       if err != nil {
+               return err
+       }
+
+       var rsp *publishapi.PutApfIdServiceApisServiceApiIdResponse
+       bodyServiceAPIDescription := publishapi.PutApfIdServiceApisServiceApiIdJSONRequestBody(updatedServiceDescription)
+
+       rsp, err = client.PutApfIdServiceApisServiceApiIdWithResponse(ctxHandler, apfId, serviceApiId, bodyServiceAPIDescription)
+
+       if err != nil {
+               msg := err.Error()
+               log.Errorf("error on PutApfIdServiceApisServiceApiIdWithResponse %s", msg)
+               return sendCoreError(ctx, http.StatusInternalServerError, msg)
+       }
+
+       if rsp.StatusCode() != http.StatusOK {
+               log.Errorf("PutApfIdServiceApisServiceApiIdWithResponse status code %d", rsp.StatusCode())
+               if rsp.StatusCode() == http.StatusBadRequest {
+                       updatedServiceDescription.UnregisterKong(ps.KongDomain, ps.KongProtocol, ps.KongIPv4, ps.KongDataPlanePort, ps.KongControlPlanePort)
+               }
+               msg := string(rsp.Body)
+               return sendCoreError(ctx, rsp.StatusCode(), msg)
+       }
+
+       rspServiceAPIDescription := *rsp.JSON200
+       apiId := *rspServiceAPIDescription.ApiId
+
+       uri := ctx.Request().Host + ctx.Request().URL.String()
+       ctx.Response().Header().Set(echo.HeaderLocation, ctx.Scheme()+`://`+path.Join(uri, apiId))
+
+       err = ctx.JSON(http.StatusOK, rspServiceAPIDescription)
+       if err != nil {
+               return err // Tell Echo that our handler failed
+       }
+       return nil
+}
+
+
+func getServiceFromRequest(ctx echo.Context) (publishapi.ServiceAPIDescription, error) {
+       var updatedServiceDescription publishapi.ServiceAPIDescription
+       err := ctx.Bind(&updatedServiceDescription)
+       if err != nil {
+               return publishapi.ServiceAPIDescription{}, fmt.Errorf("invalid format for service")
+       }
+       return updatedServiceDescription, nil
+}
+
+// This function wraps sending of an error in the Error format, and
+// handling the failure to marshal that.
+func sendCoreError(ctx echo.Context, code int, message string) error {
+       pd := common29122.ProblemDetails{
+               Cause:  &message,
+               Status: &code,
+       }
+       err := ctx.JSON(code, pd)
+       return err
+}
\ No newline at end of file
diff --git a/servicemanager/internal/publishservice/publishservice_test.go b/servicemanager/internal/publishservice/publishservice_test.go
new file mode 100644 (file)
index 0000000..bd5264d
--- /dev/null
@@ -0,0 +1,453 @@
+// -
+//   ========================LICENSE_START=================================
+//   O-RAN-SC
+//   %%
+//   Copyright (C) 2023-2024: OpenInfra Foundation Europe
+//   %%
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//        http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+//   ========================LICENSE_END===================================
+//
+
+package publishservice
+
+import (
+       "fmt"
+       "net/http"
+       "os"
+       "strings"
+       "testing"
+
+       "github.com/deepmap/oapi-codegen/pkg/middleware"
+       "github.com/deepmap/oapi-codegen/pkg/testutil"
+       echo "github.com/labstack/echo/v4"
+       echomiddleware "github.com/labstack/echo/v4/middleware"
+       log "github.com/sirupsen/logrus"
+       "github.com/stretchr/testify/assert"
+
+       "oransc.org/nonrtric/servicemanager/internal/common29122"
+       "oransc.org/nonrtric/servicemanager/internal/envreader"
+       "oransc.org/nonrtric/servicemanager/internal/kongclear"
+       "oransc.org/nonrtric/servicemanager/internal/providermanagement"
+       provapi "oransc.org/nonrtric/servicemanager/internal/providermanagementapi"
+       publishapi "oransc.org/nonrtric/servicemanager/internal/publishserviceapi"
+)
+
+var requestHandler *echo.Echo
+
+func TestMain(m *testing.M) {
+       err := setupTest()
+       if err != nil {
+               return
+       }
+
+       ret := m.Run()
+       if ret == 0 {
+               teardown()
+       }
+       os.Exit(ret)
+}
+
+func setupTest() error {
+       myEnv, myPorts, err := envreader.ReadDotEnv()
+       if err != nil {
+               log.Fatal("error loading environment file on setupTest")
+               return err
+       }
+
+       requestHandler, err = getEcho(myEnv, myPorts)
+       if err != nil {
+               log.Fatal("getEcho fatal error on setupTest")
+               return err
+       }
+       err = teardown()
+       if err != nil {
+               log.Fatal("getEcho fatal error on teardown")
+               return err
+       }
+
+       return err
+}
+
+func getProvider() provapi.APIProviderEnrolmentDetails {
+       var (
+               domainInfo  = "Kong"
+               funcInfoAPF = "rApp Kong as APF"
+               funcInfoAEF = "rApp Kong as AEF"
+       )
+
+       testFuncs := []provapi.APIProviderFunctionDetails{
+               {
+                       ApiProvFuncInfo: &funcInfoAPF,
+                       ApiProvFuncRole: provapi.ApiProviderFuncRoleAPF,
+                       RegInfo: provapi.RegistrationInformation{
+                               ApiProvPubKey: "APF-PublicKey",
+                       },
+               },
+               {
+                       ApiProvFuncInfo: &funcInfoAEF,
+                       ApiProvFuncRole: provapi.ApiProviderFuncRoleAEF,
+                       RegInfo: provapi.RegistrationInformation{
+                               ApiProvPubKey: "AEF-PublicKey",
+                       },
+               },
+       }
+       return provapi.APIProviderEnrolmentDetails{
+               RegSec:         "sec",
+               ApiProvDomInfo: &domainInfo,
+               ApiProvFuncs:   &testFuncs,
+       }
+}
+
+func teardown() error {
+       log.Trace("entering teardown")
+
+       t := new(testing.T) // Create a new testing.T instance for teardown
+
+       // Delete the invoker
+       invokerInfo := "invoker a"
+       invokerId := "api_invoker_id_" + strings.Replace(invokerInfo, " ", "_", 1)
+
+       result := testutil.NewRequest().Delete("/api-invoker-management/v1/onboardedInvokers/"+invokerId).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNoContent, result.Code())
+
+       // Delete the original published service
+       apfId := "APF_id_rApp_Kong_as_APF"
+       apiName := "apiName"
+       apiId := "api_id_" + apiName
+
+       result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNoContent, result.Code())
+
+       // Delete the first published service
+       apfId = "APF_id_rApp_Kong_as_APF"
+       apiName = "apiName1"
+       apiId = "api_id_" + apiName
+
+       result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNoContent, result.Code())
+
+       // Delete the second published service
+       apiName = "apiName2"
+       apiId = "api_id_" + apiName
+
+       result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+apiId).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNoContent, result.Code())
+
+       // Delete the provider
+       domainID := "domain_id_Kong"
+       result = testutil.NewRequest().Delete("/api-provider-management/v1/registrations/"+domainID).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNoContent, result.Code())
+
+       myEnv, myPorts, err := envreader.ReadDotEnv()
+       if err != nil {
+               log.Fatal("error loading environment file")
+               return err
+       }
+
+       err = kongclear.KongClear(myEnv, myPorts)
+       if err != nil {
+               log.Fatal("error clearing Kong on teardown")
+       }
+       return err
+}
+
+func TestPostUnpublishedServiceWithUnregisteredPublisher(t *testing.T) {
+       teardown()
+
+       apfId := "APF_id_rApp_Kong_as_APF"
+       apiName := "apiName"
+
+       // Check no services published
+       result := testutil.NewRequest().Get("/published-apis/v1/"+apfId+"/service-apis").Go(t, requestHandler)
+       assert.Equal(t, http.StatusNotFound, result.Code())
+
+       var resultError common29122.ProblemDetails
+       err := result.UnmarshalBodyToObject(&resultError)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       assert.Contains(t, *resultError.Cause, apfId)
+       assert.Contains(t, *resultError.Cause, "api is only available for publishers")
+
+       aefId := "AEF_id_rApp_Kong_as_AEF"
+       namespace := "namespace"
+       repoName := "repoName"
+       chartName := "chartName"
+       releaseName := "releaseName"
+       description := fmt.Sprintf("Description,%s,%s,%s,%s", namespace, repoName, chartName, releaseName)
+
+       myEnv, myPorts, err := envreader.ReadDotEnv()
+       assert.Nil(t, err, "error reading env file")
+
+       testServiceIpv4 := common29122.Ipv4Addr(myEnv["TEST_SERVICE_IPV4"])
+       testServicePort := common29122.Port(myPorts["TEST_SERVICE_PORT"])
+
+       assert.NotEmpty(t, testServiceIpv4, "TEST_SERVICE_IPV4 is required in .env file for unit testing")
+       assert.NotZero(t, testServicePort, "TEST_SERVICE_PORT is required in .env file for unit testing")
+
+       newServiceDescription := getServiceAPIDescription(aefId, apiName, description, testServiceIpv4, testServicePort)
+
+       // Attempt to publish a service for provider
+       result = testutil.NewRequest().Post("/published-apis/v1/"+apfId+"/service-apis").WithJsonBody(newServiceDescription).Go(t, requestHandler)
+       assert.Equal(t, http.StatusForbidden, result.Code())
+
+       // var resultError common29122.ProblemDetails
+       err = result.UnmarshalBodyToObject(&resultError)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       assert.Contains(t, *resultError.Cause, apfId)
+       assert.Contains(t, *resultError.Cause, "Unable to publish the service due to api is only available for publishers")
+}
+
+func TestRegisterValidProvider(t *testing.T) {
+       newProvider := getProvider()
+
+       // Register a valid provider
+       result := testutil.NewRequest().Post("/api-provider-management/v1/registrations").WithJsonBody(newProvider).Go(t, requestHandler)
+       assert.Equal(t, http.StatusCreated, result.Code())
+
+       var resultProvider provapi.APIProviderEnrolmentDetails
+       err := result.UnmarshalBodyToObject(&resultProvider)
+       assert.NoError(t, err, "error unmarshaling response")
+}
+
+func TestPublishUnpublishService(t *testing.T) {
+       apfId := "APF_id_rApp_Kong_as_APF"
+       apiName := "apiName"
+       newApiId := "api_id_" + apiName
+
+       myEnv, myPorts, err := envreader.ReadDotEnv()
+       assert.Nil(t, err, "error reading env file")
+
+       testServiceIpv4 := common29122.Ipv4Addr(myEnv["TEST_SERVICE_IPV4"])
+       testServicePort := common29122.Port(myPorts["TEST_SERVICE_PORT"])
+
+       assert.NotEmpty(t, testServiceIpv4, "TEST_SERVICE_IPV4 is required in .env file for unit testing")
+       assert.NotZero(t, testServicePort, "TEST_SERVICE_PORT is required in .env file for unit testing")
+
+       // Check no services published
+       result := testutil.NewRequest().Get("/published-apis/v1/"+apfId+"/service-apis").Go(t, requestHandler)
+       assert.Equal(t, http.StatusOK, result.Code())
+
+       // Parse JSON from the response body
+       var resultServices []publishapi.ServiceAPIDescription
+       err = result.UnmarshalJsonToObject(&resultServices)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       // Check if the parsed array is empty
+       assert.Zero(t, len(resultServices))
+
+       aefId := "AEF_id_rApp_Kong_as_AEF"
+       namespace := "namespace"
+       repoName := "repoName"
+       chartName := "chartName"
+       releaseName := "releaseName"
+       description := fmt.Sprintf("Description,%s,%s,%s,%s", namespace, repoName, chartName, releaseName)
+
+       newServiceDescription := getServiceAPIDescriptionMissingInterface(aefId, apiName, description)
+
+       // Publish a service for provider
+       result = testutil.NewRequest().Post("/published-apis/v1/"+apfId+"/service-apis").WithJsonBody(newServiceDescription).Go(t, requestHandler)
+       assert.Equal(t, http.StatusBadRequest, result.Code())
+
+       var resultError common29122.ProblemDetails
+       err = result.UnmarshalJsonToObject(&resultError)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       assert.Contains(t, *resultError.Cause, "cannot read interfaceDescription")
+
+       newServiceDescription = getServiceAPIDescription(aefId, apiName, description, testServiceIpv4, testServicePort)
+
+       // Publish a service for provider
+       result = testutil.NewRequest().Post("/published-apis/v1/"+apfId+"/service-apis").WithJsonBody(newServiceDescription).Go(t, requestHandler)
+       assert.Equal(t, http.StatusCreated, result.Code())
+
+       if result.Code() != http.StatusCreated {
+               log.Fatalf("failed to publish the service with HTTP result code %d", result.Code())
+               return
+       }
+
+       var resultService publishapi.ServiceAPIDescription
+       err = result.UnmarshalJsonToObject(&resultService)
+       assert.NoError(t, err, "error unmarshaling response")
+       assert.Equal(t, newApiId, *resultService.ApiId)
+
+       assert.Equal(t, "http://example.com/published-apis/v1/"+apfId+"/service-apis/"+*resultService.ApiId, result.Recorder.Header().Get(echo.HeaderLocation))
+
+       // Check that the service is published for the provider
+       result = testutil.NewRequest().Get("/published-apis/v1/"+apfId+"/service-apis/"+newApiId).Go(t, requestHandler)
+       assert.Equal(t, http.StatusOK, result.Code())
+
+       err = result.UnmarshalJsonToObject(&resultService)
+       assert.NoError(t, err, "error unmarshaling response")
+       assert.Equal(t, newApiId, *resultService.ApiId)
+
+       aefProfile := (*resultService.AefProfiles)[0]
+       interfaceDescription := (*aefProfile.InterfaceDescriptions)[0]
+
+       resultServiceIpv4 := *interfaceDescription.Ipv4Addr
+       resultServicePort := *interfaceDescription.Port
+
+       kongIPv4 := common29122.Ipv4Addr(myEnv["KONG_IPV4"])
+       kongDataPlanePort := common29122.Port(myPorts["KONG_DATA_PLANE_PORT"])
+
+       assert.NotEmpty(t, kongIPv4, "KONG_IPV4 is required in .env file for unit testing")
+       assert.NotZero(t, kongDataPlanePort, "KONG_DATA_PLANE_PORT is required in .env file for unit testing")
+
+       assert.Equal(t, kongIPv4, resultServiceIpv4)
+       assert.Equal(t, kongDataPlanePort, resultServicePort)
+
+       // Publish the same service again should result in Forbidden
+       newServiceDescription.ApiId = &newApiId
+       result = testutil.NewRequest().Post("/published-apis/v1/"+apfId+"/service-apis").WithJsonBody(newServiceDescription).Go(t, requestHandler)
+       assert.Equal(t, http.StatusForbidden, result.Code())
+
+       err = result.UnmarshalBodyToObject(&resultError)
+       assert.NoError(t, err, "error unmarshaling response")
+       assert.Contains(t, *resultError.Cause, "already published")
+       assert.Equal(t, http.StatusForbidden, *resultError.Status)
+
+       // Delete the service
+       result = testutil.NewRequest().Delete("/published-apis/v1/"+apfId+"/service-apis/"+newApiId).Go(t, requestHandler)
+       assert.Equal(t, http.StatusNoContent, result.Code())
+
+       // Check no services published
+       result = testutil.NewRequest().Get("/published-apis/v1/"+apfId+"/service-apis").Go(t, requestHandler)
+       assert.Equal(t, http.StatusOK, result.Code())
+
+       // Parse JSON from the response body
+       err = result.UnmarshalJsonToObject(&resultServices)
+       assert.NoError(t, err, "error unmarshaling response")
+
+       // Check if the parsed array is empty
+       assert.Zero(t, len(resultServices))
+       teardown()
+}
+
+func getEcho(myEnv map[string]string, myPorts map[string]int) (*echo.Echo, error) {
+       capifProtocol := myEnv["CAPIF_PROTOCOL"]
+       capifIPv4 := common29122.Ipv4Addr(myEnv["CAPIF_IPV4"])
+       capifPort := common29122.Port(myPorts["CAPIF_PORT"])
+       kongDomain := myEnv["KONG_DOMAIN"]
+       kongProtocol := myEnv["KONG_PROTOCOL"]
+       kongIPv4 := common29122.Ipv4Addr(myEnv["KONG_IPV4"])
+       kongDataPlanePort := common29122.Port(myPorts["KONG_DATA_PLANE_PORT"])
+       kongControlPlanePort := common29122.Port(myPorts["KONG_CONTROL_PLANE_PORT"])
+
+       e := echo.New()
+
+       // Register ProviderManagement
+       providerManagerSwagger, err := provapi.GetSwagger()
+       if err != nil {
+               log.Fatalf("error loading ProviderManagement swagger spec\n: %s", err)
+               return nil, err
+       }
+       providerManagerSwagger.Servers = nil
+       providerManager := providermanagement.NewProviderManager(capifProtocol, capifIPv4, capifPort)
+
+       var group *echo.Group
+
+       group = e.Group("/api-provider-management/v1")
+       group.Use(middleware.OapiRequestValidator(providerManagerSwagger))
+       provapi.RegisterHandlersWithBaseURL(e, providerManager, "/api-provider-management/v1")
+
+       publishServiceSwagger, err := publishapi.GetSwagger()
+       if err != nil {
+               fmt.Fprintf(os.Stderr, "Error loading PublishService swagger spec\n: %s", err)
+               return nil, err
+       }
+
+       publishServiceSwagger.Servers = nil
+
+       ps := NewPublishService(kongDomain, kongProtocol, kongIPv4, kongDataPlanePort, kongControlPlanePort, capifProtocol, capifIPv4, capifPort)
+
+       group = e.Group("/published-apis/v1")
+       group.Use(echomiddleware.Logger())
+       group.Use(middleware.OapiRequestValidator(publishServiceSwagger))
+       publishapi.RegisterHandlersWithBaseURL(e, ps, "/published-apis/v1")
+
+       // return ps, eventChannel, e
+       return e, err
+}
+
+func getServiceAPIDescription(aefId, apiName, description string, testServiceIpv4 common29122.Ipv4Addr, testServicePort common29122.Port) publishapi.ServiceAPIDescription {
+       domainName := "Kong"
+       var protocol publishapi.Protocol = "HTTP_1_1"
+
+       return publishapi.ServiceAPIDescription{
+               AefProfiles: &[]publishapi.AefProfile{
+                       {
+                               AefId: aefId,
+                               InterfaceDescriptions: &[]publishapi.InterfaceDescription{
+                                       {
+                                               Ipv4Addr: &testServiceIpv4,
+                                               Port:     &testServicePort,
+                                               SecurityMethods: &[]publishapi.SecurityMethod{
+                                                       "PKI",
+                                               },
+                                       },
+                               },
+                               DomainName: &domainName,
+                               Protocol:   &protocol,
+                               Versions: []publishapi.Version{
+                                       {
+                                               ApiVersion: "v1",
+                                               Resources: &[]publishapi.Resource{
+                                                       {
+                                                               CommType: "REQUEST_RESPONSE",
+                                                               Operations: &[]publishapi.Operation{
+                                                                       "GET",
+                                                               },
+                                                               ResourceName: "helloworld",
+                                                               Uri:          "/helloworld",
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+               },
+               ApiName:     apiName,
+               Description: &description,
+       }
+}
+
+func getServiceAPIDescriptionMissingInterface(aefId, apiName, description string) publishapi.ServiceAPIDescription {
+       domainName := "Kong"
+       var protocol publishapi.Protocol = "HTTP_1_1"
+
+       return publishapi.ServiceAPIDescription{
+               AefProfiles: &[]publishapi.AefProfile{
+                       {
+                               AefId:      aefId,
+                               DomainName: &domainName,
+                               Protocol:   &protocol,
+                               Versions: []publishapi.Version{
+                                       {
+                                               ApiVersion: "v1",
+                                               Resources: &[]publishapi.Resource{
+                                                       {
+                                                               CommType: "REQUEST_RESPONSE",
+                                                               Operations: &[]publishapi.Operation{
+                                                                       "GET",
+                                                               },
+                                                               ResourceName: "helloworld",
+                                                               Uri:          "/helloworld",
+                                                       },
+                                               },
+                                       },
+                               },
+                       },
+               },
+               ApiName:     apiName,
+               Description: &description,
+       }
+}
diff --git a/servicemanager/internal/publishserviceapi/publishserviceapi-client.gen.go b/servicemanager/internal/publishserviceapi/publishserviceapi-client.gen.go
new file mode 100644 (file)
index 0000000..363fbf4
--- /dev/null
@@ -0,0 +1,883 @@
+// Package publishserviceapi provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/deepmap/oapi-codegen version v1.10.1 DO NOT EDIT.
+package publishserviceapi
+
+import (
+       "bytes"
+       "context"
+       "encoding/json"
+       "fmt"
+       "io"
+       "io/ioutil"
+       "net/http"
+       "net/url"
+       "strings"
+
+       "github.com/deepmap/oapi-codegen/pkg/runtime"
+)
+
+// RequestEditorFn  is the function signature for the RequestEditor callback function
+type RequestEditorFn func(ctx context.Context, req *http.Request) error
+
+// Doer performs HTTP requests.
+//
+// The standard http.Client implements this interface.
+type HttpRequestDoer interface {
+       Do(req *http.Request) (*http.Response, error)
+}
+
+// Client which conforms to the OpenAPI3 specification for this service.
+type Client struct {
+       // The endpoint of the server conforming to this interface, with scheme,
+       // https://api.deepmap.com for example. This can contain a path relative
+       // to the server, such as https://api.deepmap.com/dev-test, and all the
+       // paths in the swagger spec will be appended to the server.
+       Server string
+
+       // Doer for performing requests, typically a *http.Client with any
+       // customized settings, such as certificate chains.
+       Client HttpRequestDoer
+
+       // A list of callbacks for modifying requests which are generated before sending over
+       // the network.
+       RequestEditors []RequestEditorFn
+}
+
+// ClientOption allows setting custom parameters during construction
+type ClientOption func(*Client) error
+
+// Creates a new Client, with reasonable defaults
+func NewClient(server string, opts ...ClientOption) (*Client, error) {
+       // create a client with sane default values
+       client := Client{
+               Server: server,
+       }
+       // mutate client and add all optional params
+       for _, o := range opts {
+               if err := o(&client); err != nil {
+                       return nil, err
+               }
+       }
+       // ensure the server URL always has a trailing slash
+       if !strings.HasSuffix(client.Server, "/") {
+               client.Server += "/"
+       }
+       // create httpClient, if not already present
+       if client.Client == nil {
+               client.Client = &http.Client{}
+       }
+       return &client, nil
+}
+
+// WithHTTPClient allows overriding the default Doer, which is
+// automatically created using http.Client. This is useful for tests.
+func WithHTTPClient(doer HttpRequestDoer) ClientOption {
+       return func(c *Client) error {
+               c.Client = doer
+               return nil
+       }
+}
+
+// WithRequestEditorFn allows setting up a callback function, which will be
+// called right before sending the request. This can be used to mutate the request.
+func WithRequestEditorFn(fn RequestEditorFn) ClientOption {
+       return func(c *Client) error {
+               c.RequestEditors = append(c.RequestEditors, fn)
+               return nil
+       }
+}
+
+// The interface specification for the client above.
+type ClientInterface interface {
+       // GetApfIdServiceApis request
+       GetApfIdServiceApis(ctx context.Context, apfId string, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+       // PostApfIdServiceApis request with any body
+       PostApfIdServiceApisWithBody(ctx context.Context, apfId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+       PostApfIdServiceApis(ctx context.Context, apfId string, body PostApfIdServiceApisJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+       // DeleteApfIdServiceApisServiceApiId request
+       DeleteApfIdServiceApisServiceApiId(ctx context.Context, apfId string, serviceApiId string, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+       // GetApfIdServiceApisServiceApiId request
+       GetApfIdServiceApisServiceApiId(ctx context.Context, apfId string, serviceApiId string, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+       // ModifyIndAPFPubAPI request with any body
+       ModifyIndAPFPubAPIWithBody(ctx context.Context, apfId string, serviceApiId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+       // PutApfIdServiceApisServiceApiId request with any body
+       PutApfIdServiceApisServiceApiIdWithBody(ctx context.Context, apfId string, serviceApiId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error)
+
+       PutApfIdServiceApisServiceApiId(ctx context.Context, apfId string, serviceApiId string, body PutApfIdServiceApisServiceApiIdJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error)
+}
+
+func (c *Client) GetApfIdServiceApis(ctx context.Context, apfId string, reqEditors ...RequestEditorFn) (*http.Response, error) {
+       req, err := NewGetApfIdServiceApisRequest(c.Server, apfId)
+       if err != nil {
+               return nil, err
+       }
+       req = req.WithContext(ctx)
+       if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+               return nil, err
+       }
+       return c.Client.Do(req)
+}
+
+func (c *Client) PostApfIdServiceApisWithBody(ctx context.Context, apfId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) {
+       req, err := NewPostApfIdServiceApisRequestWithBody(c.Server, apfId, contentType, body)
+       if err != nil {
+               return nil, err
+       }
+       req = req.WithContext(ctx)
+       if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+               return nil, err
+       }
+       return c.Client.Do(req)
+}
+
+func (c *Client) PostApfIdServiceApis(ctx context.Context, apfId string, body PostApfIdServiceApisJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) {
+       req, err := NewPostApfIdServiceApisRequest(c.Server, apfId, body)
+       if err != nil {
+               return nil, err
+       }
+       req = req.WithContext(ctx)
+       if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+               return nil, err
+       }
+       return c.Client.Do(req)
+}
+
+func (c *Client) DeleteApfIdServiceApisServiceApiId(ctx context.Context, apfId string, serviceApiId string, reqEditors ...RequestEditorFn) (*http.Response, error) {
+       req, err := NewDeleteApfIdServiceApisServiceApiIdRequest(c.Server, apfId, serviceApiId)
+       if err != nil {
+               return nil, err
+       }
+       req = req.WithContext(ctx)
+       if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+               return nil, err
+       }
+       return c.Client.Do(req)
+}
+
+func (c *Client) GetApfIdServiceApisServiceApiId(ctx context.Context, apfId string, serviceApiId string, reqEditors ...RequestEditorFn) (*http.Response, error) {
+       req, err := NewGetApfIdServiceApisServiceApiIdRequest(c.Server, apfId, serviceApiId)
+       if err != nil {
+               return nil, err
+       }
+       req = req.WithContext(ctx)
+       if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+               return nil, err
+       }
+       return c.Client.Do(req)
+}
+
+func (c *Client) ModifyIndAPFPubAPIWithBody(ctx context.Context, apfId string, serviceApiId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) {
+       req, err := NewModifyIndAPFPubAPIRequestWithBody(c.Server, apfId, serviceApiId, contentType, body)
+       if err != nil {
+               return nil, err
+       }
+       req = req.WithContext(ctx)
+       if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+               return nil, err
+       }
+       return c.Client.Do(req)
+}
+
+func (c *Client) PutApfIdServiceApisServiceApiIdWithBody(ctx context.Context, apfId string, serviceApiId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) {
+       req, err := NewPutApfIdServiceApisServiceApiIdRequestWithBody(c.Server, apfId, serviceApiId, contentType, body)
+       if err != nil {
+               return nil, err
+       }
+       req = req.WithContext(ctx)
+       if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+               return nil, err
+       }
+       return c.Client.Do(req)
+}
+
+func (c *Client) PutApfIdServiceApisServiceApiId(ctx context.Context, apfId string, serviceApiId string, body PutApfIdServiceApisServiceApiIdJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) {
+       req, err := NewPutApfIdServiceApisServiceApiIdRequest(c.Server, apfId, serviceApiId, body)
+       if err != nil {
+               return nil, err
+       }
+       req = req.WithContext(ctx)
+       if err := c.applyEditors(ctx, req, reqEditors); err != nil {
+               return nil, err
+       }
+       return c.Client.Do(req)
+}
+
+// NewGetApfIdServiceApisRequest generates requests for GetApfIdServiceApis
+func NewGetApfIdServiceApisRequest(server string, apfId string) (*http.Request, error) {
+       var err error
+
+       var pathParam0 string
+
+       pathParam0, err = runtime.StyleParamWithLocation("simple", false, "apfId", runtime.ParamLocationPath, apfId)
+       if err != nil {
+               return nil, err
+       }
+
+       serverURL, err := url.Parse(server)
+       if err != nil {
+               return nil, err
+       }
+
+       operationPath := fmt.Sprintf("/%s/service-apis", pathParam0)
+       if operationPath[0] == '/' {
+               operationPath = "." + operationPath
+       }
+
+       queryURL, err := serverURL.Parse(operationPath)
+       if err != nil {
+               return nil, err
+       }
+
+       req, err := http.NewRequest("GET", queryURL.String(), nil)
+       if err != nil {
+               return nil, err
+       }
+
+       return req, nil
+}
+
+// NewPostApfIdServiceApisRequest calls the generic PostApfIdServiceApis builder with application/json body
+func NewPostApfIdServiceApisRequest(server string, apfId string, body PostApfIdServiceApisJSONRequestBody) (*http.Request, error) {
+       var bodyReader io.Reader
+       buf, err := json.Marshal(body)
+       if err != nil {
+               return nil, err
+       }
+       bodyReader = bytes.NewReader(buf)
+       return NewPostApfIdServiceApisRequestWithBody(server, apfId, "application/json", bodyReader)
+}
+
+// NewPostApfIdServiceApisRequestWithBody generates requests for PostApfIdServiceApis with any type of body
+func NewPostApfIdServiceApisRequestWithBody(server string, apfId string, contentType string, body io.Reader) (*http.Request, error) {
+       var err error
+
+       var pathParam0 string
+
+       pathParam0, err = runtime.StyleParamWithLocation("simple", false, "apfId", runtime.ParamLocationPath, apfId)
+       if err != nil {
+               return nil, err
+       }
+
+       serverURL, err := url.Parse(server)
+       if err != nil {
+               return nil, err
+       }
+
+       operationPath := fmt.Sprintf("/%s/service-apis", pathParam0)
+       if operationPath[0] == '/' {
+               operationPath = "." + operationPath
+       }
+
+       queryURL, err := serverURL.Parse(operationPath)
+       if err != nil {
+               return nil, err
+       }
+
+       req, err := http.NewRequest("POST", queryURL.String(), body)
+       if err != nil {
+               return nil, err
+       }
+
+       req.Header.Add("Content-Type", contentType)
+
+       return req, nil
+}
+
+// NewDeleteApfIdServiceApisServiceApiIdRequest generates requests for DeleteApfIdServiceApisServiceApiId
+func NewDeleteApfIdServiceApisServiceApiIdRequest(server string, apfId string, serviceApiId string) (*http.Request, error) {
+       var err error
+
+       var pathParam0 string
+
+       pathParam0, err = runtime.StyleParamWithLocation("simple", false, "apfId", runtime.ParamLocationPath, apfId)
+       if err != nil {
+               return nil, err
+       }
+
+       var pathParam1 string
+
+       pathParam1, err = runtime.StyleParamWithLocation("simple", false, "serviceApiId", runtime.ParamLocationPath, serviceApiId)
+       if err != nil {
+               return nil, err
+       }
+
+       serverURL, err := url.Parse(server)
+       if err != nil {
+               return nil, err
+       }
+
+       operationPath := fmt.Sprintf("/%s/service-apis/%s", pathParam0, pathParam1)
+       if operationPath[0] == '/' {
+               operationPath = "." + operationPath
+       }
+
+       queryURL, err := serverURL.Parse(operationPath)
+       if err != nil {
+               return nil, err
+       }
+
+       req, err := http.NewRequest("DELETE", queryURL.String(), nil)
+       if err != nil {
+               return nil, err
+       }
+
+       return req, nil
+}
+
+// NewGetApfIdServiceApisServiceApiIdRequest generates requests for GetApfIdServiceApisServiceApiId
+func NewGetApfIdServiceApisServiceApiIdRequest(server string, apfId string, serviceApiId string) (*http.Request, error) {
+       var err error
+
+       var pathParam0 string
+
+       pathParam0, err = runtime.StyleParamWithLocation("simple", false, "apfId", runtime.ParamLocationPath, apfId)
+       if err != nil {
+               return nil, err
+       }
+
+       var pathParam1 string
+
+       pathParam1, err = runtime.StyleParamWithLocation("simple", false, "serviceApiId", runtime.ParamLocationPath, serviceApiId)
+       if err != nil {
+               return nil, err
+       }
+
+       serverURL, err := url.Parse(server)
+       if err != nil {
+               return nil, err
+       }
+
+       operationPath := fmt.Sprintf("/%s/service-apis/%s", pathParam0, pathParam1)
+       if operationPath[0] == '/' {
+               operationPath = "." + operationPath
+       }
+
+       queryURL, err := serverURL.Parse(operationPath)
+       if err != nil {
+               return nil, err
+       }
+
+       req, err := http.NewRequest("GET", queryURL.String(), nil)
+       if err != nil {
+               return nil, err
+       }
+
+       return req, nil
+}
+
+// NewModifyIndAPFPubAPIRequestWithBody generates requests for ModifyIndAPFPubAPI with any type of body
+func NewModifyIndAPFPubAPIRequestWithBody(server string, apfId string, serviceApiId string, contentType string, body io.Reader) (*http.Request, error) {
+       var err error
+
+       var pathParam0 string
+
+       pathParam0, err = runtime.StyleParamWithLocation("simple", false, "apfId", runtime.ParamLocationPath, apfId)
+       if err != nil {
+               return nil, err
+       }
+
+       var pathParam1 string
+
+       pathParam1, err = runtime.StyleParamWithLocation("simple", false, "serviceApiId", runtime.ParamLocationPath, serviceApiId)
+       if err != nil {
+               return nil, err
+       }
+
+       serverURL, err := url.Parse(server)
+       if err != nil {
+               return nil, err
+       }
+
+       operationPath := fmt.Sprintf("/%s/service-apis/%s", pathParam0, pathParam1)
+       if operationPath[0] == '/' {
+               operationPath = "." + operationPath
+       }
+
+       queryURL, err := serverURL.Parse(operationPath)
+       if err != nil {
+               return nil, err
+       }
+
+       req, err := http.NewRequest("PATCH", queryURL.String(), body)
+       if err != nil {
+               return nil, err
+       }
+
+       req.Header.Add("Content-Type", contentType)
+
+       return req, nil
+}
+
+// NewPutApfIdServiceApisServiceApiIdRequest calls the generic PutApfIdServiceApisServiceApiId builder with application/json body
+func NewPutApfIdServiceApisServiceApiIdRequest(server string, apfId string, serviceApiId string, body PutApfIdServiceApisServiceApiIdJSONRequestBody) (*http.Request, error) {
+       var bodyReader io.Reader
+       buf, err := json.Marshal(body)
+       if err != nil {
+               return nil, err
+       }
+       bodyReader = bytes.NewReader(buf)
+       return NewPutApfIdServiceApisServiceApiIdRequestWithBody(server, apfId, serviceApiId, "application/json", bodyReader)
+}
+
+// NewPutApfIdServiceApisServiceApiIdRequestWithBody generates requests for PutApfIdServiceApisServiceApiId with any type of body
+func NewPutApfIdServiceApisServiceApiIdRequestWithBody(server string, apfId string, serviceApiId string, contentType string, body io.Reader) (*http.Request, error) {
+       var err error
+
+       var pathParam0 string
+
+       pathParam0, err = runtime.StyleParamWithLocation("simple", false, "apfId", runtime.ParamLocationPath, apfId)
+       if err != nil {
+               return nil, err
+       }
+
+       var pathParam1 string
+
+       pathParam1, err = runtime.StyleParamWithLocation("simple", false, "serviceApiId", runtime.ParamLocationPath, serviceApiId)
+       if err != nil {
+               return nil, err
+       }
+
+       serverURL, err := url.Parse(server)
+       if err != nil {
+               return nil, err
+       }
+
+       operationPath := fmt.Sprintf("/%s/service-apis/%s", pathParam0, pathParam1)
+       if operationPath[0] == '/' {
+               operationPath = "." + operationPath
+       }
+
+       queryURL, err := serverURL.Parse(operationPath)
+       if err != nil {
+               return nil, err
+       }
+
+       req, err := http.NewRequest("PUT", queryURL.String(), body)
+       if err != nil {
+               return nil, err
+       }
+
+       req.Header.Add("Content-Type", contentType)
+
+       return req, nil
+}
+
+func (c *Client) applyEditors(ctx context.Context, req *http.Request, additionalEditors []RequestEditorFn) error {
+       for _, r := range c.RequestEditors {
+               if err := r(ctx, req); err != nil {
+                       return err
+               }
+       }
+       for _, r := range additionalEditors {
+               if err := r(ctx, req); err != nil {
+                       return err
+               }
+       }
+       return nil
+}
+
+// ClientWithResponses builds on ClientInterface to offer response payloads
+type ClientWithResponses struct {
+       ClientInterface
+}
+
+// NewClientWithResponses creates a new ClientWithResponses, which wraps
+// Client with return type handling
+func NewClientWithResponses(server string, opts ...ClientOption) (*ClientWithResponses, error) {
+       client, err := NewClient(server, opts...)
+       if err != nil {
+               return nil, err
+       }
+       return &ClientWithResponses{client}, nil
+}
+
+// WithBaseURL overrides the baseURL.
+func WithBaseURL(baseURL string) ClientOption {
+       return func(c *Client) error {
+               newBaseURL, err := url.Parse(baseURL)
+               if err != nil {
+                       return err
+               }
+               c.Server = newBaseURL.String()
+               return nil
+       }
+}
+
+// ClientWithResponsesInterface is the interface specification for the client with responses above.
+type ClientWithResponsesInterface interface {
+       // GetApfIdServiceApis request
+       GetApfIdServiceApisWithResponse(ctx context.Context, apfId string, reqEditors ...RequestEditorFn) (*GetApfIdServiceApisResponse, error)
+
+       // PostApfIdServiceApis request with any body
+       PostApfIdServiceApisWithBodyWithResponse(ctx context.Context, apfId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostApfIdServiceApisResponse, error)
+
+       PostApfIdServiceApisWithResponse(ctx context.Context, apfId string, body PostApfIdServiceApisJSONRequestBody, reqEditors ...RequestEditorFn) (*PostApfIdServiceApisResponse, error)
+
+       // DeleteApfIdServiceApisServiceApiId request
+       DeleteApfIdServiceApisServiceApiIdWithResponse(ctx context.Context, apfId string, serviceApiId string, reqEditors ...RequestEditorFn) (*DeleteApfIdServiceApisServiceApiIdResponse, error)
+
+       // GetApfIdServiceApisServiceApiId request
+       GetApfIdServiceApisServiceApiIdWithResponse(ctx context.Context, apfId string, serviceApiId string, reqEditors ...RequestEditorFn) (*GetApfIdServiceApisServiceApiIdResponse, error)
+
+       // ModifyIndAPFPubAPI request with any body
+       ModifyIndAPFPubAPIWithBodyWithResponse(ctx context.Context, apfId string, serviceApiId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*ModifyIndAPFPubAPIResponse, error)
+
+       // PutApfIdServiceApisServiceApiId request with any body
+       PutApfIdServiceApisServiceApiIdWithBodyWithResponse(ctx context.Context, apfId string, serviceApiId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PutApfIdServiceApisServiceApiIdResponse, error)
+
+       PutApfIdServiceApisServiceApiIdWithResponse(ctx context.Context, apfId string, serviceApiId string, body PutApfIdServiceApisServiceApiIdJSONRequestBody, reqEditors ...RequestEditorFn) (*PutApfIdServiceApisServiceApiIdResponse, error)
+}
+
+type GetApfIdServiceApisResponse struct {
+       Body         []byte
+       HTTPResponse *http.Response
+       JSON200      *[]ServiceAPIDescription
+}
+
+// Status returns HTTPResponse.Status
+func (r GetApfIdServiceApisResponse) Status() string {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.Status
+       }
+       return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r GetApfIdServiceApisResponse) StatusCode() int {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.StatusCode
+       }
+       return 0
+}
+
+type PostApfIdServiceApisResponse struct {
+       Body         []byte
+       HTTPResponse *http.Response
+       JSON201      *ServiceAPIDescription
+}
+
+// Status returns HTTPResponse.Status
+func (r PostApfIdServiceApisResponse) Status() string {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.Status
+       }
+       return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r PostApfIdServiceApisResponse) StatusCode() int {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.StatusCode
+       }
+       return 0
+}
+
+type DeleteApfIdServiceApisServiceApiIdResponse struct {
+       Body         []byte
+       HTTPResponse *http.Response
+}
+
+// Status returns HTTPResponse.Status
+func (r DeleteApfIdServiceApisServiceApiIdResponse) Status() string {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.Status
+       }
+       return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r DeleteApfIdServiceApisServiceApiIdResponse) StatusCode() int {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.StatusCode
+       }
+       return 0
+}
+
+type GetApfIdServiceApisServiceApiIdResponse struct {
+       Body         []byte
+       HTTPResponse *http.Response
+       JSON200      *ServiceAPIDescription
+}
+
+// Status returns HTTPResponse.Status
+func (r GetApfIdServiceApisServiceApiIdResponse) Status() string {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.Status
+       }
+       return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r GetApfIdServiceApisServiceApiIdResponse) StatusCode() int {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.StatusCode
+       }
+       return 0
+}
+
+type ModifyIndAPFPubAPIResponse struct {
+       Body         []byte
+       HTTPResponse *http.Response
+       JSON200      *ServiceAPIDescription
+}
+
+// Status returns HTTPResponse.Status
+func (r ModifyIndAPFPubAPIResponse) Status() string {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.Status
+       }
+       return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r ModifyIndAPFPubAPIResponse) StatusCode() int {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.StatusCode
+       }
+       return 0
+}
+
+type PutApfIdServiceApisServiceApiIdResponse struct {
+       Body         []byte
+       HTTPResponse *http.Response
+       JSON200      *ServiceAPIDescription
+}
+
+// Status returns HTTPResponse.Status
+func (r PutApfIdServiceApisServiceApiIdResponse) Status() string {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.Status
+       }
+       return http.StatusText(0)
+}
+
+// StatusCode returns HTTPResponse.StatusCode
+func (r PutApfIdServiceApisServiceApiIdResponse) StatusCode() int {
+       if r.HTTPResponse != nil {
+               return r.HTTPResponse.StatusCode
+       }
+       return 0
+}
+
+// GetApfIdServiceApisWithResponse request returning *GetApfIdServiceApisResponse
+func (c *ClientWithResponses) GetApfIdServiceApisWithResponse(ctx context.Context, apfId string, reqEditors ...RequestEditorFn) (*GetApfIdServiceApisResponse, error) {
+       rsp, err := c.GetApfIdServiceApis(ctx, apfId, reqEditors...)
+       if err != nil {
+               return nil, err
+       }
+       return ParseGetApfIdServiceApisResponse(rsp)
+}
+
+// PostApfIdServiceApisWithBodyWithResponse request with arbitrary body returning *PostApfIdServiceApisResponse
+func (c *ClientWithResponses) PostApfIdServiceApisWithBodyWithResponse(ctx context.Context, apfId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PostApfIdServiceApisResponse, error) {
+       rsp, err := c.PostApfIdServiceApisWithBody(ctx, apfId, contentType, body, reqEditors...)
+       if err != nil {
+               return nil, err
+       }
+       return ParsePostApfIdServiceApisResponse(rsp)
+}
+
+func (c *ClientWithResponses) PostApfIdServiceApisWithResponse(ctx context.Context, apfId string, body PostApfIdServiceApisJSONRequestBody, reqEditors ...RequestEditorFn) (*PostApfIdServiceApisResponse, error) {
+       rsp, err := c.PostApfIdServiceApis(ctx, apfId, body, reqEditors...)
+       if err != nil {
+               return nil, err
+       }
+       return ParsePostApfIdServiceApisResponse(rsp)
+}
+
+// DeleteApfIdServiceApisServiceApiIdWithResponse request returning *DeleteApfIdServiceApisServiceApiIdResponse
+func (c *ClientWithResponses) DeleteApfIdServiceApisServiceApiIdWithResponse(ctx context.Context, apfId string, serviceApiId string, reqEditors ...RequestEditorFn) (*DeleteApfIdServiceApisServiceApiIdResponse, error) {
+       rsp, err := c.DeleteApfIdServiceApisServiceApiId(ctx, apfId, serviceApiId, reqEditors...)
+       if err != nil {
+               return nil, err
+       }
+       return ParseDeleteApfIdServiceApisServiceApiIdResponse(rsp)
+}
+
+// GetApfIdServiceApisServiceApiIdWithResponse request returning *GetApfIdServiceApisServiceApiIdResponse
+func (c *ClientWithResponses) GetApfIdServiceApisServiceApiIdWithResponse(ctx context.Context, apfId string, serviceApiId string, reqEditors ...RequestEditorFn) (*GetApfIdServiceApisServiceApiIdResponse, error) {
+       rsp, err := c.GetApfIdServiceApisServiceApiId(ctx, apfId, serviceApiId, reqEditors...)
+       if err != nil {
+               return nil, err
+       }
+       return ParseGetApfIdServiceApisServiceApiIdResponse(rsp)
+}
+
+// ModifyIndAPFPubAPIWithBodyWithResponse request with arbitrary body returning *ModifyIndAPFPubAPIResponse
+func (c *ClientWithResponses) ModifyIndAPFPubAPIWithBodyWithResponse(ctx context.Context, apfId string, serviceApiId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*ModifyIndAPFPubAPIResponse, error) {
+       rsp, err := c.ModifyIndAPFPubAPIWithBody(ctx, apfId, serviceApiId, contentType, body, reqEditors...)
+       if err != nil {
+               return nil, err
+       }
+       return ParseModifyIndAPFPubAPIResponse(rsp)
+}
+
+// PutApfIdServiceApisServiceApiIdWithBodyWithResponse request with arbitrary body returning *PutApfIdServiceApisServiceApiIdResponse
+func (c *ClientWithResponses) PutApfIdServiceApisServiceApiIdWithBodyWithResponse(ctx context.Context, apfId string, serviceApiId string, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*PutApfIdServiceApisServiceApiIdResponse, error) {
+       rsp, err := c.PutApfIdServiceApisServiceApiIdWithBody(ctx, apfId, serviceApiId, contentType, body, reqEditors...)
+       if err != nil {
+               return nil, err
+       }
+       return ParsePutApfIdServiceApisServiceApiIdResponse(rsp)
+}
+
+func (c *ClientWithResponses) PutApfIdServiceApisServiceApiIdWithResponse(ctx context.Context, apfId string, serviceApiId string, body PutApfIdServiceApisServiceApiIdJSONRequestBody, reqEditors ...RequestEditorFn) (*PutApfIdServiceApisServiceApiIdResponse, error) {
+       rsp, err := c.PutApfIdServiceApisServiceApiId(ctx, apfId, serviceApiId, body, reqEditors...)
+       if err != nil {
+               return nil, err
+       }
+       return ParsePutApfIdServiceApisServiceApiIdResponse(rsp)
+}
+
+// ParseGetApfIdServiceApisResponse parses an HTTP response from a GetApfIdServiceApisWithResponse call
+func ParseGetApfIdServiceApisResponse(rsp *http.Response) (*GetApfIdServiceApisResponse, error) {
+       bodyBytes, err := ioutil.ReadAll(rsp.Body)
+       defer func() { _ = rsp.Body.Close() }()
+       if err != nil {
+               return nil, err
+       }
+
+       response := &GetApfIdServiceApisResponse{
+               Body:         bodyBytes,
+               HTTPResponse: rsp,
+       }
+
+       switch {
+       case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
+               var dest []ServiceAPIDescription
+               if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+                       return nil, err
+               }
+               response.JSON200 = &dest
+
+       }
+
+       return response, nil
+}
+
+// ParsePostApfIdServiceApisResponse parses an HTTP response from a PostApfIdServiceApisWithResponse call
+func ParsePostApfIdServiceApisResponse(rsp *http.Response) (*PostApfIdServiceApisResponse, error) {
+       bodyBytes, err := ioutil.ReadAll(rsp.Body)
+       defer func() { _ = rsp.Body.Close() }()
+       if err != nil {
+               return nil, err
+       }
+
+       response := &PostApfIdServiceApisResponse{
+               Body:         bodyBytes,
+               HTTPResponse: rsp,
+       }
+
+       switch {
+       case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 201:
+               var dest ServiceAPIDescription
+               if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+                       return nil, err
+               }
+               response.JSON201 = &dest
+
+       }
+
+       return response, nil
+}
+
+// ParseDeleteApfIdServiceApisServiceApiIdResponse parses an HTTP response from a DeleteApfIdServiceApisServiceApiIdWithResponse call
+func ParseDeleteApfIdServiceApisServiceApiIdResponse(rsp *http.Response) (*DeleteApfIdServiceApisServiceApiIdResponse, error) {
+       bodyBytes, err := ioutil.ReadAll(rsp.Body)
+       defer func() { _ = rsp.Body.Close() }()
+       if err != nil {
+               return nil, err
+       }
+
+       response := &DeleteApfIdServiceApisServiceApiIdResponse{
+               Body:         bodyBytes,
+               HTTPResponse: rsp,
+       }
+
+       return response, nil
+}
+
+// ParseGetApfIdServiceApisServiceApiIdResponse parses an HTTP response from a GetApfIdServiceApisServiceApiIdWithResponse call
+func ParseGetApfIdServiceApisServiceApiIdResponse(rsp *http.Response) (*GetApfIdServiceApisServiceApiIdResponse, error) {
+       bodyBytes, err := ioutil.ReadAll(rsp.Body)
+       defer func() { _ = rsp.Body.Close() }()
+       if err != nil {
+               return nil, err
+       }
+
+       response := &GetApfIdServiceApisServiceApiIdResponse{
+               Body:         bodyBytes,
+               HTTPResponse: rsp,
+       }
+
+       switch {
+       case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
+               var dest ServiceAPIDescription
+               if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+                       return nil, err
+               }
+               response.JSON200 = &dest
+
+       }
+
+       return response, nil
+}
+
+// ParseModifyIndAPFPubAPIResponse parses an HTTP response from a ModifyIndAPFPubAPIWithResponse call
+func ParseModifyIndAPFPubAPIResponse(rsp *http.Response) (*ModifyIndAPFPubAPIResponse, error) {
+       bodyBytes, err := ioutil.ReadAll(rsp.Body)
+       defer func() { _ = rsp.Body.Close() }()
+       if err != nil {
+               return nil, err
+       }
+
+       response := &ModifyIndAPFPubAPIResponse{
+               Body:         bodyBytes,
+               HTTPResponse: rsp,
+       }
+
+       switch {
+       case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
+               var dest ServiceAPIDescription
+               if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+                       return nil, err
+               }
+               response.JSON200 = &dest
+
+       }
+
+       return response, nil
+}
+
+// ParsePutApfIdServiceApisServiceApiIdResponse parses an HTTP response from a PutApfIdServiceApisServiceApiIdWithResponse call
+func ParsePutApfIdServiceApisServiceApiIdResponse(rsp *http.Response) (*PutApfIdServiceApisServiceApiIdResponse, error) {
+       bodyBytes, err := ioutil.ReadAll(rsp.Body)
+       defer func() { _ = rsp.Body.Close() }()
+       if err != nil {
+               return nil, err
+       }
+
+       response := &PutApfIdServiceApisServiceApiIdResponse{
+               Body:         bodyBytes,
+               HTTPResponse: rsp,
+       }
+
+       switch {
+       case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200:
+               var dest ServiceAPIDescription
+               if err := json.Unmarshal(bodyBytes, &dest); err != nil {
+                       return nil, err
+               }
+               response.JSON200 = &dest
+
+       }
+
+       return response, nil
+}
diff --git a/servicemanager/internal/publishserviceapi/publishserviceapi-server.gen.go b/servicemanager/internal/publishserviceapi/publishserviceapi-server.gen.go
new file mode 100644 (file)
index 0000000..b81073c
--- /dev/null
@@ -0,0 +1,360 @@
+// Package publishserviceapi provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/deepmap/oapi-codegen version v1.10.1 DO NOT EDIT.
+package publishserviceapi
+
+import (
+       "bytes"
+       "compress/gzip"
+       "encoding/base64"
+       "fmt"
+       "net/http"
+       "net/url"
+       "path"
+       "strings"
+
+       "github.com/deepmap/oapi-codegen/pkg/runtime"
+       "github.com/getkin/kin-openapi/openapi3"
+       "github.com/labstack/echo/v4"
+       externalRef0 "oransc.org/nonrtric/servicemanager/internal/common"
+       externalRef1 "oransc.org/nonrtric/servicemanager/internal/common29122"
+       externalRef2 "oransc.org/nonrtric/servicemanager/internal/common29571"
+)
+
+// ServerInterface represents all server handlers.
+type ServerInterface interface {
+
+       // (GET /{apfId}/service-apis)
+       GetApfIdServiceApis(ctx echo.Context, apfId string) error
+
+       // (POST /{apfId}/service-apis)
+       PostApfIdServiceApis(ctx echo.Context, apfId string) error
+
+       // (DELETE /{apfId}/service-apis/{serviceApiId})
+       DeleteApfIdServiceApisServiceApiId(ctx echo.Context, apfId string, serviceApiId string) error
+
+       // (GET /{apfId}/service-apis/{serviceApiId})
+       GetApfIdServiceApisServiceApiId(ctx echo.Context, apfId string, serviceApiId string) error
+
+       // (PATCH /{apfId}/service-apis/{serviceApiId})
+       ModifyIndAPFPubAPI(ctx echo.Context, apfId string, serviceApiId string) error
+
+       // (PUT /{apfId}/service-apis/{serviceApiId})
+       PutApfIdServiceApisServiceApiId(ctx echo.Context, apfId string, serviceApiId string) error
+}
+
+// ServerInterfaceWrapper converts echo contexts to parameters.
+type ServerInterfaceWrapper struct {
+       Handler ServerInterface
+}
+
+// GetApfIdServiceApis converts echo context to params.
+func (w *ServerInterfaceWrapper) GetApfIdServiceApis(ctx echo.Context) error {
+       var err error
+       // ------------- Path parameter "apfId" -------------
+       var apfId string
+
+       err = runtime.BindStyledParameterWithLocation("simple", false, "apfId", runtime.ParamLocationPath, ctx.Param("apfId"), &apfId)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter apfId: %s", err))
+       }
+
+       // Invoke the callback with all the unmarshalled arguments
+       err = w.Handler.GetApfIdServiceApis(ctx, apfId)
+       return err
+}
+
+// PostApfIdServiceApis converts echo context to params.
+func (w *ServerInterfaceWrapper) PostApfIdServiceApis(ctx echo.Context) error {
+       var err error
+       // ------------- Path parameter "apfId" -------------
+       var apfId string
+
+       err = runtime.BindStyledParameterWithLocation("simple", false, "apfId", runtime.ParamLocationPath, ctx.Param("apfId"), &apfId)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter apfId: %s", err))
+       }
+
+       // Invoke the callback with all the unmarshalled arguments
+       err = w.Handler.PostApfIdServiceApis(ctx, apfId)
+       return err
+}
+
+// DeleteApfIdServiceApisServiceApiId converts echo context to params.
+func (w *ServerInterfaceWrapper) DeleteApfIdServiceApisServiceApiId(ctx echo.Context) error {
+       var err error
+       // ------------- Path parameter "apfId" -------------
+       var apfId string
+
+       err = runtime.BindStyledParameterWithLocation("simple", false, "apfId", runtime.ParamLocationPath, ctx.Param("apfId"), &apfId)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter apfId: %s", err))
+       }
+
+       // ------------- Path parameter "serviceApiId" -------------
+       var serviceApiId string
+
+       err = runtime.BindStyledParameterWithLocation("simple", false, "serviceApiId", runtime.ParamLocationPath, ctx.Param("serviceApiId"), &serviceApiId)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter serviceApiId: %s", err))
+       }
+
+       // Invoke the callback with all the unmarshalled arguments
+       err = w.Handler.DeleteApfIdServiceApisServiceApiId(ctx, apfId, serviceApiId)
+       return err
+}
+
+// GetApfIdServiceApisServiceApiId converts echo context to params.
+func (w *ServerInterfaceWrapper) GetApfIdServiceApisServiceApiId(ctx echo.Context) error {
+       var err error
+       // ------------- Path parameter "apfId" -------------
+       var apfId string
+
+       err = runtime.BindStyledParameterWithLocation("simple", false, "apfId", runtime.ParamLocationPath, ctx.Param("apfId"), &apfId)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter apfId: %s", err))
+       }
+
+       // ------------- Path parameter "serviceApiId" -------------
+       var serviceApiId string
+
+       err = runtime.BindStyledParameterWithLocation("simple", false, "serviceApiId", runtime.ParamLocationPath, ctx.Param("serviceApiId"), &serviceApiId)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter serviceApiId: %s", err))
+       }
+
+       // Invoke the callback with all the unmarshalled arguments
+       err = w.Handler.GetApfIdServiceApisServiceApiId(ctx, apfId, serviceApiId)
+       return err
+}
+
+// ModifyIndAPFPubAPI converts echo context to params.
+func (w *ServerInterfaceWrapper) ModifyIndAPFPubAPI(ctx echo.Context) error {
+       var err error
+       // ------------- Path parameter "apfId" -------------
+       var apfId string
+
+       err = runtime.BindStyledParameterWithLocation("simple", false, "apfId", runtime.ParamLocationPath, ctx.Param("apfId"), &apfId)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter apfId: %s", err))
+       }
+
+       // ------------- Path parameter "serviceApiId" -------------
+       var serviceApiId string
+
+       err = runtime.BindStyledParameterWithLocation("simple", false, "serviceApiId", runtime.ParamLocationPath, ctx.Param("serviceApiId"), &serviceApiId)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter serviceApiId: %s", err))
+       }
+
+       // Invoke the callback with all the unmarshalled arguments
+       err = w.Handler.ModifyIndAPFPubAPI(ctx, apfId, serviceApiId)
+       return err
+}
+
+// PutApfIdServiceApisServiceApiId converts echo context to params.
+func (w *ServerInterfaceWrapper) PutApfIdServiceApisServiceApiId(ctx echo.Context) error {
+       var err error
+       // ------------- Path parameter "apfId" -------------
+       var apfId string
+
+       err = runtime.BindStyledParameterWithLocation("simple", false, "apfId", runtime.ParamLocationPath, ctx.Param("apfId"), &apfId)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter apfId: %s", err))
+       }
+
+       // ------------- Path parameter "serviceApiId" -------------
+       var serviceApiId string
+
+       err = runtime.BindStyledParameterWithLocation("simple", false, "serviceApiId", runtime.ParamLocationPath, ctx.Param("serviceApiId"), &serviceApiId)
+       if err != nil {
+               return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter serviceApiId: %s", err))
+       }
+
+       // Invoke the callback with all the unmarshalled arguments
+       err = w.Handler.PutApfIdServiceApisServiceApiId(ctx, apfId, serviceApiId)
+       return err
+}
+
+// This is a simple interface which specifies echo.Route addition functions which
+// are present on both echo.Echo and echo.Group, since we want to allow using
+// either of them for path registration
+type EchoRouter interface {
+       CONNECT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       DELETE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       GET(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       HEAD(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       OPTIONS(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       PATCH(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       POST(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       PUT(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+       TRACE(path string, h echo.HandlerFunc, m ...echo.MiddlewareFunc) *echo.Route
+}
+
+// RegisterHandlers adds each server route to the EchoRouter.
+func RegisterHandlers(router EchoRouter, si ServerInterface) {
+       RegisterHandlersWithBaseURL(router, si, "")
+}
+
+// Registers handlers, and prepends BaseURL to the paths, so that the paths
+// can be served under a prefix.
+func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL string) {
+
+       wrapper := ServerInterfaceWrapper{
+               Handler: si,
+       }
+
+       router.GET(baseURL+"/:apfId/service-apis", wrapper.GetApfIdServiceApis)
+       router.POST(baseURL+"/:apfId/service-apis", wrapper.PostApfIdServiceApis)
+       router.DELETE(baseURL+"/:apfId/service-apis/:serviceApiId", wrapper.DeleteApfIdServiceApisServiceApiId)
+       router.GET(baseURL+"/:apfId/service-apis/:serviceApiId", wrapper.GetApfIdServiceApisServiceApiId)
+       router.PATCH(baseURL+"/:apfId/service-apis/:serviceApiId", wrapper.ModifyIndAPFPubAPI)
+       router.PUT(baseURL+"/:apfId/service-apis/:serviceApiId", wrapper.PutApfIdServiceApisServiceApiId)
+
+}
+
+// Base64 encoded, gzipped, json marshaled Swagger object
+var swaggerSpec = []string{
+
+       "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",
+}
+
+// GetSwagger returns the content of the embedded swagger specification file
+// or error if failed to decode
+func decodeSpec() ([]byte, error) {
+       zipped, err := base64.StdEncoding.DecodeString(strings.Join(swaggerSpec, ""))
+       if err != nil {
+               return nil, fmt.Errorf("error base64 decoding spec: %s", err)
+       }
+       zr, err := gzip.NewReader(bytes.NewReader(zipped))
+       if err != nil {
+               return nil, fmt.Errorf("error decompressing spec: %s", err)
+       }
+       var buf bytes.Buffer
+       _, err = buf.ReadFrom(zr)
+       if err != nil {
+               return nil, fmt.Errorf("error decompressing spec: %s", err)
+       }
+
+       return buf.Bytes(), nil
+}
+
+var rawSpec = decodeSpecCached()
+
+// a naive cached of a decoded swagger spec
+func decodeSpecCached() func() ([]byte, error) {
+       data, err := decodeSpec()
+       return func() ([]byte, error) {
+               return data, err
+       }
+}
+
+// Constructs a synthetic filesystem for resolving external references when loading openapi specifications.
+func PathToRawSpec(pathToFile string) map[string]func() ([]byte, error) {
+       var res = make(map[string]func() ([]byte, error))
+       if len(pathToFile) > 0 {
+               res[pathToFile] = rawSpec
+       }
+
+       pathPrefix := path.Dir(pathToFile)
+
+       for rawPath, rawFunc := range externalRef0.PathToRawSpec(path.Join(pathPrefix, "CommonData.yaml")) {
+               if _, ok := res[rawPath]; ok {
+                       // it is not possible to compare functions in golang, so always overwrite the old value
+               }
+               res[rawPath] = rawFunc
+       }
+       for rawPath, rawFunc := range externalRef1.PathToRawSpec(path.Join(pathPrefix, "TS29122_CommonData.yaml")) {
+               if _, ok := res[rawPath]; ok {
+                       // it is not possible to compare functions in golang, so always overwrite the old value
+               }
+               res[rawPath] = rawFunc
+       }
+       for rawPath, rawFunc := range externalRef2.PathToRawSpec(path.Join(pathPrefix, "TS29571_CommonData.yaml")) {
+               if _, ok := res[rawPath]; ok {
+                       // it is not possible to compare functions in golang, so always overwrite the old value
+               }
+               res[rawPath] = rawFunc
+       }
+       return res
+}
+
+// GetSwagger returns the Swagger specification corresponding to the generated code
+// in this file. The external references of Swagger specification are resolved.
+// The logic of resolving external references is tightly connected to "import-mapping" feature.
+// Externally referenced files must be embedded in the corresponding golang packages.
+// Urls can be supported but this task was out of the scope.
+func GetSwagger() (swagger *openapi3.T, err error) {
+       var resolvePath = PathToRawSpec("")
+
+       loader := openapi3.NewLoader()
+       loader.IsExternalRefsAllowed = true
+       loader.ReadFromURIFunc = func(loader *openapi3.Loader, url *url.URL) ([]byte, error) {
+               var pathToFile = url.String()
+               pathToFile = path.Clean(pathToFile)
+               getSpec, ok := resolvePath[pathToFile]
+               if !ok {
+                       err1 := fmt.Errorf("path not found: %s", pathToFile)
+                       return nil, err1
+               }
+               return getSpec()
+       }
+       var specData []byte
+       specData, err = rawSpec()
+       if err != nil {
+               return
+       }
+       swagger, err = loader.LoadFromData(specData)
+       if err != nil {
+               return
+       }
+       return
+}
diff --git a/servicemanager/internal/publishserviceapi/publishserviceapi-types.gen.go b/servicemanager/internal/publishserviceapi/publishserviceapi-types.gen.go
new file mode 100644 (file)
index 0000000..20daf89
--- /dev/null
@@ -0,0 +1,270 @@
+// Package publishserviceapi provides primitives to interact with the openapi HTTP API.
+//
+// Code generated by github.com/deepmap/oapi-codegen version v1.10.1 DO NOT EDIT.
+package publishserviceapi
+
+import (
+       externalRef0 "oransc.org/nonrtric/servicemanager/internal/common"
+       externalRef1 "oransc.org/nonrtric/servicemanager/internal/common29122"
+       externalRef2 "oransc.org/nonrtric/servicemanager/internal/common29571"
+)
+
+// Defines values for CommunicationType.
+const (
+       CommunicationTypeREQUESTRESPONSE CommunicationType = "REQUEST_RESPONSE"
+
+       CommunicationTypeSUBSCRIBENOTIFY CommunicationType = "SUBSCRIBE_NOTIFY"
+)
+
+// Defines values for DataFormat.
+const (
+       DataFormatJSON DataFormat = "JSON"
+)
+
+// Defines values for Operation.
+const (
+       OperationDELETE Operation = "DELETE"
+
+       OperationGET Operation = "GET"
+
+       OperationPATCH Operation = "PATCH"
+
+       OperationPOST Operation = "POST"
+
+       OperationPUT Operation = "PUT"
+)
+
+// Defines values for Protocol.
+const (
+       ProtocolHTTP11 Protocol = "HTTP_1_1"
+
+       ProtocolHTTP2 Protocol = "HTTP_2"
+)
+
+// Defines values for SecurityMethod.
+const (
+       SecurityMethodOAUTH SecurityMethod = "OAUTH"
+
+       SecurityMethodPKI SecurityMethod = "PKI"
+
+       SecurityMethodPSK SecurityMethod = "PSK"
+)
+
+// The location information (e.g. civic address, GPS coordinates, data center ID) where the AEF providing the service API is located.
+type AefLocation struct {
+       // Indicates a Civic address.
+       CivicAddr *externalRef0.CivicAddress `json:"civicAddr,omitempty"`
+
+       // Identifies the data center where the AEF providing the service API is located.
+       DcId *string `json:"dcId,omitempty"`
+
+       // Geographic area specified by different shape.
+       GeoArea *externalRef0.GeographicArea `json:"geoArea,omitempty"`
+}
+
+// Represents the AEF profile data.
+type AefProfile struct {
+       // Identifier of the API exposing function
+       AefId string `json:"aefId"`
+
+       // The location information (e.g. civic address, GPS coordinates, data center ID) where the AEF providing the service API is located.
+       AefLocation *AefLocation `json:"aefLocation,omitempty"`
+
+       // Possible values are:
+       // - JSON: JavaScript Object Notation
+       DataFormat *DataFormat `json:"dataFormat,omitempty"`
+
+       // Domain to which API belongs to
+       DomainName *string `json:"domainName,omitempty"`
+
+       // Interface details
+       InterfaceDescriptions *[]InterfaceDescription `json:"interfaceDescriptions,omitempty"`
+
+       // Possible values are:
+       // - HTTP_1_1: HTTP version 1.1
+       // - HTTP_2: HTTP version 2
+       Protocol *Protocol `json:"protocol,omitempty"`
+
+       // Security methods supported by the AEF
+       SecurityMethods *[]SecurityMethod `json:"securityMethods,omitempty"`
+
+       // API version
+       Versions []Version `json:"versions"`
+}
+
+// Possible values are:
+// - REQUEST_RESPONSE: The communication is of the type request-response
+// - SUBSCRIBE_NOTIFY: The communication is of the type subscribe-notify
+type CommunicationType string
+
+// Represents the description of a custom operation.
+type CustomOperation struct {
+       // Possible values are:
+       // - REQUEST_RESPONSE: The communication is of the type request-response
+       // - SUBSCRIBE_NOTIFY: The communication is of the type subscribe-notify
+       CommType CommunicationType `json:"commType"`
+
+       // it is set as {custOpName} part of the URI structure for a custom operation without resource association as defined in clause 5.2.4 of 3GPP TS 29.122.
+       CustOpName string `json:"custOpName"`
+
+       // Text description of the custom operation
+       Description *string `json:"description,omitempty"`
+
+       // Supported HTTP methods for the API resource. Only applicable when the protocol in AefProfile indicates HTTP.
+       Operations *[]Operation `json:"operations,omitempty"`
+}
+
+// Possible values are:
+// - JSON: JavaScript Object Notation
+type DataFormat string
+
+// Represents the description of an API's interface.
+type InterfaceDescription struct {
+       // string identifying a Ipv4 address formatted in the "dotted decimal" notation as defined in IETF RFC 1166.
+       Ipv4Addr *externalRef1.Ipv4Addr `json:"ipv4Addr,omitempty"`
+
+       // string identifying a Ipv6 address formatted according to clause 4 in IETF RFC 5952. The mixed Ipv4 Ipv6 notation according to clause 5 of IETF RFC 5952 shall not be used.
+       Ipv6Addr *externalRef1.Ipv6Addr `json:"ipv6Addr,omitempty"`
+
+       // Unsigned integer with valid values between 0 and 65535.
+       Port *externalRef1.Port `json:"port,omitempty"`
+
+       // Security methods supported by the interface, it take precedence over the security methods provided in AefProfile, for this specific interface.
+       SecurityMethods *[]SecurityMethod `json:"securityMethods,omitempty"`
+}
+
+// Possible values are:
+// - GET: HTTP GET method
+// - POST: HTTP POST method
+// - PUT: HTTP PUT method
+// - PATCH: HTTP PATCH method
+// - DELETE: HTTP DELETE method
+type Operation string
+
+// Possible values are:
+// - HTTP_1_1: HTTP version 1.1
+// - HTTP_2: HTTP version 2
+type Protocol string
+
+// Represents the published API path within the same CAPIF provider domain.
+type PublishedApiPath struct {
+       // A list of CCF identifiers where the service API is already published.
+       CcfIds *[]string `json:"ccfIds,omitempty"`
+}
+
+// Represents the API resource data.
+type Resource struct {
+       // Possible values are:
+       // - REQUEST_RESPONSE: The communication is of the type request-response
+       // - SUBSCRIBE_NOTIFY: The communication is of the type subscribe-notify
+       CommType CommunicationType `json:"commType"`
+
+       // it is set as {custOpName} part of the URI structure for a custom operation associated with a resource as defined in clause 5.2.4 of 3GPP TS 29.122.
+       CustOpName *string `json:"custOpName,omitempty"`
+
+       // Text description of the API resource
+       Description *string `json:"description,omitempty"`
+
+       // Supported HTTP methods for the API resource. Only applicable when the protocol in AefProfile indicates HTTP.
+       Operations *[]Operation `json:"operations,omitempty"`
+
+       // Resource name
+       ResourceName string `json:"resourceName"`
+
+       // Relative URI of the API resource, it is set as {apiSpecificSuffixes} part of the URI structure as defined in clause 5.2.4 of 3GPP TS 29.122.
+       Uri string `json:"uri"`
+}
+
+// Possible values are:
+// - PSK: Security method 1 (Using TLS-PSK) as described in 3GPP TS 33.122
+// - PKI: Security method 2 (Using PKI) as described in 3GPP TS 33.122
+// - OAUTH: Security method 3 (TLS with OAuth token) as described in 3GPP TS 33.122
+type SecurityMethod string
+
+// Represents the description of a service API as published by the APF.
+type ServiceAPIDescription struct {
+       // AEF profile information, which includes the exposed API details (e.g. protocol).
+       AefProfiles *[]AefProfile `json:"aefProfiles,omitempty"`
+
+       // API identifier assigned by the CAPIF core function to the published service API. Shall not be present in the HTTP POST request from the API publishing function to the CAPIF core function. Shall be present in the HTTP POST response from the CAPIF core function to the API publishing function and in the HTTP GET response from the CAPIF core function to the API invoker (discovery API).
+       ApiId *string `json:"apiId,omitempty"`
+
+       // API name, it is set as {apiName} part of the URI structure as defined in clause 5.2.4 of 3GPP TS 29.122.
+       ApiName string `json:"apiName"`
+
+       // A string used to indicate the features supported by an API that is used as defined in clause  6.6 in 3GPP TS 29.500. The string shall contain a bitmask indicating supported features in  hexadecimal representation Each character in the string shall take a value of "0" to "9",  "a" to "f" or "A" to "F" and shall represent the support of 4 features as described in  table 5.2.2-3. The most significant character representing the highest-numbered features shall  appear first in the string, and the character representing features 1 to 4 shall appear last  in the string. The list of features and their numbering (starting with 1) are defined  separately for each API. If the string contains a lower number of characters than there are  defined features for an API, all features that would be represented by characters that are not  present in the string are not supported.
+       ApiSuppFeats *externalRef2.SupportedFeatures `json:"apiSuppFeats,omitempty"`
+
+       // CAPIF core function identifier.
+       CcfId *string `json:"ccfId,omitempty"`
+
+       // Text description of the API
+       Description *string `json:"description,omitempty"`
+
+       // Represents the published API path within the same CAPIF provider domain.
+       PubApiPath         *PublishedApiPath `json:"pubApiPath,omitempty"`
+       ServiceAPICategory *string           `json:"serviceAPICategory,omitempty"`
+
+       // Indicates whether the service API and/or the service API category can be shared to the list of CAPIF provider domains.
+       ShareableInfo *ShareableInformation `json:"shareableInfo,omitempty"`
+
+       // A string used to indicate the features supported by an API that is used as defined in clause  6.6 in 3GPP TS 29.500. The string shall contain a bitmask indicating supported features in  hexadecimal representation Each character in the string shall take a value of "0" to "9",  "a" to "f" or "A" to "F" and shall represent the support of 4 features as described in  table 5.2.2-3. The most significant character representing the highest-numbered features shall  appear first in the string, and the character representing features 1 to 4 shall appear last  in the string. The list of features and their numbering (starting with 1) are defined  separately for each API. If the string contains a lower number of characters than there are  defined features for an API, all features that would be represented by characters that are not  present in the string are not supported.
+       SupportedFeatures *externalRef2.SupportedFeatures `json:"supportedFeatures,omitempty"`
+}
+
+// Represents the parameters to request the modification of an APF published API resource.
+type ServiceAPIDescriptionPatch struct {
+       AefProfiles *[]AefProfile `json:"aefProfiles,omitempty"`
+
+       // A string used to indicate the features supported by an API that is used as defined in clause  6.6 in 3GPP TS 29.500. The string shall contain a bitmask indicating supported features in  hexadecimal representation Each character in the string shall take a value of "0" to "9",  "a" to "f" or "A" to "F" and shall represent the support of 4 features as described in  table 5.2.2-3. The most significant character representing the highest-numbered features shall  appear first in the string, and the character representing features 1 to 4 shall appear last  in the string. The list of features and their numbering (starting with 1) are defined  separately for each API. If the string contains a lower number of characters than there are  defined features for an API, all features that would be represented by characters that are not  present in the string are not supported.
+       ApiSuppFeats *externalRef2.SupportedFeatures `json:"apiSuppFeats,omitempty"`
+
+       // CAPIF core function identifier.
+       CcfId *string `json:"ccfId,omitempty"`
+
+       // Text description of the API
+       Description *string `json:"description,omitempty"`
+
+       // Represents the published API path within the same CAPIF provider domain.
+       PubApiPath         *PublishedApiPath `json:"pubApiPath,omitempty"`
+       ServiceAPICategory *string           `json:"serviceAPICategory,omitempty"`
+
+       // Indicates whether the service API and/or the service API category can be shared to the list of CAPIF provider domains.
+       ShareableInfo *ShareableInformation `json:"shareableInfo,omitempty"`
+}
+
+// Indicates whether the service API and/or the service API category can be shared to the list of CAPIF provider domains.
+type ShareableInformation struct {
+       // List of CAPIF provider domains to which the service API information to be shared.
+       CapifProvDoms *[]string `json:"capifProvDoms,omitempty"`
+
+       // Set to "true" indicates that the service API and/or the service API category can be shared to the list of CAPIF provider domain information. Otherwise set to "false".
+       IsShareable bool `json:"isShareable"`
+}
+
+// Represents the API version information.
+type Version struct {
+       // API major version in URI (e.g. v1)
+       ApiVersion string `json:"apiVersion"`
+
+       // Custom operations without resource association.
+       CustOperations *[]CustomOperation `json:"custOperations,omitempty"`
+
+       // string with format "date-time" as defined in OpenAPI.
+       Expiry *externalRef1.DateTime `json:"expiry,omitempty"`
+
+       // Resources supported by the API.
+       Resources *[]Resource `json:"resources,omitempty"`
+}
+
+// PostApfIdServiceApisJSONBody defines parameters for PostApfIdServiceApis.
+type PostApfIdServiceApisJSONBody ServiceAPIDescription
+
+// PutApfIdServiceApisServiceApiIdJSONBody defines parameters for PutApfIdServiceApisServiceApiId.
+type PutApfIdServiceApisServiceApiIdJSONBody ServiceAPIDescription
+
+// PostApfIdServiceApisJSONRequestBody defines body for PostApfIdServiceApis for application/json ContentType.
+type PostApfIdServiceApisJSONRequestBody PostApfIdServiceApisJSONBody
+
+// PutApfIdServiceApisServiceApiIdJSONRequestBody defines body for PutApfIdServiceApisServiceApiId for application/json ContentType.
+type PutApfIdServiceApisServiceApiIdJSONRequestBody PutApfIdServiceApisServiceApiIdJSONBody
diff --git a/servicemanager/internal/publishserviceapi/typeupdate.go b/servicemanager/internal/publishserviceapi/typeupdate.go
new file mode 100644 (file)
index 0000000..fe681f9
--- /dev/null
@@ -0,0 +1,351 @@
+// -
+//   ========================LICENSE_START=================================
+//   O-RAN-SC
+//   %%
+//   Copyright (C) 2023-2024: OpenInfra Foundation Europe
+//   %%
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//        http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+//   ========================LICENSE_END===================================
+//
+
+package publishserviceapi
+
+import (
+       "errors"
+       "fmt"
+       "net/http"
+       "net/url"
+       "strings"
+
+       resty "github.com/go-resty/resty/v2"
+       log "github.com/sirupsen/logrus"
+
+       common29122 "oransc.org/nonrtric/servicemanager/internal/common29122"
+)
+
+func (sd *ServiceAPIDescription) PrepareNewService() {
+       apiName := "api_id_" + strings.ReplaceAll(sd.ApiName, " ", "_")
+       sd.ApiId = &apiName
+}
+
+func (sd *ServiceAPIDescription) RegisterKong(kongDomain string, kongProtocol string, kongIPv4 common29122.Ipv4Addr, kongDataPlanePort common29122.Port, kongControlPlanePort common29122.Port) (int, error) {
+       log.Trace("entering RegisterKong")
+       var (
+               statusCode int
+               err        error
+       )
+       kongControlPlaneURL := fmt.Sprintf("%s://%s:%d", kongProtocol, kongIPv4, kongControlPlanePort)
+
+       statusCode, err = sd.createKongRoutes(kongControlPlaneURL)
+       if (err != nil) || (statusCode != http.StatusCreated) {
+               return statusCode, err
+       }
+
+       sd.updateInterfaceDescription(kongIPv4, kongDataPlanePort, kongDomain)
+
+       log.Trace("exiting from RegisterKong")
+       return statusCode, nil
+}
+
+func (sd *ServiceAPIDescription) createKongRoutes(kongControlPlaneURL string) (int, error) {
+       log.Trace("entering createKongRoutes")
+       var (
+               statusCode int
+               err        error
+       )
+
+       client := resty.New()
+
+       profiles := *sd.AefProfiles
+       for _, profile := range profiles {
+               log.Debugf("createKongRoutes, AefId %s", profile.AefId)
+               for _, version := range profile.Versions {
+                       log.Debugf("createKongRoutes, apiVersion \"%s\"", version.ApiVersion)
+                       for _, resource := range *version.Resources {
+                               statusCode, err = sd.createKongRoute(kongControlPlaneURL, client, resource, profile.AefId, version.ApiVersion)
+                               if (err != nil) || (statusCode != http.StatusCreated) {
+                                       return statusCode, err
+                               }
+                       }
+               }
+       }
+       return statusCode, nil
+}
+
+func (sd *ServiceAPIDescription) createKongRoute(kongControlPlaneURL string, client *resty.Client, resource Resource, aefId string, apiVersion string) (int, error) {
+       log.Trace("entering createKongRoute")
+       uri := resource.Uri
+
+       if apiVersion != "" {
+               if apiVersion[0] != '/' {
+                       apiVersion = "/" + apiVersion
+               }
+               if apiVersion[len(apiVersion)-1] != '/' && resource.Uri[0] != '/' {
+                       apiVersion = apiVersion + "/"
+               }
+               uri = apiVersion + resource.Uri
+       }
+
+       log.Debugf("createKongRoute, uri %s", uri)
+
+       serviceName := *sd.ApiId + "_" + resource.ResourceName
+       log.Debugf("createKongRoute, serviceName %s", serviceName)
+       log.Debugf("createKongRoute, aefId %s", aefId)
+
+       statusCode, err := sd.createKongService(kongControlPlaneURL, serviceName, uri, aefId)
+       if (err != nil) || (statusCode != http.StatusCreated) {
+               return statusCode, err
+       }
+
+       routeName := serviceName
+       kongRoutesURL := kongControlPlaneURL + "/services/" + serviceName + "/routes"
+
+       // Define the route information for Kong
+       kongRouteInfo := map[string]interface{}{
+               "name":       routeName,
+               "paths":      []string{uri},
+               "methods":    resource.Operations,
+               "tags":       []string{aefId},
+               "strip_path": true,
+       }
+
+       // Make the POST request to create the Kong service
+       resp, err := client.R().
+               SetHeader("Content-Type", "application/json").
+               SetBody(kongRouteInfo).
+               Post(kongRoutesURL)
+
+       // Check for errors in the request
+       if err != nil {
+               log.Debugf("createKongRoute POST Error: %v", err)
+               return resp.StatusCode(), err
+       }
+
+       // Check the response status code
+       if resp.StatusCode() == http.StatusCreated {
+               log.Infof("kong route %s created successfully", routeName)
+       } else {
+               err = fmt.Errorf("the Kong service already exists. Status code: %d", resp.StatusCode())
+               log.Error(err.Error())
+               log.Errorf("response body: %s", resp.Body())
+               return resp.StatusCode(), err
+       }
+
+       return resp.StatusCode(), nil
+}
+
+func (sd *ServiceAPIDescription) createKongService(kongControlPlaneURL string, kongServiceName string, kongServiceUri string, aefId string) (int, error) {
+       log.Tracef("entering createKongService")
+       log.Tracef("createKongService, kongServiceName %s", kongServiceName)
+
+       // Define the service information for Kong
+       firstAEFProfileIpv4Addr, firstAEFProfilePort, err := sd.findFirstAEFProfile()
+       if err != nil {
+               return http.StatusBadRequest, err
+       }
+
+       kongControlPlaneURLParsed, err := url.Parse(kongControlPlaneURL)
+       if err != nil {
+               return http.StatusInternalServerError, err
+       }
+       log.Debugf("kongControlPlaneURL %s", kongControlPlaneURL)
+       log.Debugf("kongControlPlaneURLParsed.Scheme %s", kongControlPlaneURLParsed.Scheme)
+
+       kongServiceInfo := map[string]interface{}{
+               "host":     firstAEFProfileIpv4Addr,
+               "name":     kongServiceName,
+               "port":     firstAEFProfilePort,
+               "protocol": kongControlPlaneURLParsed.Scheme,
+               "path":     kongServiceUri,
+               "tags":     []string{aefId},
+       }
+
+       // Kong admin API endpoint for creating a service
+       kongServicesURL := kongControlPlaneURL + "/services"
+
+       // Create a new Resty client
+       client := resty.New()
+
+       // Make the POST request to create the Kong service
+       resp, err := client.R().
+               SetHeader("Content-Type", "application/json").
+               SetBody(kongServiceInfo).
+               Post(kongServicesURL)
+
+       // Check for errors in the request
+       if err != nil {
+               log.Errorf("create Kong Service Request Error: %v", err)
+               return http.StatusInternalServerError, err
+       }
+
+       // Check the response status code
+       statusCode := resp.StatusCode()
+       if statusCode == http.StatusCreated {
+               log.Infof("kong service %s created successfully", kongServiceName)
+       } else if resp.StatusCode() == http.StatusConflict {
+               log.Errorf("kong service already exists. Status code: %d", resp.StatusCode())
+               err = fmt.Errorf("service with identical apiName is already published") // for compatibilty with Capif error message on a duplicate service
+               statusCode = http.StatusForbidden // for compatibilty with the spec, TS29222_CAPIF_Publish_Service_API
+       } else {
+               err = fmt.Errorf("error creating Kong service. Status code: %d", resp.StatusCode())
+       }
+       if err != nil {
+               log.Errorf(err.Error())
+               log.Errorf("response body: %s", resp.Body())
+       }
+
+       return statusCode, err
+}
+
+func (sd *ServiceAPIDescription) findFirstAEFProfile() (common29122.Ipv4Addr, common29122.Port, error) {
+       log.Tracef("entering findFirstAEFProfile")
+       var aefProfile AefProfile
+       if *sd.AefProfiles != nil {
+               aefProfile = (*sd.AefProfiles)[0]
+       }
+       if (*sd.AefProfiles == nil) || (aefProfile.InterfaceDescriptions == nil) {
+               err := errors.New("cannot read interfaceDescription")
+               log.Errorf(err.Error())
+               return "", common29122.Port(0), err
+       }
+
+       interfaceDescription := (*aefProfile.InterfaceDescriptions)[0]
+       firstIpv4Addr := *interfaceDescription.Ipv4Addr
+       firstPort := *interfaceDescription.Port
+
+       log.Debugf("findFirstAEFProfile firstIpv4Addr %s firstPort %d", firstIpv4Addr, firstPort)
+
+       return firstIpv4Addr, firstPort, nil
+}
+
+// Update our exposures to point to Kong by replacing in incoming interface description with Kong interface descriptions.
+func (sd *ServiceAPIDescription) updateInterfaceDescription(kongIPv4 common29122.Ipv4Addr, kongDataPlanePort common29122.Port, kongDomain string) {
+       log.Trace("updating InterfaceDescriptions")
+       interfaceDesc := InterfaceDescription{
+               Ipv4Addr: &kongIPv4,
+               Port:     &kongDataPlanePort,
+       }
+       interfaceDescs := []InterfaceDescription{interfaceDesc}
+
+       profiles := *sd.AefProfiles
+       for i, profile := range profiles {
+               profile.DomainName = &kongDomain
+               profile.InterfaceDescriptions = &interfaceDescs
+               profiles[i] = profile
+       }
+}
+
+func (sd *ServiceAPIDescription) UnregisterKong(kongDomain string, kongProtocol string, kongIPv4 common29122.Ipv4Addr, kongDataPlanePort common29122.Port, kongControlPlanePort common29122.Port) (int, error) {
+       log.Trace("entering UnregisterKong")
+
+       var (
+               statusCode int
+               err        error
+       )
+       kongControlPlaneURL := fmt.Sprintf("%s://%s:%d", kongProtocol, kongIPv4, kongControlPlanePort)
+
+       statusCode, err = sd.deleteKongRoutes(kongControlPlaneURL)
+       if (err != nil) || (statusCode != http.StatusNoContent) {
+               return statusCode, err
+       }
+
+       log.Trace("exiting from UnregisterKong")
+       return statusCode, nil
+}
+
+func (sd *ServiceAPIDescription) deleteKongRoutes(kongControlPlaneURL string) (int, error) {
+       log.Trace("entering deleteKongRoutes")
+
+       var (
+               statusCode int
+               err        error
+       )
+
+       client := resty.New()
+
+       profiles := *sd.AefProfiles
+       for _, profile := range profiles {
+               log.Debugf("deleteKongRoutes, AefId %s", profile.AefId)
+               for _, version := range profile.Versions {
+                       log.Debugf("deleteKongRoutes, apiVersion \"%s\"", version.ApiVersion)
+                       for _, resource := range *version.Resources {
+                               statusCode, err = sd.deleteKongRoute(kongControlPlaneURL, client, resource, profile.AefId, version.ApiVersion)
+                               if (err != nil) || (statusCode != http.StatusNoContent) {
+                                       return statusCode, err
+                               }
+                       }
+               }
+       }
+       return statusCode, nil
+}
+
+func (sd *ServiceAPIDescription) deleteKongRoute(kongControlPlaneURL string, client *resty.Client, resource Resource, aefId string, apiVersion string) (int, error) {
+       log.Trace("entering deleteKongRoute")
+       routeName := *sd.ApiId + "_" + resource.ResourceName
+       kongRoutesURL := kongControlPlaneURL + "/routes/" + routeName + "?tags=" + aefId
+       log.Debugf("deleteKongRoute, routeName %s, tag %s", routeName, aefId)
+
+       // Make the DELETE request to delete the Kong route
+       resp, err := client.R().Delete(kongRoutesURL)
+
+       // Check for errors in the request
+       if err != nil {
+               log.Errorf("error on Kong route delete: %v", err)
+               return resp.StatusCode(), err
+       }
+
+       // Check the response status code
+       if resp.StatusCode() == http.StatusNoContent {
+               log.Infof("kong route %s deleted successfully", routeName)
+       } else {
+               log.Errorf("error deleting Kong route. Status code: %d", resp.StatusCode())
+               log.Errorf("response body: %s", resp.Body())
+               return resp.StatusCode(), err
+       }
+
+       statusCode, err := sd.deleteKongService(kongControlPlaneURL, routeName, aefId)
+       if (err != nil) || (statusCode != http.StatusNoContent) {
+               return statusCode, err
+       }
+       return statusCode, err
+}
+
+func (sd *ServiceAPIDescription) deleteKongService(kongControlPlaneURL string, serviceName string, aefId string) (int, error) {
+       log.Trace("entering deleteKongService")
+       // Define the service information for Kong
+       // Kong admin API endpoint for deleting a service
+       kongServicesURL := kongControlPlaneURL + "/services/" + serviceName + "?tags=" + aefId
+
+       // Create a new Resty client
+       client := resty.New()
+
+       // Make the DELETE request to delete the Kong service
+       resp, err := client.R().
+               SetHeader("Content-Type", "application/json").
+               Delete(kongServicesURL)
+
+       // Check for errors in the request
+       if err != nil {
+               log.Errorf("delete kong service request: %v", err)
+               return http.StatusInternalServerError, err
+       }
+
+       // Check the response status code
+       if resp.StatusCode() == http.StatusNoContent {
+               log.Infof("kong service %s deleted successfully", serviceName)
+       } else {
+               log.Errorf("deleting Kong service, status code: %d", resp.StatusCode())
+               log.Errorf("response body: %s", resp.Body())
+       }
+       return resp.StatusCode(), nil
+}
diff --git a/servicemanager/main.go b/servicemanager/main.go
new file mode 100644 (file)
index 0000000..5d0cc55
--- /dev/null
@@ -0,0 +1,180 @@
+// -
+//   ========================LICENSE_START=================================
+//   O-RAN-SC
+//   %%
+//   Copyright (C) 2023-2024: OpenInfra Foundation Europe
+//   %%
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//        http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+//   ========================LICENSE_END===================================
+//
+
+package main
+
+import (
+       "fmt"
+       "net/http"
+
+       "github.com/getkin/kin-openapi/openapi3"
+
+       "github.com/deepmap/oapi-codegen/pkg/middleware"
+       echo "github.com/labstack/echo/v4"
+       echomiddleware "github.com/labstack/echo/v4/middleware"
+       log "github.com/sirupsen/logrus"
+
+       "oransc.org/nonrtric/servicemanager/internal/common29122"
+       "oransc.org/nonrtric/servicemanager/internal/envreader"
+
+       "oransc.org/nonrtric/servicemanager/internal/discoverserviceapi"
+       "oransc.org/nonrtric/servicemanager/internal/invokermanagementapi"
+       "oransc.org/nonrtric/servicemanager/internal/providermanagementapi"
+       "oransc.org/nonrtric/servicemanager/internal/publishserviceapi"
+
+       "oransc.org/nonrtric/servicemanager/internal/discoverservice"
+       "oransc.org/nonrtric/servicemanager/internal/invokermanagement"
+       "oransc.org/nonrtric/servicemanager/internal/providermanagement"
+       "oransc.org/nonrtric/servicemanager/internal/publishservice"
+)
+
+func main() {
+       myEnv, myPorts, err := envreader.ReadDotEnv()
+       if err != nil {
+               log.Fatal("error loading environment file")
+               return
+       }
+
+       e, err := getEcho(myEnv, myPorts)
+       if err != nil {
+               log.Fatal("getEcho fatal error")
+               return
+       }
+
+       port := myPorts["SERVICE_MANAGER_PORT"]
+
+       go startWebServer(e, port)
+       log.Info("server started and listening on port: ", port)
+       keepServerAlive()
+}
+
+func getEcho(myEnv map[string]string, myPorts map[string]int) (*echo.Echo, error) {
+       e := echo.New()
+       // Log all requests
+       e.Use(echomiddleware.Logger())
+
+       capifProtocol := myEnv["CAPIF_PROTOCOL"]
+       capifIPv4 := common29122.Ipv4Addr(myEnv["CAPIF_IPV4"])
+       capifPort := common29122.Port(myPorts["CAPIF_PORT"])
+       kongDomain := myEnv["KONG_DOMAIN"]
+       kongProtocol := myEnv["KONG_PROTOCOL"]
+       kongIPv4 := common29122.Ipv4Addr(myEnv["KONG_IPV4"])
+       kongDataPlanePort := common29122.Port(myPorts["KONG_DATA_PLANE_PORT"])
+       kongControlPlanePort := common29122.Port(myPorts["KONG_CONTROL_PLANE_PORT"])
+
+       var group *echo.Group
+
+       // Register ProviderManagement
+       providerManagerSwagger, err := providermanagementapi.GetSwagger()
+       if err != nil {
+               log.Fatalf("error loading ProviderManagement swagger spec\n: %s", err)
+               return nil, err
+       }
+       providerManagerSwagger.Servers = nil
+       providerManager := providermanagement.NewProviderManager(capifProtocol, capifIPv4, capifPort)
+       group = e.Group("/api-provider-management/v1")
+       group.Use(middleware.OapiRequestValidator(providerManagerSwagger))
+       providermanagementapi.RegisterHandlersWithBaseURL(e, providerManager, "/api-provider-management/v1")
+
+       // Register PublishService
+       publishServiceSwagger, err := publishserviceapi.GetSwagger()
+       if err != nil {
+               log.Fatalf("error loading PublishService swagger spec\n: %s", err)
+               return nil, err
+       }
+       publishServiceSwagger.Servers = nil
+       publishService := publishservice.NewPublishService(kongDomain, kongProtocol, kongIPv4, kongDataPlanePort, kongControlPlanePort, capifProtocol, capifIPv4, capifPort)
+
+       group = e.Group("/published-apis/v1")
+       group.Use(middleware.OapiRequestValidator(publishServiceSwagger))
+       publishserviceapi.RegisterHandlersWithBaseURL(e, publishService, "/published-apis/v1")
+
+       // Register InvokerManagement
+       invokerManagerSwagger, err := invokermanagementapi.GetSwagger()
+       if err != nil {
+               log.Fatalf("error loading InvokerManagement swagger spec\n: %s", err)
+               return nil, err
+       }
+       invokerManagerSwagger.Servers = nil
+       invokerManager := invokermanagement.NewInvokerManager(capifProtocol, capifIPv4, capifPort)
+       group = e.Group("/api-invoker-management/v1")
+       group.Use(middleware.OapiRequestValidator(invokerManagerSwagger))
+       invokermanagementapi.RegisterHandlersWithBaseURL(e, invokerManager, "/api-invoker-management/v1")
+
+       // Register DiscoverService
+       discoverServiceSwagger, err := discoverserviceapi.GetSwagger()
+       if err != nil {
+               log.Fatalf("error loading DiscoverService swagger spec\n: %s", err)
+               return nil, err
+       }
+
+       discoverServiceSwagger.Servers = nil
+       discoverService := discoverservice.NewDiscoverService(capifProtocol, capifIPv4, capifPort)
+
+       group = e.Group("/service-apis/v1")
+       group.Use(middleware.OapiRequestValidator(discoverServiceSwagger))
+       discoverserviceapi.RegisterHandlersWithBaseURL(e, discoverService, "/service-apis/v1")
+
+       e.GET("/", hello)
+       e.GET("/swagger/:apiName", getSwagger)
+
+       return e, err
+}
+
+func startWebServer(e *echo.Echo, port int) {
+       e.Logger.Fatal(e.Start(fmt.Sprintf("0.0.0.0:%d", port)))
+}
+
+func keepServerAlive() {
+       forever := make(chan int)
+       <-forever
+}
+
+func hello(c echo.Context) error {
+       return c.String(http.StatusOK, "Hello, World!")
+}
+
+func getSwagger(c echo.Context) error {
+       var swagger *openapi3.T
+       var err error
+       switch api := c.Param("apiName"); api {
+       case "provider":
+               swagger, err = providermanagementapi.GetSwagger()
+       case "publish":
+               swagger, err = publishserviceapi.GetSwagger()
+       case "invoker":
+               swagger, err = invokermanagementapi.GetSwagger()
+       case "discover":
+               swagger, err = discoverserviceapi.GetSwagger()
+       default:
+               return c.JSON(http.StatusBadRequest, getProblemDetails("Invalid API name "+api, http.StatusBadRequest))
+       }
+       if err != nil {
+               return c.JSON(http.StatusInternalServerError, getProblemDetails("Unable to get swagger for API", http.StatusInternalServerError))
+       }
+       return c.JSON(http.StatusOK, swagger)
+}
+
+func getProblemDetails(cause string, status int) common29122.ProblemDetails {
+       return common29122.ProblemDetails{
+               Cause:  &cause,
+               Status: &status,
+       }
+}
diff --git a/servicemanager/main_test.go b/servicemanager/main_test.go
new file mode 100644 (file)
index 0000000..0f6e4cd
--- /dev/null
@@ -0,0 +1,186 @@
+// -
+//   ========================LICENSE_START=================================
+//   O-RAN-SC
+//   %%
+//   Copyright (C) 2023-2024: OpenInfra Foundation Europe
+//   %%
+//   Licensed under the Apache License, Version 2.0 (the "License");
+//   you may not use this file except in compliance with the License.
+//   You may obtain a copy of the License at
+//
+//        http://www.apache.org/licenses/LICENSE-2.0
+//
+//   Unless required by applicable law or agreed to in writing, software
+//   distributed under the License is distributed on an "AS IS" BASIS,
+//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//   See the License for the specific language governing permissions and
+//   limitations under the License.
+//   ========================LICENSE_END===================================
+//
+
+package main
+
+import (
+       "net/http"
+       "os"
+       "testing"
+
+       "github.com/deepmap/oapi-codegen/pkg/testutil"
+       "github.com/getkin/kin-openapi/openapi3"
+       "github.com/labstack/echo/v4"
+       "github.com/stretchr/testify/assert"
+       log "github.com/sirupsen/logrus"
+
+       "oransc.org/nonrtric/servicemanager/internal/common29122"
+       "oransc.org/nonrtric/servicemanager/internal/envreader"
+)
+
+var e *echo.Echo
+var myPorts map [string]int
+
+func TestMain(m *testing.M) {
+    // Init code to run before tests
+       myEnv, myPorts, err := envreader.ReadDotEnv()
+       if err != nil {
+               log.Fatal("error loading environment file")
+               return
+       }
+
+       e, err = getEcho(myEnv, myPorts)
+       if err != nil {
+               log.Fatal("getEcho fatal error")
+               return
+       }
+    
+    // Run tests
+    exitVal := m.Run()
+    
+    // Finalization code to run after tests
+
+    // Exit with exit value from tests
+    os.Exit(exitVal)
+}
+
+
+func Test_routing(t *testing.T) {
+       type args struct {
+               url          string
+               returnStatus int
+               method       string
+       }
+       tests := []struct {
+               name string
+               args args
+       }{
+               {
+                       name: "Default path",
+                       args: args{
+                               url:          "/",
+                               returnStatus: http.StatusOK,
+                               method:       "GET",
+                       },
+               },
+               {
+                       name: "Provider path",
+                       args: args{
+                               url:          "/api-provider-management/v1/registrations/provider",
+                               returnStatus: http.StatusNoContent,
+                               method:       "DELETE",
+                       },
+               },
+               {
+                       name: "Publish path",
+                       args: args{
+                               url:          "/published-apis/v1/apfId/service-apis/serviceId",
+                               returnStatus: http.StatusNotFound,
+                               method:       "GET",
+                       },
+               },
+               {
+                       name: "Discover path",
+                       args: args{
+                               url:          "/service-apis/v1/allServiceAPIs?api-invoker-id=api_invoker_id",
+                               returnStatus: http.StatusNotFound,
+                               method:       "GET",
+                       },
+               },
+               {
+                       name: "Invoker path",
+                       args: args{
+                               url:          "/api-invoker-management/v1/onboardedInvokers/invoker",
+                               returnStatus: http.StatusNoContent,
+                               method:       "DELETE",
+                       },
+               },
+       }
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       var result *testutil.CompletedRequest
+                       if tt.args.method == "GET" {
+                               result = testutil.NewRequest().Get(tt.args.url).Go(t, e)
+                       } else if tt.args.method == "DELETE" {
+                               result = testutil.NewRequest().Delete(tt.args.url).Go(t, e)
+                       }
+
+                       assert.Equal(t, tt.args.returnStatus, result.Code(), tt.name)
+               })
+       }
+}
+
+func TestGetSwagger(t *testing.T) {
+       type args struct {
+               apiPath string
+               apiName string
+       }
+       tests := []struct {
+               name string
+               args args
+       }{
+               {
+                       name: "Provider api",
+                       args: args{
+                               apiPath: "provider",
+                               apiName: "Provider",
+                       },
+               },
+               {
+                       name: "Publish api",
+                       args: args{
+                               apiPath: "publish",
+                               apiName: "Publish",
+                       },
+               },
+               {
+                       name: "Invoker api",
+                       args: args{
+                               apiPath: "invoker",
+                               apiName: "Invoker",
+                       },
+               },
+               {
+                       name: "Discover api",
+                       args: args{
+                               apiPath: "discover",
+                               apiName: "Discover",
+                       },
+               },
+       }
+       for _, tt := range tests {
+               t.Run(tt.name, func(t *testing.T) {
+                       result := testutil.NewRequest().Get("/swagger/"+tt.args.apiPath).Go(t, e)
+                       assert.Equal(t, http.StatusOK, result.Code())
+                       var swaggerResponse openapi3.T
+                       err := result.UnmarshalJsonToObject(&swaggerResponse)
+                       assert.Nil(t, err)
+                       assert.Contains(t, swaggerResponse.Info.Title, tt.args.apiName)
+               })
+       }
+       invalidApi := "foobar"
+       result := testutil.NewRequest().Get("/swagger/"+invalidApi).Go(t, e)
+       assert.Equal(t, http.StatusBadRequest, result.Code())
+       var errorResponse common29122.ProblemDetails
+       err := result.UnmarshalJsonToObject(&errorResponse)
+       assert.Nil(t, err)
+       assert.Contains(t, *errorResponse.Cause, "Invalid API")
+       assert.Contains(t, *errorResponse.Cause, invalidApi)
+}
\ No newline at end of file