-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #54 from interlynk-io/feature/folder_system
added folder system as a input and output adapter
- Loading branch information
Showing
16 changed files
with
851 additions
and
11 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
# 📖 Writing a New Adapter for sbommv | ||
|
||
## Understanding Adapters in sbommv | ||
|
||
`sbommv` follows a pluggable architecture where adapters act as interfaces between SBOM sources and destinations. | ||
|
||
- **Input Adapters** → Fetch SBOMs (e.g., from GitHub, Folder, etc.). | ||
- **Output Adapters** → Send SBOMs (e.g., to Interlynk, Folder, etc.). | ||
- **Each Adapter Implements the** `Adapter` **Interface** → This ensures a common API across different sources & destinations. | ||
|
||
## Implementing a New Adapter | ||
|
||
To add a new adapter, follow these steps: | ||
|
||
### Step 1: Define a Struct for Your Adapter | ||
|
||
Each adapter has its own struct. This struct will hold relevant configuration details. | ||
|
||
For **FolderAdapter**, we define: | ||
|
||
```go | ||
// FolderAdapter struct represents an adapter for local folder storage | ||
type FolderAdapter struct { | ||
Role types.AdapterRole | ||
FolderPath string | ||
Recursive bool | ||
} | ||
``` | ||
|
||
💡 **Note**: | ||
|
||
- **Role**: Defines whether the adapter is for input or output. | ||
- **FolderPath**: Directory to scan or store SBOMs. | ||
- **Recursive**: If true, scans subdirectories when acting as an input adapter. | ||
|
||
### Step 2: Implement `AddCommandParams` | ||
|
||
- This method adds CLI flags related to the adapter. | ||
|
||
```go | ||
// AddCommandParams adds folder adapter-specific CLI flags | ||
func (f *FolderAdapter) AddCommandParams(cmd *cobra.Command) { | ||
// implementation code | ||
} | ||
``` | ||
|
||
- This ensures the correct flags are registered depending on the adapter role. | ||
|
||
### Step 3: Implement `ParseAndValidateParams` | ||
|
||
- This method validates and extracts CLI parameters. | ||
|
||
```go | ||
// ParseAndValidateParams extracts and validates folder adapter parameters | ||
func (f *FolderAdapter) ParseAndValidateParams(cmd *cobra.Command) error { | ||
// implementation code | ||
} | ||
``` | ||
|
||
- This ensures we have valid folder paths before proceeding. | ||
|
||
### Step 4: Implement `FetchSBOMs` for Input Adapter | ||
|
||
- This method scans a folder, detects SBOMs, and returns an iterator. | ||
|
||
```go | ||
// FetchSBOMs retrieves SBOMs from the specified folder | ||
func (f *FolderAdapter) FetchSBOMs(ctx *tcontext.TransferMetadata) (iterator.SBOMIterator, error) { | ||
// implementation code | ||
} | ||
``` | ||
|
||
- This method: | ||
|
||
- Scans the directory recursively, if resursive flag is `true`. | ||
- Detects SBOMs using utils.IsValidSBOM(). | ||
- Returns an iterator for processing SBOMs. | ||
|
||
### Step 5: Implement UploadSBOMs for Output Adapter | ||
|
||
- This method saves SBOMs to the specified folder. | ||
|
||
```go | ||
// UploadSBOMs writes SBOMs to the specified folder | ||
func (f *FolderAdapter) UploadSBOMs(ctx *tcontext.TransferMetadata, it iterator.SBOMIterator) error { | ||
// implementation code | ||
} | ||
``` | ||
|
||
- This method: | ||
- Creates a folder if it doesn’t exist. | ||
- Writes SBOMs using either their original filename or a generated UUID. | ||
|
||
### Step 6: Implement DryRun | ||
|
||
```go | ||
// DryRun simulates fetching or uploading SBOMs | ||
func (f *FolderAdapter) DryRun(ctx *tcontext.TransferMetadata, it iterator.SBOMIterator) error { | ||
// implementation code | ||
} | ||
``` | ||
|
||
- This method: | ||
|
||
- In input mode, lists detected SBOMs. | ||
- In output mode, shows where SBOMs will be saved. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,117 @@ | ||
// Copyright 2025 Interlynk.io | ||
// | ||
// 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. | ||
|
||
package folder | ||
|
||
import ( | ||
"fmt" | ||
"strings" | ||
|
||
"github.com/interlynk-io/sbommv/pkg/iterator" | ||
"github.com/interlynk-io/sbommv/pkg/logger" | ||
"github.com/interlynk-io/sbommv/pkg/tcontext" | ||
"github.com/interlynk-io/sbommv/pkg/types" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
// FolderAdapter handles fetching SBOMs from folders | ||
type FolderAdapter struct { | ||
config *FolderConfig | ||
Role types.AdapterRole // "input" or "output" adapter type | ||
Fetcher SBOMFetcher | ||
} | ||
|
||
// AddCommandParams adds Folder-specific CLI flags | ||
func (f *FolderAdapter) AddCommandParams(cmd *cobra.Command) { | ||
cmd.Flags().String("in-folder-path", "", "Folder path") | ||
cmd.Flags().Bool("in-folder-recursive", false, "Folder recurssive (default: false)") | ||
cmd.Flags().String("in-folder-processing-mode", "sequential", "Folder processing mode (sequential/parallel)") | ||
} | ||
|
||
// ParseAndValidateParams validates the Folder adapter params | ||
func (f *FolderAdapter) ParseAndValidateParams(cmd *cobra.Command) error { | ||
var ( | ||
pathFlag, recursiveFlag, processingModeFlag string | ||
missingFlags []string | ||
invalidFlags []string | ||
) | ||
|
||
switch f.Role { | ||
case types.InputAdapterRole: | ||
pathFlag = "in-folder-path" | ||
recursiveFlag = "in-folder-recursive" | ||
processingModeFlag = "in-folder-processing-mode" | ||
|
||
case types.OutputAdapterRole: | ||
return fmt.Errorf("The Folder adapter doesn't support output adapter functionalities.") | ||
|
||
default: | ||
return fmt.Errorf("The adapter is neither an input type nor an output type") | ||
|
||
} | ||
|
||
// Extract Folder Path | ||
folderPath, _ := cmd.Flags().GetString(pathFlag) | ||
if folderPath == "" { | ||
missingFlags = append(missingFlags, "--"+pathFlag) | ||
} | ||
|
||
// Extract Folder Path | ||
folderRecurse, _ := cmd.Flags().GetBool(recursiveFlag) | ||
|
||
validModes := map[string]bool{"sequential": true, "parallel": true} | ||
|
||
// Extract the processing mode: sequential/parallel | ||
mode, _ := cmd.Flags().GetString(processingModeFlag) | ||
if !validModes[mode] { | ||
invalidFlags = append(invalidFlags, fmt.Sprintf("%s=%s (must be one of: sequential, parallel mode)", processingModeFlag, mode)) | ||
} | ||
|
||
// Validate required flags | ||
if len(missingFlags) > 0 { | ||
return fmt.Errorf("missing input adapter required flags: %v\n\nUse 'sbommv transfer --help' for usage details.", missingFlags) | ||
} | ||
|
||
// Validate incorrect flag usage | ||
if len(invalidFlags) > 0 { | ||
return fmt.Errorf("invalid input adapter flag usage:\n %s\n\nUse 'sbommv transfer --help' for correct usage.", strings.Join(invalidFlags, "\n ")) | ||
} | ||
|
||
cfg := FolderConfig{ | ||
FolderPath: folderPath, | ||
Recursive: folderRecurse, | ||
ProcessingMode: types.ProcessingMode(mode), | ||
} | ||
|
||
f.config = &cfg | ||
|
||
return nil | ||
} | ||
|
||
// FetchSBOMs initializes the Folder SBOM iterator using the unified method | ||
func (f *FolderAdapter) FetchSBOMs(ctx *tcontext.TransferMetadata) (iterator.SBOMIterator, error) { | ||
logger.LogDebug(ctx.Context, "Initializing SBOM fetching", "mode", f.config.ProcessingMode) | ||
return f.Fetcher.Fetch(ctx, f.config) | ||
} | ||
|
||
// OutputSBOMs should return an error since Folder does not support SBOM uploads | ||
func (f *FolderAdapter) UploadSBOMs(ctx *tcontext.TransferMetadata, iterator iterator.SBOMIterator) error { | ||
return fmt.Errorf("Folder adapter does not support SBOM uploading") | ||
} | ||
|
||
// DryRun for Folder Adapter: Displays all fetched SBOMs from folder adapter | ||
func (f *FolderAdapter) DryRun(ctx *tcontext.TransferMetadata, iter iterator.SBOMIterator) error { | ||
reporter := NewFolderReporter(false, "") | ||
return reporter.DryRun(ctx.Context, iter) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
// Copyright 2025 Interlynk.io | ||
// | ||
// 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. | ||
// ------------------------------------------------------------------------- | ||
|
||
package folder | ||
|
||
import "github.com/interlynk-io/sbommv/pkg/types" | ||
|
||
type FolderConfig struct { | ||
FolderPath string | ||
Recursive bool | ||
ProcessingMode types.ProcessingMode | ||
} | ||
|
||
func NewFolderConfig() *FolderConfig { | ||
return &FolderConfig{ | ||
ProcessingMode: types.FetchSequential, // Default | ||
} | ||
} |
Oops, something went wrong.