diff --git a/.github/workflows/slack.yml b/.github/workflows/slack.yml
index afd9a5b3..b7b85f31 100644
--- a/.github/workflows/slack.yml
+++ b/.github/workflows/slack.yml
@@ -1,16 +1,30 @@
-name: Slack Notify on Star
-on: watch
+name: Slack Notify
+on:
+ watch:
+ types: [started]
jobs:
star-notify:
+ if: github.event_name == 'watch'
name: Notify Slack on star
- runs-on: ubuntu-latest
+ runs-on: ubuntu-22.04
steps:
- name: Get current star count
run: |
- echo "STARS=$(curl --silent 'https://api.github.com/repos/layer5io/meshkit' -H 'Accept: application/vnd.github.preview' | jq '.watchers_count')" >> $GITHUB_ENV
+ echo "STARS=$(curl --silent 'https://api.github.com/repos/${{github.repository}}' -H 'Accept: application/vnd.github.preview' | jq '.stargazers_count')" >> $GITHUB_ENV
- name: Notify slack
env:
SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
uses: pullreminders/slack-action@master
with:
- args: '{\"channel\":\"CSK7N9TGX\",\"text\":\"${{ github.actor }} just starred Meshkit! (https://github.com/layer5io/meshkit/stargazers) Total ⭐️: ${{env.STARS}}\"}'
+ args: '{\"channel\":\"CSK7N9TGX\",\"text\":\"${{ github.actor }} just starred ${{github.repository}}! (https://github.com/${{github.repository}}/stargazers) Total ⭐️: ${{env.STARS}}\"}'
+ good-first-issue-notify:
+ if: github.event_name == 'issues' && github.event.label.name == 'good first issue' || github.event.label.name == 'first-timers-only'
+ name: Notify Slack for new good-first-issue
+ runs-on: ubuntu-22.04
+ steps:
+ - name: Notify slack
+ env:
+ SLACK_BOT_TOKEN: ${{ secrets.SLACK_BOT_TOKEN }}
+ uses: pullreminders/slack-action@master
+ with:
+ args: '{\"channel\":\"C019426UBNY\",\"text\":\"A good first issue label was just added to ${{github.event.issue.html_url}}.\"}'
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 00417cc3..d254b26e 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -50,22 +50,6 @@ Or you may configure your IDE, for example, Visual Studio Code to automatically
-## Documentation Contribution Flow
-Please contribute! Layer5 documentation uses Jekyll and GitHub Pages to host docs sites. Learn more about [Layer5's documentation framework](https://docs.google.com/document/d/17guuaxb0xsfutBCzyj2CT6OZiFnMu9w4PzoILXhRXSo/edit?usp=sharing). The process of contributing follows this flow:
-
-1. Create a fork, if you have not already, by following the steps described [here](./CONTRIBUTING-gitflow.md)
-1. In the local copy of your fork, navigate to the docs folder.
-`cd docs`
-1. Create and checkout a new branch to make changes within
-`git checkout -b `
-1. Edit/add documentation.
-`vi .md`
-1. Run site locally to preview changes.
-`make site`
-1. Commit, [sign-off](#commit-signing), and push changes to your remote branch.
-`git push origin `
-1. Open a pull request (in your web browser) against the repo.
-
#### Tests
Users can now test their code on their local machine against the CI checks implemented using `make run-tests`.
@@ -92,7 +76,7 @@ All contributors are invited to review pull requests. See this short video on [h
Resources: https://lab.github.com and https://try.github.com/
-# FQA
+# FAQs
### Instructions for making custom dictionary entries
diff --git a/go.mod b/go.mod
index ea10a40a..8e252044 100644
--- a/go.mod
+++ b/go.mod
@@ -24,7 +24,7 @@ require (
github.com/google/uuid v1.6.0
github.com/kubernetes/kompose v1.31.1
github.com/layer5io/meshery-operator v0.7.0
- github.com/meshery/schemas v0.7.31
+ github.com/meshery/schemas v0.7.36
github.com/nats-io/nats.go v1.31.0
github.com/open-policy-agent/opa v0.67.1
github.com/opencontainers/image-spec v1.1.0
@@ -39,7 +39,7 @@ require (
gopkg.in/yaml.v3 v3.0.1
gorm.io/driver/postgres v1.5.3
gorm.io/driver/sqlite v1.5.4
- gorm.io/gorm v1.25.11
+ gorm.io/gorm v1.25.12
helm.sh/helm/v3 v3.13.2
k8s.io/api v0.28.4
k8s.io/apimachinery v0.28.4
diff --git a/go.sum b/go.sum
index 9aad5ca9..f4b94cd3 100644
--- a/go.sum
+++ b/go.sum
@@ -608,8 +608,8 @@ github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/meshery/kompose v1.0.1 h1:lg8B/pkLh6762jeFsQATD8UJZZwXZf/aviC3/dzw78A=
github.com/meshery/kompose v1.0.1/go.mod h1:TWhWTEMbJBUzENf4JTEtBmZRFm/r8n0nS6v4/nSD2vA=
-github.com/meshery/schemas v0.7.31 h1:FfVR+oErAiiEomt6sTZI5uKhoyU26QXawT6UDZHbthI=
-github.com/meshery/schemas v0.7.31/go.mod h1:UfiO+zm92yLkaJP0aroNwVnjuozoh793AWDXrKDYmT0=
+github.com/meshery/schemas v0.7.36 h1:KQOz/SODr+T6fDS2lDSrNo/Eu3LCaEUGIRauQtvXkjg=
+github.com/meshery/schemas v0.7.36/go.mod h1:wOh519/EDxiYlC4aeGv74ru+t9h9VJ4P2JYIvSfdPWQ=
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM=
github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk=
@@ -1198,8 +1198,8 @@ gorm.io/driver/postgres v1.5.3 h1:qKGY5CPHOuj47K/VxbCXJfFvIUeqMSXXadqdCY+MbBU=
gorm.io/driver/postgres v1.5.3/go.mod h1:F+LtvlFhZT7UBiA81mC9W6Su3D4WUhSboc/36QZU0gk=
gorm.io/driver/sqlite v1.5.4 h1:IqXwXi8M/ZlPzH/947tn5uik3aYQslP9BVveoax0nV0=
gorm.io/driver/sqlite v1.5.4/go.mod h1:qxAuCol+2r6PannQDpOP1FP6ag3mKi4esLnB/jHed+4=
-gorm.io/gorm v1.25.11 h1:/Wfyg1B/je1hnDx3sMkX+gAlxrlZpn6X0BXRlwXlvHg=
-gorm.io/gorm v1.25.11/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
+gorm.io/gorm v1.25.12 h1:I0u8i2hWQItBq1WfE0o2+WuL9+8L21K9e2HHSTE/0f8=
+gorm.io/gorm v1.25.12/go.mod h1:xh7N7RHfYlNc5EmcI/El95gXusucDrQnHXe0+CgWcLQ=
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o=
diff --git a/models/meshmodel/registry/v1alpha3/relationship_filter.go b/models/meshmodel/registry/v1alpha3/relationship_filter.go
index 624c683a..de31351e 100644
--- a/models/meshmodel/registry/v1alpha3/relationship_filter.go
+++ b/models/meshmodel/registry/v1alpha3/relationship_filter.go
@@ -74,6 +74,9 @@ func (relationshipFilter *RelationshipFilter) Get(db *database.Handler) ([]entit
if relationshipFilter.SubType != "" {
finder = finder.Where("relationship_definition_dbs.sub_type = ?", relationshipFilter.SubType)
}
+ if relationshipFilter.Id != "" {
+ finder = finder.Where("relationship_definition_dbs.id = ?", relationshipFilter.Id)
+ }
if relationshipFilter.ModelName != "" {
finder = finder.Where("model_dbs.name = ?", relationshipFilter.ModelName)
}
diff --git a/models/meshmodel/registry/v1beta1/category_filter.go b/models/meshmodel/registry/v1beta1/category_filter.go
index 399385a1..520614ae 100644
--- a/models/meshmodel/registry/v1beta1/category_filter.go
+++ b/models/meshmodel/registry/v1beta1/category_filter.go
@@ -50,6 +50,9 @@ func (cf *CategoryFilter) Get(db *database.Handler) ([]entity.Entity, int64, int
finder = finder.Where("name = ?", cf.Name)
}
}
+ if cf.Id != "" {
+ finder = finder.Where("id = ?", cf.Id)
+ }
if cf.OrderOn != "" {
if cf.Sort == "desc" {
finder = finder.Order(clause.OrderByColumn{Column: clause.Column{Name: cf.OrderOn}, Desc: true})
diff --git a/models/meshmodel/registry/v1beta1/component_filter.go b/models/meshmodel/registry/v1beta1/component_filter.go
index 76a6fb57..47aefe58 100644
--- a/models/meshmodel/registry/v1beta1/component_filter.go
+++ b/models/meshmodel/registry/v1beta1/component_filter.go
@@ -116,7 +116,9 @@ func (componentFilter *ComponentFilter) Get(db *database.Handler) ([]entity.Enti
if componentFilter.Version != "" {
finder = finder.Where("model_dbs.model->>'version' = ?", componentFilter.Version)
}
-
+ if componentFilter.Id != "" {
+ finder = finder.Where("component_definition_dbs.id = ?", componentFilter.Id)
+ }
if componentFilter.OrderOn != "" {
if componentFilter.Sort == "desc" {
finder = finder.Order(clause.OrderByColumn{Column: clause.Column{Name: componentFilter.OrderOn}, Desc: true})
diff --git a/models/meshmodel/registry/v1beta1/model_filter.go b/models/meshmodel/registry/v1beta1/model_filter.go
index 6a512f79..cb014d5b 100644
--- a/models/meshmodel/registry/v1beta1/model_filter.go
+++ b/models/meshmodel/registry/v1beta1/model_filter.go
@@ -29,6 +29,9 @@ type ModelFilter struct {
Components bool
Relationships bool
Status string
+ // When Trim is true it will only send necessary models data
+ // like: component count, relationship count, id and name of model
+ Trim bool
}
// Create the filter from map[string]interface{}
@@ -138,6 +141,9 @@ func (mf *ModelFilter) Get(db *database.Handler) ([]entity.Entity, int64, int, e
} else if mf.Annotations == "false" {
finder = finder.Where("model_dbs.metadata->>'isAnnotation' = false")
}
+ if mf.Id != "" {
+ finder = finder.Where("model_dbs.id = ?", mf.Id)
+ }
if mf.OrderOn != "" {
if mf.Sort == "desc" {
finder = finder.Order(clause.OrderByColumn{Column: clause.Column{Name: mf.OrderOn}, Desc: true})
@@ -179,27 +185,48 @@ func (mf *ModelFilter) Get(db *database.Handler) ([]entity.Entity, int64, int, e
for _, modelDB := range modelWithCategories {
// resolve for loop scope
_modelDB := modelDB
- if includeComponents {
- var components []component.ComponentDefinition
- finder := db.Model(&component.ComponentDefinition{}).
- Select("component_definition_dbs.id, component_definition_dbs.component, component_definition_dbs.display_name, component_definition_dbs.metadata, component_definition_dbs.schema_version, component_definition_dbs.version,component_definition_dbs.styles,component_definition_dbs.capabilities").
- Where("component_definition_dbs.model_id = ?", _modelDB.Id)
- if err := finder.Scan(&components).Error; err != nil {
- return nil, 0, 0, err
+ var componentCount int64
+ db.Model(&component.ComponentDefinition{}).Where("component_definition_dbs.model_id = ?", _modelDB.Id).Count(&componentCount)
+ var relationshipCount int64
+ db.Model(&relationship.RelationshipDefinition{}).Where("relationship_definition_dbs.model_id = ?", _modelDB.Id).Count(&relationshipCount)
+ _modelDB.ComponentsCount = int(componentCount)
+ _modelDB.RelationshipsCount = int(relationshipCount)
+
+ // If Trim is true, only include the id, name, counts and metadata
+ if mf.Trim {
+ trimmedModel := &model.ModelDefinition{
+ Id: _modelDB.Id,
+ Name: _modelDB.Name,
+ DisplayName: _modelDB.DisplayName,
+ Metadata: _modelDB.Metadata,
+ ComponentsCount: int(componentCount),
+ RelationshipsCount: int(relationshipCount),
}
- _modelDB.Components = components
- }
- if includeRelationships {
- var relationships []relationship.RelationshipDefinition
- finder := db.Model(&relationship.RelationshipDefinition{}).
- Select("relationship_definition_dbs.*").
- Where("relationship_definition_dbs.model_id = ?", _modelDB.Id)
- if err := finder.Scan(&relationships).Error; err != nil {
- return nil, 0, 0, err
+ defs = append(defs, trimmedModel)
+
+ } else {
+ if includeComponents {
+ var components []component.ComponentDefinition
+ finder := db.Model(&component.ComponentDefinition{}).
+ Select("component_definition_dbs.*").
+ Where("component_definition_dbs.model_id = ?", _modelDB.Id)
+ if err := finder.Scan(&components).Error; err != nil {
+ return nil, 0, 0, err
+ }
+ _modelDB.Components = components
+ }
+ if includeRelationships {
+ var relationships []relationship.RelationshipDefinition
+ finder := db.Model(&relationship.RelationshipDefinition{}).
+ Select("relationship_definition_dbs.*").
+ Where("relationship_definition_dbs.model_id = ?", _modelDB.Id)
+ if err := finder.Scan(&relationships).Error; err != nil {
+ return nil, 0, 0, err
+ }
+ _modelDB.Relationships = relationships
}
- _modelDB.Relationships = relationships
+ defs = append(defs, &_modelDB)
}
- defs = append(defs, &_modelDB)
}
return defs, count, countUniqueModels(modelWithCategories), nil
}
diff --git a/models/meshmodel/registry/v1beta1/policy_filter.go b/models/meshmodel/registry/v1beta1/policy_filter.go
index d15d970c..3108d68c 100644
--- a/models/meshmodel/registry/v1beta1/policy_filter.go
+++ b/models/meshmodel/registry/v1beta1/policy_filter.go
@@ -49,7 +49,9 @@ func (pf *PolicyFilter) Get(db *database.Handler) ([]entity.Entity, int64, int,
if pf.ModelName != "" {
finder = finder.Where("model_dbs.name = ?", pf.ModelName)
}
-
+ if pf.Id != "" {
+ finder = finder.Where("policy_definition_dbs.id = ?", pf.Id)
+ }
var count int64
finder.Count(&count)
diff --git a/utils/component/openapi_generator.go b/utils/component/openapi_generator.go
index 045fcd6f..8d0178de 100644
--- a/utils/component/openapi_generator.go
+++ b/utils/component/openapi_generator.go
@@ -4,6 +4,7 @@ import (
"encoding/json"
"errors"
"fmt"
+ "strings"
"cuelang.org/go/cue"
"cuelang.org/go/cue/cuecontext"
@@ -100,6 +101,26 @@ func GenerateFromOpenAPI(resource string, pkg models.Package) ([]component.Compo
continue
}
+ // Determine if the resource is namespaced
+ var isNamespaced bool
+
+ scopeCue, err := utils.Lookup(fieldVal, `"x-kubernetes-resource".scope`)
+ if err == nil {
+ scope, err := scopeCue.String()
+ if err == nil {
+ if scope == "Namespaced" {
+ isNamespaced = true
+ } else if scope == "Cluster" {
+ isNamespaced = false
+ }
+ }
+ } else {
+ isNamespaced, err = getResourceScope(resource, kind)
+ if err != nil {
+ isNamespaced = false
+ }
+ }
+
c := component.ComponentDefinition{
SchemaVersion: v1beta1.ComponentSchemaVersion,
Format: component.JSON,
@@ -109,6 +130,9 @@ func GenerateFromOpenAPI(resource string, pkg models.Package) ([]component.Compo
Schema: string(crd),
},
DisplayName: manifests.FormatToReadableString(kind),
+ Metadata: component.ComponentDefinition_Metadata{
+ IsNamespaced: isNamespaced,
+ },
Model: model.ModelDefinition{
SchemaVersion: v1beta1.ModelSchemaVersion,
Model: model.Model{
@@ -127,7 +151,27 @@ func GenerateFromOpenAPI(resource string, pkg models.Package) ([]component.Compo
components = append(components, c)
}
return components, nil
+}
+func getResourceScope(manifest string, kind string) (bool, error) {
+ var m map[string]interface{}
+
+ err := yaml.Unmarshal([]byte(manifest), &m)
+ if err != nil {
+ return false, utils.ErrDecodeYaml(err)
+ }
+
+ paths, ok := m["paths"].(map[string]interface{})
+ if !ok {
+ return false, fmt.Errorf("paths not found in manifest")
+ }
+
+ for path := range paths {
+ if strings.Contains(path, "/namespaces/{namespace}/") && strings.Contains(path, strings.ToLower(kind)) {
+ return true, nil // Resource is namespaced
+ }
+ }
+ return false, nil // Resource is cluster-scoped
}
func getResolvedManifest(manifest string) (string, error) {