Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
19f8b4e
Changes to Pipelines (#1638)
syeleti-msft Jul 21, 2025
00bb41e
go mod update, resolve unit test errors (#1884)
syeleti-msft Jul 21, 2025
9c8c2f8
Hard limit in file-cache shall be on by default to avoid issues relat…
vibhansa-msft Jul 24, 2025
7776998
Add New stage to the Nightly pipeline (#1889)
syeleti-msft Jul 24, 2025
bec24fb
Making the truncate callback handle aware. (#1895)
syeleti-msft Jul 29, 2025
fce0b55
ESRP and PMC migration to MI (#1891)
souravgupta-msft Jul 29, 2025
718c75e
Increase file cache size limit in config file. (#1897)
syeleti-msft Jul 30, 2025
d77bc8c
Modernize go code using modernize tool (#1819)
jfantinhardesty Aug 1, 2025
653c1ef
fix build for fuse2 unit tests (#1906)
syeleti-msft Aug 1, 2025
d47700b
Add test suite to check the data integrity of block cache. (#1894)
syeleti-msft Aug 2, 2025
171080b
Convert read options struct to pointer in the pipeline (#1901)
syeleti-msft Aug 2, 2025
1868b37
Don't auto-detect account if --use-adls flag is given (#1905)
ashruti-msft Aug 4, 2025
53e11a8
pass write options struct as pointer in the pipeline (#1902)
syeleti-msft Aug 4, 2025
b36c03f
Removed duplicate step From Sec Pack Installation (#1898)
jainakanksha-msft Aug 4, 2025
1a7d91c
fix e2e tests failure (#1913)
syeleti-msft Aug 5, 2025
6eb2b51
Update README.md (#1926)
p15nishatr Aug 25, 2025
ba81558
Add comprehensive GitHub Copilot instructions for Azure Storage Fuse …
Copilot Aug 26, 2025
4e93340
Fail FNS account mounted as HNS account (#1925)
vibhansa-msft Sep 4, 2025
241e272
Document Blobfuse HTTPS communication and version check (#1945)
vibhansa-msft Sep 8, 2025
58a0998
Query DeepWiki with issue statement and post responce as comment (#1958)
vibhansa-msft Sep 15, 2025
f1df086
Vibhansa/deepwiki qustion update (#1960)
vibhansa-msft Sep 15, 2025
9509b8d
Vibhansa/deepwiki qustion (#1962)
vibhansa-msft Sep 15, 2025
eb728a4
Summarize deepwiki responce using AI and post as comment to new issue…
vibhansa-msft Sep 16, 2025
c4a0a2d
Vibhansa/deepwiki qustion (#1966)
vibhansa-msft Sep 16, 2025
81c335f
Vibhansa/deepwiki qustion (#1968)
vibhansa-msft Sep 16, 2025
d8b4203
Vibhansa/deepwiki qustion (#1970)
vibhansa-msft Sep 16, 2025
ed37ce1
Vibhansa/deepwiki qustion (#1973)
vibhansa-msft Sep 16, 2025
218c488
Vibhansa/deepwiki qustion (#1975)
vibhansa-msft Sep 16, 2025
d6dd455
Vibhansa/deepwiki qustion (#1977)
vibhansa-msft Sep 17, 2025
e113ff6
Vibhansa/deepwiki qustion (#1983)
vibhansa-msft Sep 17, 2025
e38c156
Vibhansa/deepwiki qustion (#1985)
vibhansa-msft Sep 17, 2025
5f42b8d
Vibhansa/deepwiki qustion (#1988)
vibhansa-msft Sep 17, 2025
dfa3e9d
AI Comment cleanup (#1995)
vibhansa-msft Sep 18, 2025
ff13892
Merge commit 'd77bc8c215aafcb9023b4645dfc5a6d114463235' into update-b…
jfantinhardesty Sep 19, 2025
b40af4a
Run gomodernize
jfantinhardesty Sep 19, 2025
11e3fa2
Delete extra files
jfantinhardesty Sep 19, 2025
aa3cfd8
Add back streaming
jfantinhardesty Sep 19, 2025
927b580
Merge branch 'main' into update-blobfuse2-after-2.5.0
jfantinhardesty Sep 23, 2025
9bada82
Updating go dependencies (#1972)
vibhansa-msft Sep 26, 2025
db077b7
New linter integration (#2013)
vibhansa-msft Sep 29, 2025
43314da
Add FIO tests to check the data integrity (#1893)
syeleti-msft Sep 29, 2025
702e513
Merge branch 'main' into update-blobfuse2-after-2.5.0
jfantinhardesty Sep 30, 2025
a64c9a7
persist the stack trace, in the event of crash (#1939)
syeleti-msft Oct 7, 2025
2d74e12
Change msi ids in pipeline (#2022)
syeleti-msft Oct 10, 2025
389136c
Fix issues while truncating the file (#2003)
syeleti-msft Oct 10, 2025
c09d35a
2.5.1 release version update (#2024)
vibhansa-msft Oct 14, 2025
d41a423
Merge branch 'main' into update-blobfuse2-after-2.5.0
jfantinhardesty Nov 12, 2025
162b437
Fix failing tests
jfantinhardesty Nov 14, 2025
1998cf4
Merge branch 'main' into update-blobfuse2-after-2.5.0
jfantinhardesty Nov 14, 2025
6aab0d9
Merge tag 'blobfuse2-2.5.1' into update-blobfuse2-2.5.1
jfantinhardesty Nov 14, 2025
2e8508f
Fix environment variable names
jfantinhardesty Nov 14, 2025
dc4b5e2
Merge branch 'update-blobfuse2-after-2.5.0' into update-blobfuse2-2.5.1
jfantinhardesty Nov 14, 2025
f1f97b7
Fix cleanup
jfantinhardesty Nov 17, 2025
d955af3
Fix unit test failures
jfantinhardesty Nov 20, 2025
a3c93b7
Merge branch 'main' into update-blobfuse2-2.5.1
jfantinhardesty Dec 11, 2025
c4770e2
Fix failing test
jfantinhardesty Dec 11, 2025
394764e
Fix failing tests on Windows
jfantinhardesty Dec 11, 2025
b7db963
Add linux build
jfantinhardesty Dec 11, 2025
39f6ba4
Merge branch 'main' into update-blobfuse2-2.5.1
jfantinhardesty Dec 30, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
192 changes: 192 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
# Azure Storage Fuse (cloudfuse)

Cloudfuse is a FUSE filesystem driver that provides virtual filesystem backed by S3 or Azure Blob Storage. It uses libfuse (fuse3) to communicate with the Linux FUSE kernel module and implements filesystem operations using the AWS S3 or Azure Storage REST APIs.

Always reference these instructions first and fallback to search or bash commands only when you encounter unexpected information that does not match the info here.

## Working Effectively

### Bootstrap, Build, and Test the Repository

**CRITICAL**: All build and test commands include specific timeout warnings. NEVER CANCEL long-running operations.

- Install required dependencies:
```bash
sudo apt update
sudo apt install -y libfuse3-dev fuse3 gcc
```

- Install Go 1.25.4+ (already available in most environments):
```bash
go version # Should show 1.25.4 or higher
```

- Build cloudfuse binary:
```bash
./build.sh
```
**Timing**: ~30 seconds. NEVER CANCEL. Use timeout 120+ seconds.

- Build health monitor binary:
```bash
./build.sh health
```
**Timing**: ~5 seconds. Use timeout 60+ seconds.

- Verify binary functionality:
```bash
./cloudfuse --version
./cloudfuse -h
```

### Testing

- Run unit tests (core components only):
```bash
go test -v -timeout=10m ./internal/... ./common/... --tags=unittest,fuse3
```
**Timing**: ~2 minutes. NEVER CANCEL. Use timeout 15+ minutes.

- Run full unit tests (some may fail without Azure credentials):
```bash
go test -v -timeout=45m ./... --tags=unittest,fuse3
```
**WARNING**: Expected network/credential test failures. **Timing**: ~5-10 minutes. NEVER CANCEL. Use timeout 60+ minutes.

- Run linting:
```bash
# Install golangci-lint if not available
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin

# Run linting
$(go env GOPATH)/bin/golangci-lint run --tests=false --build-tags fuse3 --max-issues-per-linter=0
```
**Timing**: ~10 seconds. Use timeout 60+ seconds.

- Check code formatting:
```bash
gofmt -s -l -d .
```
**Timing**: ~2 seconds. Should return no output if properly formatted.

### Validation Scenarios

**ALWAYS test these scenarios after making changes**:

1. **Binary Creation and Basic Commands**:
```bash
./build.sh
./cloudfuse --version
./cloudfuse -h
./cloudfuse mount --help
```

2. **Config Generation**:
```bash
mkdir -p /tmp/cloudfuse-test
./cloudfuse gen-config --tmp-path=/tmp/cloudfuse-test --o /tmp/cloudfuse-test/config.yaml
cat /tmp/cloudfuse-test/config.yaml
```

3. **Health Monitor**:
```bash
./build.sh health
./cfusemon --help
```

4. **Format and Lint Validation**:
```bash
gofmt -s -l -d . # Should return no output
$(go env GOPATH)/bin/golangci-lint run --tests=false --build-tags fuse3 --max-issues-per-linter=0
```

## Build System Details

- **Primary Build Script**: `./build.sh` - builds cloudfuse with fuse3 by default
- **Build Variants**:
- `./build.sh` - standard fuse3 build
- `./build.sh fuse2` - legacy fuse2 build
- `./build.sh health` - health monitor binary
- **Output**: `cloudfuse` binary (~30MB) and optionally `cfusemon` binary (~6MB)
- **Go Version**: Requires Go 1.25.4+ (specified in go.mod)
- **Tags**: Use `fuse3` tag for testing/building (default), `fuse2` for legacy systems

## Testing Infrastructure

- **Unit Tests**: Use `--tags=unittest,fuse3` to run unit tests
- **E2E Tests**: Located in `test/e2e_tests/` - require Azure Storage credentials
- **Mount Tests**: `test/mount_test/` - comprehensive filesystem testing
- **Performance Tests**: `test/scripts/` - benchmarking and stress testing
- **Test Timeout**: Mount tests can take up to 120 minutes - NEVER CANCEL

## Key Components and Architecture

- **cmd/**: CLI commands and main entry points
- **component/**: Core components (libfuse, azstorage, caching)
- **common/**: Shared utilities, configuration, logging
- **internal/**: Internal APIs and pipeline management
- **test/**: All testing code and scripts
- **tools/health-monitor/**: cloudfuse monitoring tool

## Configuration

- **Sample Configs**:
- `sampleFileCacheConfig.yaml` - file-based caching
- `sampleBlockCacheConfig.yaml` - block-based caching
- `setup/baseConfig.yaml` - complete configuration options
- **Config Generation**: Use `cloudfuse gen-config` to auto-generate configs
- **Authentication**: Supports account keys, SAS tokens, MSI, SPN, Azure CLI

## Important Notes

- **Mount Operations**: Require Azure Storage credentials - will fail in testing without them
- **Permissions**: May require sudo for actual mount operations
- **FUSE Configuration**: `/etc/fuse.conf` may need `user_allow_other` enabled for multi-user access
- **Dependencies**: Requires libfuse3-dev for building, fuse3 for runtime
- **Platform**: Linux only (Ubuntu 20+, other distros listed in wiki)

## Common Pre-commit Validation

Always run these before committing changes:

```bash
# Format check
gofmt -s -l -d .

# Build verification
./build.sh

# Core unit tests
go test -v -timeout=10m ./internal/... ./common/... --tags=unittest,fuse3

# Linting
$(go env GOPATH)/bin/golangci-lint run --tests=false --build-tags fuse3 --max-issues-per-linter=0

# Binary functionality
./cloudfuse --version
./cloudfuse gen-config --tmp-path=/tmp/test --o /tmp/test-config.yaml
```

## CI/CD Integration

- **Build Pipeline**: Github Actions
- **Testing**: Automated on Ubuntu 24, both x86 and ARM64
- **Performance**: Dedicated benchmark workflows
- **Security**: CodeQL analysis and dependency scanning
- **Release**: Automated package building and distribution

## Troubleshooting

- **Build Failures**: Check Go version, ensure libfuse3-dev installed
- **Test Failures**: Network/credential tests expected to fail without Azure setup
- **Mount Failures**: Verify FUSE permissions and Azure credentials
- **Performance**: Use health monitor (`cfusemon`) for runtime diagnostics

## Key Files to Monitor

When making changes, always check these files for consistency:
- `go.mod` - dependency versions
- `main.go` - entry point
- `build.sh` - build configuration
- `cmd/mount.go` - core mount functionality
- Configuration templates in `setup/` and root directory
2 changes: 2 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ linters:
- third_party$
- builtin$
- examples$
- component/azstorage/config.go
- common/version.go
rules:
- path: component/libfuse/libfuse2_handler_test_wrapper.go
text: "(\\w) (\\w+|\\(\\*\\w+\\)\\.\\w+) is unused"
Expand Down
27 changes: 6 additions & 21 deletions cmd/mount.go
Original file line number Diff line number Diff line change
Expand Up @@ -460,7 +460,6 @@ var mountCmd = &cobra.Command{
Level: logLevel,
TimeTracker: options.Logging.TimeTracker,
})

if err != nil {
return fmt.Errorf("failed to initialize logger [%s]", err.Error())
}
Expand Down Expand Up @@ -528,18 +527,14 @@ var mountCmd = &cobra.Command{
"mount : failed to initialize new pipeline :: To authenticate using MSI with object-ID, ensure Azure CLI is installed. Alternatively, use app/client ID or resource ID for authentication. [%v]",
err,
)
return Destroy(
fmt.Sprintf(
"failed to initialize new pipeline :: To authenticate using MSI with object-ID, ensure Azure CLI is installed. Alternatively, use app/client ID or resource ID for authentication. [%s]",
err.Error(),
),
return fmt.Errorf(
"failed to initialize new pipeline :: To authenticate using MSI with object-ID, ensure Azure CLI is installed. Alternatively, use app/client ID or resource ID for authentication. [%s]",
err.Error(),
)
}

log.Err("mount : failed to initialize new pipeline [%v]", err)
return Destroy(
fmt.Sprintf("mount : failed to initialize new pipeline [%s]", err.Error()),
)
return fmt.Errorf("mount : failed to initialize new pipeline [%s]", err.Error())
}

// Dry run ends here
Expand Down Expand Up @@ -668,16 +663,15 @@ func runPipeline(pipeline *internal.Pipeline, ctx context.Context) error {
err := pipeline.Start(ctx)
if err != nil {
log.Err("mount: error unable to start pipeline [%s]", err.Error())
return Destroy(fmt.Sprintf("unable to start pipeline [%s]", err.Error()))
return fmt.Errorf("unable to start pipeline [%s]", err.Error())
}

err = pipeline.Stop()
if err != nil {
log.Err("mount: error unable to stop pipeline [%s]", err.Error())
return Destroy(fmt.Sprintf("unable to stop pipeline [%s]", err.Error()))
return fmt.Errorf("unable to stop pipeline [%s]", err.Error())
}

_ = log.Destroy()
return nil
}

Expand Down Expand Up @@ -928,12 +922,3 @@ func init() {
config.AttachFlagCompletions(mountCmd)
config.AddConfigChangeEventListener(config.ConfigChangeEventHandlerFunc(OnConfigChange))
}

func Destroy(message string) error {
_ = log.Destroy()
if message != "" {
return fmt.Errorf("%s", message)
}

return nil
}
18 changes: 15 additions & 3 deletions cmd/mount_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import (
"strings"
"time"

"github.com/Seagate/cloudfuse/common"
"github.com/Seagate/cloudfuse/common/config"
"github.com/Seagate/cloudfuse/common/log"
"github.com/Seagate/cloudfuse/internal"
Expand All @@ -63,6 +64,11 @@ func createDaemon(
umask int,
fname string,
) error {
pid := os.Getpid()
traceFile := fmt.Sprintf("%s.%d.trace", strings.ReplaceAll(options.MountPath, "/", "_"), pid)
// we link this file to stderr of child process in daemon mode
traceFilePath := filepath.Join(os.ExpandEnv(common.DefaultWorkDir), traceFile)

dmnCtx := &daemon.Context{
PidFileName: pidFileName,
PidFilePerm: pidFilePerm,
Expand Down Expand Up @@ -92,7 +98,7 @@ retry:
rmErr := os.Remove(pidFileName)
if rmErr != nil {
log.Err("mount : auto cleanup failed [%v]", rmErr.Error())
return Destroy(fmt.Sprintf("failed to daemonize application [%s]", err.Error()))
return fmt.Errorf("failed to daemonize application [%s]", err.Error())
}
goto retry
}
Expand Down Expand Up @@ -151,9 +157,15 @@ retry:
buff, err := os.ReadFile(dmnCtx.LogFileName)
if err != nil {
log.Err("mount: failed to read child [%v] failure logs [%s]", child.Pid, err.Error())
return Destroy(fmt.Sprintf("failed to mount, please check logs [%s]", err.Error()))
err = fmt.Errorf("failed to mount, please check logs [%s]", err.Error())
} else {
return Destroy(string(buff))
err = fmt.Errorf("%s", string(buff))
}

// Safe to delete the temp file.
rmErr := os.Remove(traceFilePath)
if rmErr != nil {
log.Err("mount : Failed to delete temp file: %s[%v]", traceFilePath, err)
}

case <-time.After(options.WaitForMount):
Expand Down
7 changes: 6 additions & 1 deletion common/log/logger.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
package log

import (
"fmt"
"log"
"time"

Expand Down Expand Up @@ -136,8 +137,12 @@ func SetLogLevel(lvl common.LogLevel) {
}

// Destroy : DeInitialize the logging library
// This should only be called from the main function.
func Destroy() error {
return logObj.Destroy()
if logObj != nil {
return logObj.Destroy()
}
return fmt.Errorf("Logger is not initialized")
}

// ------------------ Public methods for logging events ------------------
Expand Down
Loading
Loading