Note: in addition to the changes introduced by this PR, the diff includes unreleased changes living in main.
### 🔎 Changes to `grafana-foundation-sdk@next+cog-v0.0.x`
```patch
diff --git a/.config/ci/php/phpstan.neon b/.config/ci/php/phpstan.neon
new file mode 100644
index 0000000..4dd83a7
--- /dev/null
+++ b/.config/ci/php/phpstan.neon
@@ -0,0 +1,9 @@
+parameters:
+ level: 9 # https://phpstan.org/user-guide/rule-levels
+ paths:
+ - ../../../php/src
+
+ ignoreErrors:
+ - identifier: identical.alwaysFalse # not a big deal, duplicated enum values come from the schema
+ paths:
+ - ../../../php/src/Common/ScaleDirection.php
diff --git a/.config/ci/php/psalm.xml b/.config/ci/php/psalm.xml
new file mode 100644
index 0000000..3600652
--- /dev/null
+++ b/.config/ci/php/psalm.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/.github/workflows/php-ci.yaml b/.github/workflows/php-ci.yaml
new file mode 100644
index 0000000..4cd62b2
--- /dev/null
+++ b/.github/workflows/php-ci.yaml
@@ -0,0 +1,39 @@
+# Code generated - EDITING IS FUTILE. DO NOT EDIT.
+
+name: PHP CI
+on:
+ pull_request: ~
+
+env:
+ PHP_VERSION: '8.3'
+
+jobs:
+ php:
+ name: PHP
+ runs-on: ubuntu-latest
+
+ defaults:
+ run:
+ shell: bash
+
+ steps:
+ - uses: actions/checkout@v4
+
+ - name: Setup PHP ${{ env.PHP_VERSION }}
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: ${{ env.PHP_VERSION }}
+ tools: phpstan, psalm
+ extensions: none, curl, ctype, dom, mbstring, opcache, simplexml, tokenizer
+ ini-values: opcache.enable_cli=1
+
+ - name: Install dependencies
+ run: |
+ cd php
+ composer install
+
+ - name: Lint generated PHP code with phpstan
+ run: phpstan analyze --memory-limit 256M -c .config/ci/php/phpstan.neon
+
+ - name: Lint generated PHP code with psalm
+ run: psalm -c .config/ci/php/psalm.xml php
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..2550723
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,21 @@
+{
+ "name": "grafana/foundation-sdk",
+ "type": "library",
+ "license": "Apache-2.0",
+ "homepage": "https://github.com/grafana/grafana-foundation-sdk",
+ "description": "A set of tools, types and libraries for building and manipulating Grafana objects.",
+ "keywords": [
+ "observability",
+ "sdk",
+ "grafana",
+ "logs",
+ "traces",
+ "metrics"
+ ],
+ "autoload": {
+ "psr-4": {
+ "Grafana\\Foundation\\": "php/src/"
+ }
+ },
+ "require": {}
+}
diff --git a/go/alerting/query_builder_gen.go b/go/alerting/query_builder_gen.go
index 94b524f..e2d3513 100644
--- a/go/alerting/query_builder_gen.go
+++ b/go/alerting/query_builder_gen.go
@@ -75,9 +75,6 @@ func (builder *QueryBuilder) RelativeTimeRange(from Duration, to Duration) *Quer
builder.internal.RelativeTimeRange = &RelativeTimeRange{}
}
builder.internal.RelativeTimeRange.From = &from
- if builder.internal.RelativeTimeRange == nil {
- builder.internal.RelativeTimeRange = &RelativeTimeRange{}
- }
builder.internal.RelativeTimeRange.To = &to
return builder
diff --git a/go/dashboard/dashboard_builder_gen.go b/go/dashboard/dashboard_builder_gen.go
index cebab62..284a7ae 100644
--- a/go/dashboard/dashboard_builder_gen.go
+++ b/go/dashboard/dashboard_builder_gen.go
@@ -137,12 +137,6 @@ func (builder *DashboardBuilder) Time(from string, to string) *DashboardBuilder
}{}
}
builder.internal.Time.From = from
- if builder.internal.Time == nil {
- builder.internal.Time = &struct {
- From string `json:"from"`
- To string `json:"to"`
- }{}
- }
builder.internal.Time.To = to
return builder
diff --git a/jsonschema/azuremonitor.jsonschema.json b/jsonschema/azuremonitor.jsonschema.json
index 983c6d1..7a9da51 100644
--- a/jsonschema/azuremonitor.jsonschema.json
+++ b/jsonschema/azuremonitor.jsonschema.json
@@ -1,5 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
+ "$ref": "#/definitions/AzureMonitorQuery",
"definitions": {
"AzureMonitorQuery": {
"type": "object",
diff --git a/jsonschema/cloudwatch.jsonschema.json b/jsonschema/cloudwatch.jsonschema.json
index 996b5ee..e8cd42e 100644
--- a/jsonschema/cloudwatch.jsonschema.json
+++ b/jsonschema/cloudwatch.jsonschema.json
@@ -1,5 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
+ "$ref": "#/definitions/CloudWatchQuery",
"definitions": {
"MetricStat": {
"type": "object",
diff --git a/jsonschema/elasticsearch.jsonschema.json b/jsonschema/elasticsearch.jsonschema.json
index f80edcc..08b5c6f 100644
--- a/jsonschema/elasticsearch.jsonschema.json
+++ b/jsonschema/elasticsearch.jsonschema.json
@@ -1,5 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
+ "$ref": "#/definitions/dataquery",
"definitions": {
"BucketAggregation": {
"anyOf": [
diff --git a/jsonschema/googlecloudmonitoring.jsonschema.json b/jsonschema/googlecloudmonitoring.jsonschema.json
index c129a4b..8693f61 100644
--- a/jsonschema/googlecloudmonitoring.jsonschema.json
+++ b/jsonschema/googlecloudmonitoring.jsonschema.json
@@ -1,5 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
+ "$ref": "#/definitions/CloudMonitoringQuery",
"definitions": {
"CloudMonitoringQuery": {
"type": "object",
diff --git a/jsonschema/grafanapyroscope.jsonschema.json b/jsonschema/grafanapyroscope.jsonschema.json
index d16c059..80c67c0 100644
--- a/jsonschema/grafanapyroscope.jsonschema.json
+++ b/jsonschema/grafanapyroscope.jsonschema.json
@@ -1,5 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
+ "$ref": "#/definitions/dataquery",
"definitions": {
"PyroscopeQueryType": {
"enum": [
diff --git a/jsonschema/loki.jsonschema.json b/jsonschema/loki.jsonschema.json
index 9b5e7d4..c9d5185 100644
--- a/jsonschema/loki.jsonschema.json
+++ b/jsonschema/loki.jsonschema.json
@@ -1,5 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
+ "$ref": "#/definitions/dataquery",
"definitions": {
"QueryEditorMode": {
"enum": [
diff --git a/jsonschema/parca.jsonschema.json b/jsonschema/parca.jsonschema.json
index c1235f5..6901bf8 100644
--- a/jsonschema/parca.jsonschema.json
+++ b/jsonschema/parca.jsonschema.json
@@ -1,5 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
+ "$ref": "#/definitions/dataquery",
"definitions": {
"ParcaQueryType": {
"enum": [
diff --git a/jsonschema/prometheus.jsonschema.json b/jsonschema/prometheus.jsonschema.json
index cd6e9ce..fde9f58 100644
--- a/jsonschema/prometheus.jsonschema.json
+++ b/jsonschema/prometheus.jsonschema.json
@@ -1,5 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
+ "$ref": "#/definitions/dataquery",
"definitions": {
"QueryEditorMode": {
"enum": [
diff --git a/jsonschema/tempo.jsonschema.json b/jsonschema/tempo.jsonschema.json
index de1fabf..744d96e 100644
--- a/jsonschema/tempo.jsonschema.json
+++ b/jsonschema/tempo.jsonschema.json
@@ -1,5 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
+ "$ref": "#/definitions/TempoQuery",
"definitions": {
"TempoQuery": {
"type": "object",
diff --git a/jsonschema/testdata.jsonschema.json b/jsonschema/testdata.jsonschema.json
index 61a92bf..66fdf2c 100644
--- a/jsonschema/testdata.jsonschema.json
+++ b/jsonschema/testdata.jsonschema.json
@@ -1,5 +1,6 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
+ "$ref": "#/definitions/testdata",
"definitions": {
"CSVWave": {
"type": "object",
diff --git a/php/LICENSE.md b/php/LICENSE.md
new file mode 100644
index 0000000..c319da3
--- /dev/null
+++ b/php/LICENSE.md
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+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.
diff --git a/php/src/Accesspolicy/AccessPolicy.php b/php/src/Accesspolicy/AccessPolicy.php
new file mode 100644
index 0000000..5a08196
--- /dev/null
+++ b/php/src/Accesspolicy/AccessPolicy.php
@@ -0,0 +1,74 @@
+
+ */
+ public array $rules;
+
+ /**
+ * @param \Grafana\Foundation\Accesspolicy\ResourceRef|null $scope
+ * @param \Grafana\Foundation\Accesspolicy\RoleRef|null $role
+ * @param array<\Grafana\Foundation\Accesspolicy\AccessRule>|null $rules
+ */
+ public function __construct(?\Grafana\Foundation\Accesspolicy\ResourceRef $scope = null, ?\Grafana\Foundation\Accesspolicy\RoleRef $role = null, ?array $rules = null)
+ {
+ $this->scope = $scope ?: new \Grafana\Foundation\Accesspolicy\ResourceRef();
+ $this->role = $role ?: new \Grafana\Foundation\Accesspolicy\RoleRef();
+ $this->rules = $rules ?: [];
+ }
+
+ /**
+ * @param array $inputData
+ */
+ public static function fromArray(array $inputData): self
+ {
+ /** @var array{scope?: mixed, role?: mixed, rules?: array} $inputData */
+ $data = $inputData;
+ return new self(
+ scope: isset($data["scope"]) ? (function($input) {
+ /** @var array{kind?: string, name?: string} */
+ $val = $input;
+ return \Grafana\Foundation\Accesspolicy\ResourceRef::fromArray($val);
+ })($data["scope"]) : null,
+ role: isset($data["role"]) ? (function($input) {
+ /** @var array{kind?: string, name?: string, xname?: string} */
+ $val = $input;
+ return \Grafana\Foundation\Accesspolicy\RoleRef::fromArray($val);
+ })($data["role"]) : null,
+ rules: array_filter(array_map((function($input) {
+ /** @var array{kind?: string, verb?: string, target?: string} */
+ $val = $input;
+ return \Grafana\Foundation\Accesspolicy\AccessRule::fromArray($val);
+ }), $data["rules"] ?? [])),
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function jsonSerialize(): array
+ {
+ $data = [
+ "scope" => $this->scope,
+ "role" => $this->role,
+ "rules" => $this->rules,
+ ];
+ return $data;
+ }
+}
diff --git a/php/src/Accesspolicy/AccessPolicyBuilder.php b/php/src/Accesspolicy/AccessPolicyBuilder.php
new file mode 100644
index 0000000..7c40044
--- /dev/null
+++ b/php/src/Accesspolicy/AccessPolicyBuilder.php
@@ -0,0 +1,60 @@
+
+ */
+class AccessPolicyBuilder implements \Grafana\Foundation\Cog\Builder
+{
+ protected \Grafana\Foundation\Accesspolicy\AccessPolicy $internal;
+
+ public function __construct()
+ {
+ $this->internal = new \Grafana\Foundation\Accesspolicy\AccessPolicy();
+ }
+
+ /**
+ * @return \Grafana\Foundation\Accesspolicy\AccessPolicy
+ */
+ public function build()
+ {
+ return $this->internal;
+ }
+
+ /**
+ * The scope where these policies should apply
+ * @param \Grafana\Foundation\Cog\Builder<\Grafana\Foundation\Accesspolicy\ResourceRef> $scope
+ */
+ public function scope(\Grafana\Foundation\Cog\Builder $scope): static
+ {
+ $scopeResource = $scope->build();
+ $this->internal->scope = $scopeResource;
+
+ return $this;
+ }
+ /**
+ * The role that must apply this policy
+ * @param \Grafana\Foundation\Cog\Builder<\Grafana\Foundation\Accesspolicy\RoleRef> $role
+ */
+ public function role(\Grafana\Foundation\Cog\Builder $role): static
+ {
+ $roleResource = $role->build();
+ $this->internal->role = $roleResource;
+
+ return $this;
+ }
+ /**
+ * The set of rules to apply. Note that * is required to modify
+ * access policy rules, and that "none" will reject all actions
+ * @param \Grafana\Foundation\Cog\Builder<\Grafana\Foundation\Accesspolicy\AccessRule> $rules
+ */
+ public function rules(\Grafana\Foundation\Cog\Builder $rules): static
+ {
+ $rulesResource = $rules->build();
+ $this->internal->rules[] = $rulesResource;
+
+ return $this;
+ }
+
+}
diff --git a/php/src/Accesspolicy/AccessRule.php b/php/src/Accesspolicy/AccessRule.php
new file mode 100644
index 0000000..b6d4fd2
--- /dev/null
+++ b/php/src/Accesspolicy/AccessRule.php
@@ -0,0 +1,71 @@
+kind = $kind ?: "*";
+ $this->verb = $verb ?: "*";
+ $this->target = $target;
+ }
+
+ /**
+ * @param array $inputData
+ */
+ public static function fromArray(array $inputData): self
+ {
+ /** @var array{kind?: string, verb?: string, target?: string} $inputData */
+ $data = $inputData;
+ return new self(
+ kind: $data["kind"] ?? null,
+ verb: isset($data["verb"]) ? (function($input) {
+ switch (true) {
+ case is_string($input):
+ return $input;
+ default:
+ throw new \ValueError('incorrect value for disjunction');
+ }
+ })($data["verb"]) : null,
+ target: $data["target"] ?? null,
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function jsonSerialize(): array
+ {
+ $data = [
+ "kind" => $this->kind,
+ "verb" => $this->verb,
+ ];
+ if (isset($this->target)) {
+ $data["target"] = $this->target;
+ }
+ return $data;
+ }
+}
diff --git a/php/src/Accesspolicy/AccessRuleBuilder.php b/php/src/Accesspolicy/AccessRuleBuilder.php
new file mode 100644
index 0000000..129f248
--- /dev/null
+++ b/php/src/Accesspolicy/AccessRuleBuilder.php
@@ -0,0 +1,55 @@
+
+ */
+class AccessRuleBuilder implements \Grafana\Foundation\Cog\Builder
+{
+ protected \Grafana\Foundation\Accesspolicy\AccessRule $internal;
+
+ public function __construct()
+ {
+ $this->internal = new \Grafana\Foundation\Accesspolicy\AccessRule();
+ }
+
+ /**
+ * @return \Grafana\Foundation\Accesspolicy\AccessRule
+ */
+ public function build()
+ {
+ return $this->internal;
+ }
+
+ /**
+ * The kind this rule applies to (dashboards, alert, etc)
+ */
+ public function kind(string $kind): static
+ {
+ $this->internal->kind = $kind;
+
+ return $this;
+ }
+ /**
+ * READ, WRITE, CREATE, DELETE, ...
+ * should move to k8s style verbs like: "get", "list", "watch", "create", "update", "patch", "delete"
+ * @param string $verb
+ */
+ public function verb( $verb): static
+ {
+ $this->internal->verb = $verb;
+
+ return $this;
+ }
+ /**
+ * Specific sub-elements like "alert.rules" or "dashboard.permissions"????
+ */
+ public function target(string $target): static
+ {
+ $this->internal->target = $target;
+
+ return $this;
+ }
+
+}
diff --git a/php/src/Accesspolicy/ResourceRef.php b/php/src/Accesspolicy/ResourceRef.php
new file mode 100644
index 0000000..20435cb
--- /dev/null
+++ b/php/src/Accesspolicy/ResourceRef.php
@@ -0,0 +1,45 @@
+kind = $kind ?: "";
+ $this->name = $name ?: "";
+ }
+
+ /**
+ * @param array $inputData
+ */
+ public static function fromArray(array $inputData): self
+ {
+ /** @var array{kind?: string, name?: string} $inputData */
+ $data = $inputData;
+ return new self(
+ kind: $data["kind"] ?? null,
+ name: $data["name"] ?? null,
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function jsonSerialize(): array
+ {
+ $data = [
+ "kind" => $this->kind,
+ "name" => $this->name,
+ ];
+ return $data;
+ }
+}
diff --git a/php/src/Accesspolicy/ResourceRefBuilder.php b/php/src/Accesspolicy/ResourceRefBuilder.php
new file mode 100644
index 0000000..f837897
--- /dev/null
+++ b/php/src/Accesspolicy/ResourceRefBuilder.php
@@ -0,0 +1,38 @@
+
+ */
+class ResourceRefBuilder implements \Grafana\Foundation\Cog\Builder
+{
+ protected \Grafana\Foundation\Accesspolicy\ResourceRef $internal;
+
+ public function __construct()
+ {
+ $this->internal = new \Grafana\Foundation\Accesspolicy\ResourceRef();
+ }
+
+ /**
+ * @return \Grafana\Foundation\Accesspolicy\ResourceRef
+ */
+ public function build()
+ {
+ return $this->internal;
+ }
+
+ public function kind(string $kind): static
+ {
+ $this->internal->kind = $kind;
+
+ return $this;
+ }
+ public function name(string $name): static
+ {
+ $this->internal->name = $name;
+
+ return $this;
+ }
+
+}
diff --git a/php/src/Accesspolicy/RoleRef.php b/php/src/Accesspolicy/RoleRef.php
new file mode 100644
index 0000000..5c9de4d
--- /dev/null
+++ b/php/src/Accesspolicy/RoleRef.php
@@ -0,0 +1,55 @@
+kind = $kind ?: \Grafana\Foundation\Accesspolicy\RoleRefKind::Role();
+ $this->name = $name ?: "";
+ $this->xname = $xname ?: "";
+ }
+
+ /**
+ * @param array $inputData
+ */
+ public static function fromArray(array $inputData): self
+ {
+ /** @var array{kind?: string, name?: string, xname?: string} $inputData */
+ $data = $inputData;
+ return new self(
+ kind: isset($data["kind"]) ? (function($input) { return \Grafana\Foundation\Accesspolicy\RoleRefKind::fromValue($input); })($data["kind"]) : null,
+ name: $data["name"] ?? null,
+ xname: $data["xname"] ?? null,
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function jsonSerialize(): array
+ {
+ $data = [
+ "kind" => $this->kind,
+ "name" => $this->name,
+ "xname" => $this->xname,
+ ];
+ return $data;
+ }
+}
diff --git a/php/src/Accesspolicy/RoleRefBuilder.php b/php/src/Accesspolicy/RoleRefBuilder.php
new file mode 100644
index 0000000..84e1eb2
--- /dev/null
+++ b/php/src/Accesspolicy/RoleRefBuilder.php
@@ -0,0 +1,48 @@
+
+ */
+class RoleRefBuilder implements \Grafana\Foundation\Cog\Builder
+{
+ protected \Grafana\Foundation\Accesspolicy\RoleRef $internal;
+
+ public function __construct()
+ {
+ $this->internal = new \Grafana\Foundation\Accesspolicy\RoleRef();
+ }
+
+ /**
+ * @return \Grafana\Foundation\Accesspolicy\RoleRef
+ */
+ public function build()
+ {
+ return $this->internal;
+ }
+
+ /**
+ * Policies can apply to roles, teams, or users
+ * Applying policies to individual users is supported, but discouraged
+ */
+ public function kind(\Grafana\Foundation\Accesspolicy\RoleRefKind $kind): static
+ {
+ $this->internal->kind = $kind;
+
+ return $this;
+ }
+ public function name(string $name): static
+ {
+ $this->internal->name = $name;
+
+ return $this;
+ }
+ public function xname(string $xname): static
+ {
+ $this->internal->xname = $xname;
+
+ return $this;
+ }
+
+}
diff --git a/php/src/Accesspolicy/RoleRefKind.php b/php/src/Accesspolicy/RoleRefKind.php
new file mode 100644
index 0000000..c81a5bf
--- /dev/null
+++ b/php/src/Accesspolicy/RoleRefKind.php
@@ -0,0 +1,88 @@
+
+ */
+ private static $instances = [];
+
+ private function __construct(string $value)
+ {
+ $this->value = $value;
+ }
+
+ public static function role(): self
+ {
+ if (!isset(self::$instances["Role"])) {
+ self::$instances["Role"] = new self("Role");
+ }
+
+ return self::$instances["Role"];
+ }
+
+ public static function builtinRole(): self
+ {
+ if (!isset(self::$instances["BuiltinRole"])) {
+ self::$instances["BuiltinRole"] = new self("BuiltinRole");
+ }
+
+ return self::$instances["BuiltinRole"];
+ }
+
+ public static function team(): self
+ {
+ if (!isset(self::$instances["Team"])) {
+ self::$instances["Team"] = new self("Team");
+ }
+
+ return self::$instances["Team"];
+ }
+
+ public static function user(): self
+ {
+ if (!isset(self::$instances["User"])) {
+ self::$instances["User"] = new self("User");
+ }
+
+ return self::$instances["User"];
+ }
+
+ public static function fromValue(string $value): self
+ {
+ if ($value === "Role") {
+ return self::role();
+ }
+
+ if ($value === "BuiltinRole") {
+ return self::builtinRole();
+ }
+
+ if ($value === "Team") {
+ return self::team();
+ }
+
+ if ($value === "User") {
+ return self::user();
+ }
+
+ throw new \UnexpectedValueException("Value '$value' is not part of the enum RoleRefKind");
+ }
+
+ public function jsonSerialize(): string
+ {
+ return $this->value;
+ }
+
+ public function __toString(): string
+ {
+ return $this->value;
+ }
+}
+
diff --git a/php/src/Alerting/ContactPoint.php b/php/src/Alerting/ContactPoint.php
new file mode 100644
index 0000000..0bff452
--- /dev/null
+++ b/php/src/Alerting/ContactPoint.php
@@ -0,0 +1,106 @@
+disableResolveMessage = $disableResolveMessage;
+ $this->name = $name;
+ $this->provenance = $provenance;
+ $this->settings = $settings ?: null;
+ $this->type = $type ?: \Grafana\Foundation\Alerting\ContactPointType::Alertmanager();
+ $this->uid = $uid;
+ }
+
+ /**
+ * @param array $inputData
+ */
+ public static function fromArray(array $inputData): self
+ {
+ /** @var array{disableResolveMessage?: bool, name?: string, provenance?: string, settings?: mixed, type?: string, uid?: string} $inputData */
+ $data = $inputData;
+ return new self(
+ disableResolveMessage: $data["disableResolveMessage"] ?? null,
+ name: $data["name"] ?? null,
+ provenance: $data["provenance"] ?? null,
+ settings: $data["settings"] ?? null,
+ type: isset($data["type"]) ? (function($input) { return \Grafana\Foundation\Alerting\ContactPointType::fromValue($input); })($data["type"]) : null,
+ uid: $data["uid"] ?? null,
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function jsonSerialize(): array
+ {
+ $data = [
+ "settings" => $this->settings,
+ "type" => $this->type,
+ ];
+ if (isset($this->disableResolveMessage)) {
+ $data["disableResolveMessage"] = $this->disableResolveMessage;
+ }
+ if (isset($this->name)) {
+ $data["name"] = $this->name;
+ }
+ if (isset($this->provenance)) {
+ $data["provenance"] = $this->provenance;
+ }
+ if (isset($this->uid)) {
+ $data["uid"] = $this->uid;
+ }
+ return $data;
+ }
+}
diff --git a/php/src/Alerting/ContactPointBuilder.php b/php/src/Alerting/ContactPointBuilder.php
new file mode 100644
index 0000000..93d3678
--- /dev/null
+++ b/php/src/Alerting/ContactPointBuilder.php
@@ -0,0 +1,95 @@
+
+ */
+class ContactPointBuilder implements \Grafana\Foundation\Cog\Builder
+{
+ protected \Grafana\Foundation\Alerting\ContactPoint $internal;
+
+ public function __construct()
+ {
+ $this->internal = new \Grafana\Foundation\Alerting\ContactPoint();
+ }
+
+ /**
+ * @return \Grafana\Foundation\Alerting\ContactPoint
+ */
+ public function build()
+ {
+ return $this->internal;
+ }
+
+ /**
+ * EmbeddedContactPoint is the contact point type that is used
+ * by grafanas embedded alertmanager implementation.
+ */
+ public function disableResolveMessage(bool $disableResolveMessage): static
+ {
+ $this->internal->disableResolveMessage = $disableResolveMessage;
+
+ return $this;
+ }
+ /**
+ * EmbeddedContactPoint is the contact point type that is used
+ * by grafanas embedded alertmanager implementation.
+ */
+ public function name(string $name): static
+ {
+ $this->internal->name = $name;
+
+ return $this;
+ }
+ /**
+ * EmbeddedContactPoint is the contact point type that is used
+ * by grafanas embedded alertmanager implementation.
+ */
+ public function provenance(string $provenance): static
+ {
+ $this->internal->provenance = $provenance;
+
+ return $this;
+ }
+ /**
+ * EmbeddedContactPoint is the contact point type that is used
+ * by grafanas embedded alertmanager implementation.
+ * @param mixed $settings
+ */
+ public function settings( $settings): static
+ {
+ $this->internal->settings = $settings;
+
+ return $this;
+ }
+ /**
+ * EmbeddedContactPoint is the contact point type that is used
+ * by grafanas embedded alertmanager implementation.
+ */
+ public function type(\Grafana\Foundation\Alerting\ContactPointType $type): static
+ {
+ $this->internal->type = $type;
+
+ return $this;
+ }
+ /**
+ * EmbeddedContactPoint is the contact point type that is used
+ * by grafanas embedded alertmanager implementation.
+ */
+ public function uid(string $uid): static
+ {
+ if (!(strlen($uid) >= 1)) {
+ throw new \ValueError('strlen($uid) must be >= 1');
+ }
+ if (!(strlen($uid) <= 40)) {
+ throw new \ValueError('strlen($uid) must be <= 40');
+ }
+ $this->internal->uid = $uid;
+
+ return $this;
+ }
+
+}
diff --git a/php/src/Alerting/ContactPointType.php b/php/src/Alerting/ContactPointType.php
new file mode 100644
index 0000000..299a554
--- /dev/null
+++ b/php/src/Alerting/ContactPointType.php
@@ -0,0 +1,270 @@
+
+ */
+ private static $instances = [];
+
+ private function __construct(string $value)
+ {
+ $this->value = $value;
+ }
+
+ public static function alertmanager(): self
+ {
+ if (!isset(self::$instances["Alertmanager"])) {
+ self::$instances["Alertmanager"] = new self("alertmanager");
+ }
+
+ return self::$instances["Alertmanager"];
+ }
+
+ public static function dingding(): self
+ {
+ if (!isset(self::$instances["Dingding"])) {
+ self::$instances["Dingding"] = new self(" dingding");
+ }
+
+ return self::$instances["Dingding"];
+ }
+
+ public static function discord(): self
+ {
+ if (!isset(self::$instances["Discord"])) {
+ self::$instances["Discord"] = new self(" discord");
+ }
+
+ return self::$instances["Discord"];
+ }
+
+ public static function email(): self
+ {
+ if (!isset(self::$instances["Email"])) {
+ self::$instances["Email"] = new self(" email");
+ }
+
+ return self::$instances["Email"];
+ }
+
+ public static function googlechat(): self
+ {
+ if (!isset(self::$instances["Googlechat"])) {
+ self::$instances["Googlechat"] = new self(" googlechat");
+ }
+
+ return self::$instances["Googlechat"];
+ }
+
+ public static function kafka(): self
+ {
+ if (!isset(self::$instances["Kafka"])) {
+ self::$instances["Kafka"] = new self(" kafka");
+ }
+
+ return self::$instances["Kafka"];
+ }
+
+ public static function line(): self
+ {
+ if (!isset(self::$instances["Line"])) {
+ self::$instances["Line"] = new self(" line");
+ }
+
+ return self::$instances["Line"];
+ }
+
+ public static function opsgenie(): self
+ {
+ if (!isset(self::$instances["Opsgenie"])) {
+ self::$instances["Opsgenie"] = new self(" opsgenie");
+ }
+
+ return self::$instances["Opsgenie"];
+ }
+
+ public static function pagerduty(): self
+ {
+ if (!isset(self::$instances["Pagerduty"])) {
+ self::$instances["Pagerduty"] = new self(" pagerduty");
+ }
+
+ return self::$instances["Pagerduty"];
+ }
+
+ public static function pushover(): self
+ {
+ if (!isset(self::$instances["Pushover"])) {
+ self::$instances["Pushover"] = new self(" pushover");
+ }
+
+ return self::$instances["Pushover"];
+ }
+
+ public static function sensugo(): self
+ {
+ if (!isset(self::$instances["Sensugo"])) {
+ self::$instances["Sensugo"] = new self(" sensugo");
+ }
+
+ return self::$instances["Sensugo"];
+ }
+
+ public static function slack(): self
+ {
+ if (!isset(self::$instances["Slack"])) {
+ self::$instances["Slack"] = new self(" slack");
+ }
+
+ return self::$instances["Slack"];
+ }
+
+ public static function teams(): self
+ {
+ if (!isset(self::$instances["Teams"])) {
+ self::$instances["Teams"] = new self(" teams");
+ }
+
+ return self::$instances["Teams"];
+ }
+
+ public static function telegram(): self
+ {
+ if (!isset(self::$instances["Telegram"])) {
+ self::$instances["Telegram"] = new self(" telegram");
+ }
+
+ return self::$instances["Telegram"];
+ }
+
+ public static function threema(): self
+ {
+ if (!isset(self::$instances["Threema"])) {
+ self::$instances["Threema"] = new self(" threema");
+ }
+
+ return self::$instances["Threema"];
+ }
+
+ public static function victorops(): self
+ {
+ if (!isset(self::$instances["Victorops"])) {
+ self::$instances["Victorops"] = new self(" victorops");
+ }
+
+ return self::$instances["Victorops"];
+ }
+
+ public static function webhook(): self
+ {
+ if (!isset(self::$instances["Webhook"])) {
+ self::$instances["Webhook"] = new self(" webhook");
+ }
+
+ return self::$instances["Webhook"];
+ }
+
+ public static function wecom(): self
+ {
+ if (!isset(self::$instances["Wecom"])) {
+ self::$instances["Wecom"] = new self(" wecom");
+ }
+
+ return self::$instances["Wecom"];
+ }
+
+ public static function fromValue(string $value): self
+ {
+ if ($value === "alertmanager") {
+ return self::alertmanager();
+ }
+
+ if ($value === " dingding") {
+ return self::dingding();
+ }
+
+ if ($value === " discord") {
+ return self::discord();
+ }
+
+ if ($value === " email") {
+ return self::email();
+ }
+
+ if ($value === " googlechat") {
+ return self::googlechat();
+ }
+
+ if ($value === " kafka") {
+ return self::kafka();
+ }
+
+ if ($value === " line") {
+ return self::line();
+ }
+
+ if ($value === " opsgenie") {
+ return self::opsgenie();
+ }
+
+ if ($value === " pagerduty") {
+ return self::pagerduty();
+ }
+
+ if ($value === " pushover") {
+ return self::pushover();
+ }
+
+ if ($value === " sensugo") {
+ return self::sensugo();
+ }
+
+ if ($value === " slack") {
+ return self::slack();
+ }
+
+ if ($value === " teams") {
+ return self::teams();
+ }
+
+ if ($value === " telegram") {
+ return self::telegram();
+ }
+
+ if ($value === " threema") {
+ return self::threema();
+ }
+
+ if ($value === " victorops") {
+ return self::victorops();
+ }
+
+ if ($value === " webhook") {
+ return self::webhook();
+ }
+
+ if ($value === " wecom") {
+ return self::wecom();
+ }
+
+ throw new \UnexpectedValueException("Value '$value' is not part of the enum ContactPointType");
+ }
+
+ public function jsonSerialize(): string
+ {
+ return $this->value;
+ }
+
+ public function __toString(): string
+ {
+ return $this->value;
+ }
+}
+
diff --git a/php/src/Alerting/MatchType.php b/php/src/Alerting/MatchType.php
new file mode 100644
index 0000000..7b69505
--- /dev/null
+++ b/php/src/Alerting/MatchType.php
@@ -0,0 +1,88 @@
+
+ */
+ private static $instances = [];
+
+ private function __construct(string $value)
+ {
+ $this->value = $value;
+ }
+
+ public static function equal(): self
+ {
+ if (!isset(self::$instances["equal"])) {
+ self::$instances["equal"] = new self("=");
+ }
+
+ return self::$instances["equal"];
+ }
+
+ public static function notEqual(): self
+ {
+ if (!isset(self::$instances["not-equal"])) {
+ self::$instances["not-equal"] = new self("!=");
+ }
+
+ return self::$instances["not-equal"];
+ }
+
+ public static function equalRegex(): self
+ {
+ if (!isset(self::$instances["equal-regex"])) {
+ self::$instances["equal-regex"] = new self("=~");
+ }
+
+ return self::$instances["equal-regex"];
+ }
+
+ public static function notEqualRegex(): self
+ {
+ if (!isset(self::$instances["not-equal-regex"])) {
+ self::$instances["not-equal-regex"] = new self("!~");
+ }
+
+ return self::$instances["not-equal-regex"];
+ }
+
+ public static function fromValue(string $value): self
+ {
+ if ($value === "=") {
+ return self::equal();
+ }
+
+ if ($value === "!=") {
+ return self::notEqual();
+ }
+
+ if ($value === "=~") {
+ return self::equalRegex();
+ }
+
+ if ($value === "!~") {
+ return self::notEqualRegex();
+ }
+
+ throw new \UnexpectedValueException("Value '$value' is not part of the enum MatchType");
+ }
+
+ public function jsonSerialize(): string
+ {
+ return $this->value;
+ }
+
+ public function __toString(): string
+ {
+ return $this->value;
+ }
+}
+
diff --git a/php/src/Alerting/Matcher.php b/php/src/Alerting/Matcher.php
new file mode 100644
index 0000000..8ff7906
--- /dev/null
+++ b/php/src/Alerting/Matcher.php
@@ -0,0 +1,57 @@
+name = $name;
+ $this->type = $type;
+ $this->value = $value;
+ }
+
+ /**
+ * @param array $inputData
+ */
+ public static function fromArray(array $inputData): self
+ {
+ /** @var array{Name?: string, Type?: string, Value?: string} $inputData */
+ $data = $inputData;
+ return new self(
+ name: $data["Name"] ?? null,
+ type: isset($data["Type"]) ? (function($input) { return \Grafana\Foundation\Alerting\MatchType::fromValue($input); })($data["Type"]) : null,
+ value: $data["Value"] ?? null,
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function jsonSerialize(): array
+ {
+ $data = [
+ ];
+ if (isset($this->name)) {
+ $data["Name"] = $this->name;
+ }
+ if (isset($this->type)) {
+ $data["Type"] = $this->type;
+ }
+ if (isset($this->value)) {
+ $data["Value"] = $this->value;
+ }
+ return $data;
+ }
+}
diff --git a/php/src/Alerting/MatcherBuilder.php b/php/src/Alerting/MatcherBuilder.php
new file mode 100644
index 0000000..24626c9
--- /dev/null
+++ b/php/src/Alerting/MatcherBuilder.php
@@ -0,0 +1,44 @@
+
+ */
+class MatcherBuilder implements \Grafana\Foundation\Cog\Builder
+{
+ protected \Grafana\Foundation\Alerting\Matcher $internal;
+
+ public function __construct()
+ {
+ $this->internal = new \Grafana\Foundation\Alerting\Matcher();
+ }
+
+ /**
+ * @return \Grafana\Foundation\Alerting\Matcher
+ */
+ public function build()
+ {
+ return $this->internal;
+ }
+
+ public function name(string $name): static
+ {
+ $this->internal->name = $name;
+
+ return $this;
+ }
+ public function type(\Grafana\Foundation\Alerting\MatchType $type): static
+ {
+ $this->internal->type = $type;
+
+ return $this;
+ }
+ public function value(string $value): static
+ {
+ $this->internal->value = $value;
+
+ return $this;
+ }
+
+}
diff --git a/php/src/Alerting/MuteTiming.php b/php/src/Alerting/MuteTiming.php
new file mode 100644
index 0000000..439dee6
--- /dev/null
+++ b/php/src/Alerting/MuteTiming.php
@@ -0,0 +1,56 @@
+|null
+ */
+ public ?array $timeIntervals;
+
+ /**
+ * @param string|null $name
+ * @param array<\Grafana\Foundation\Alerting\TimeInterval>|null $timeIntervals
+ */
+ public function __construct(?string $name = null, ?array $timeIntervals = null)
+ {
+ $this->name = $name;
+ $this->timeIntervals = $timeIntervals;
+ }
+
+ /**
+ * @param array $inputData
+ */
+ public static function fromArray(array $inputData): self
+ {
+ /** @var array{name?: string, time_intervals?: array} $inputData */
+ $data = $inputData;
+ return new self(
+ name: $data["name"] ?? null,
+ timeIntervals: array_filter(array_map((function($input) {
+ /** @var array{name?: string, time_intervals?: array} */
+ $val = $input;
+ return \Grafana\Foundation\Alerting\TimeInterval::fromArray($val);
+ }), $data["time_intervals"] ?? [])),
+ );
+ }
+
+ /**
+ * @return array
+ */
+ public function jsonSerialize(): array
+ {
+ $data = [
+ ];
+ if (isset($this->name)) {
+ $data["name"] = $this->name;
+ }
+ if (isset($this->timeIntervals)) {
+ $data["time_intervals"] = $this->timeIntervals;
+ }
+ return $data;
+ }
+}
diff --git a/php/src/Alerting/MuteTimingBuilder.php b/php/src/Alerting/MuteTimingBuilder.php
new file mode 100644
index 0000000..14b5c29
--- /dev/null
+++ b/php/src/Alerting/MuteTimingBuilder.php
@@ -0,0 +1,45 @@
+
+ */
+class MuteTimingBuilder implements \Grafana\Foundation\Cog\Builder
+{
+ protected \Grafana\Foundation\Alerting\MuteTiming $internal;
+
+ public function __construct()
+ {
+ $this->internal = new \Grafana\Foundation\Alerting\MuteTiming();
+ }
+
+ /**
+ * @return \Grafana\Foundation\Alerting\MuteTiming
+ */
+ public function build()
+ {
+ return $this->internal;
+ }
+
+ public function name(string $name): static
+ {
+ $this->internal->name = $name;
+
+ return $this;
+ }
+ /**
+ * @param array<\Grafana\Foundation\Cog\Builder<\Grafana\Foundation\Alerting\TimeInterval>> $timeIntervals
+ */
+ public function timeIntervals(array $timeIntervals): static
+ {
+ $timeIntervalsResources = [];
+ foreach ($timeIntervals as $r1) {
+ $timeIntervalsResources[] = $r1->build();
+ }
+ $this->internal->timeIntervals = $timeIntervalsResources;
+
+ return $this;
+ }
+
+}
diff --git a/php/src/Alerting/NotificationPolicy.php b/php/src/Alerting/NotificationPolicy.php
new file mode 100644
index 0000000..3c2a3bc
--- /dev/null
+++ b/php/src/Alerting/NotificationPolicy.php
@@ -0,0 +1,200 @@
+|null
+ */
+ public ?array $groupBy;
+
+ /**
+ * A Route is a node that contains definitions of how to handle alerts. This is modified
+ * from the upstream alertmanager in that it adds the ObjectMatchers property.
+ */
+ public ?string $groupInterval;
+
+ /**
+ * A Route is a node that contains definitions of how to handle alerts. This is modified
+ * from the upstream alertmanager in that it adds the ObjectMatchers property.
+ */
+ public ?string $groupWait;
+
+ /**
+ * A Route is a node that contains definitions of how to handle alerts. This is modified
+ * from the upstream alertmanager in that it adds the ObjectMatchers property.
+ * @var array|null
+ */
+ public ?array $match;
+
+ /**
+ * A Route is a node that contains definitions of how to handle alerts. This is modified
+ * from the upstream alertmanager in that it adds the ObjectMatchers property.
+ * @var array
+ */
+ public array $matchRe;
+
+ /**
+ * A Route is a node that contains definitions of how to handle alerts. This is modified
+ * from the upstream alertmanager in that it adds the ObjectMatchers property.
+ * @var array<\Grafana\Foundation\Alerting\Matcher>
+ */
+ public array $matchers;
+
+ /**
+ * A Route is a node that contains definitions of how to handle alerts. This is modified
+ * from the upstream alertmanager in that it adds the ObjectMatchers property.
+ * @var array|null
+ */
+ public ?array $muteTimeIntervals;
+
+ /**
+ * A Route is a node that contains definitions of how to handle alerts. This is modified
+ * from the upstream alertmanager in that it adds the ObjectMatchers property.
+ * @var array>
+ */
+ public array $objectMatchers;
+
+ /**
+ * A Route is a node that contains definitions of how to handle alerts. This is modified
+ * from the upstream alertmanager in that it adds the ObjectMatchers property.
+ */
+ public string $provenance;
+
+ /**
+ * A Route is a node that contains definitions of how to handle alerts. This is modified
+ * from the upstream alertmanager in that it adds the ObjectMatchers property.
+ */
+ public ?string $receiver;
+
+ /**
+ * A Route is a node that contains definitions of how to handle alerts. This is modified
+ * from the upstream alertmanager in that it adds the ObjectMatchers property.
+ */
+ public ?string $repeatInterval;
+
+ /**
+ * A Route is a node that contains definitions of how to handle alerts. This is modified
+ * from the upstream alertmanager in that it adds the ObjectMatchers property.
+ * @var array<\Grafana\Foundation\Alerting\NotificationPolicy>|null
+ */
+ public ?array $routes;
+
+ /**
+ * @param bool|null $continue
+ * @param array|null $groupBy
+ * @param string|null $groupInterval
+ * @param string|null $groupWait
+ * @param array|null $match
+ * @param array|null $matchRe
+ * @param array<\Grafana\Foundation\Alerting\Matcher>|null $matchers
+ * @param array|null $muteTimeIntervals
+ * @param array>|null $objectMatchers
+ * @param string|null $provenance
+ * @param string|null $receiver
+ * @param string|null $repeatInterval
+ * @param array<\Grafana\Foundation\Alerting\NotificationPolicy>|null $routes
+ */
+ public function __construct(?bool $continue = null, ?array $groupBy = null, ?string $groupInterval = null, ?string $groupWait = null, ?array $match = null, ?array $matchRe = null, ?array $matchers = null, ?array $muteTimeIntervals = null, ?array $objectMatchers = null, ?string $provenance = null, ?string $receiver = null, ?string $repeatInterval = null, ?array $routes = null)
+ {
+ $this->continue = $continue;
+ $this->groupBy = $groupBy;
+ $this->groupInterval = $groupInterval;
+ $this->groupWait = $groupWait;
+ $this->match = $match;
+ $this->matchRe = $matchRe ?: [];
+ $this->matchers = $matchers ?: [];
+ $this->muteTimeIntervals = $muteTimeIntervals;
+ $this->objectMatchers = $objectMatchers ?: [];
+ $this->provenance = $provenance ?: "";
+ $this->receiver = $receiver;
+ $this->repeatInterval = $repeatInterval;
+ $this->routes = $routes;
+ }
+
+ /**
+ * @param array $inputData
+ */
+ public static function fromArray(array $inputData): self
+ {
+ /** @var array{continue?: bool, group_by?: array, group_interval?: string, group_wait?: string, match?: array, match_re?: array, matchers?: array, mute_time_intervals?: array, object_matchers?: array>, provenance?: string, receiver?: string, repeat_interval?: string, routes?: array} $inputData */
+ $data = $inputData;
+ return new self(
+ continue: $data["continue"] ?? null,
+ groupBy: $data["group_by"] ?? null,
+ groupInterval: $data["group_interval"] ?? null,
+ groupWait: $data["group_wait"] ?? null,
+ match: $data["match"] ?? null,
+ matchRe: $data["match_re"] ?? null,
+ matchers: array_filter(array_map((function($input) {
+ /** @var array{Name?: string, Type?: string, Value?: string} */
+ $val = $input;
+ return \Grafana\Foundation\Alerting\Matcher::fromArray($val);
+ }), $data["matchers"] ?? [])),
+ muteTimeIntervals: $data["mute_time_intervals"] ?? null,
+ objectMatchers: $data["object_matchers"] ?? null,
+ provenance: $data["provenance"] ?? null,
+ receiver: $data["receiver"] ?? null,
+ repeatInterval: $data["repeat_interval"] ?? null,
+ routes: array_filter(array_map((function($input) {
+ /** @var array{continue?: bool, group_by?: array, group_interval?: string, group_wait?: string, match?: array, match_re?: array, matchers?: array, mute_time_intervals?: array, object_matchers?: array>, provenance?: string, receiver?: string, repeat_inter...*[Comment body truncated]*
To publish a PHP package, the composer.json file describing it must be at the root of the repository.
Contributes to #470